C++函数内无法交换vector元素,求解决单词重排索引同步问题
问题:随机打乱单词字母并同步交换索引,直至恢复原顺序
我要写一个程序,输入一个单词后随机打乱字母,直到恢复初始顺序。输出要在单词前打印字母的索引,示例如下:
[1] 0123 Test
[2] 3201 tsTe
[3] 2103 seTt
...
我定义了字符串signchain存储初始输入,还有一个包含0到n(单词长度)的vector<uint16_t> indexes。现在字母随机重排功能已经实现,但没法同步交换vector里的索引。
各函数预期功能:
mix_cycle:从初始化signchain和indexes开始,直到恢复原单词的完整循环form_new_word_by_indexes:重排单词字母,交换次数和对象随机,索引要随字母交换同步更新getRandomNumber:生成指定区间内的随机数
我的问题是:怎么让索引跟着字母的交换同步交换?试过std::swap但没成功,附上代码:
// 生成指定区间内的随机数 static uint16_t getRandomNumber(uint16_t min, uint16_t max) { uint16_t rand_num = rand() % (max - min) + min; //生成指定范围内的数 return rand_num; } // 根据原单词和索引生成新单词 std::string form_new_word_by_indexes(const std::string& initial_word, const std::vector<uint16_t>& indexes) { int min = 0; int max = initial_word.length(); string new_word = initial_word; char element_memory; uint16_t index_1, index_2; for (int i = 0; i <= getRandomNumber(min, max); i++) //执行随机次数的交换 { while (true) { //确保不与自身交换 index_1 = getRandomNumber(min, max); index_2 = getRandomNumber(min, max); if (index_1 != index_2) { break; } } element_memory = new_word[index_1]; new_word[index_1] = new_word[index_2]; new_word[index_2] = element_memory; swap(indexes[index_1], indexes[index_2]); } return new_word; } // 主循环:随机打乱单词直到恢复原顺序 void mix_cycle(const std::string& initial_word) { // 单词长度 int am_letters = initial_word.length(); // 存储当前单词 string signchain = initial_word; // 初始化索引数组:0,1,2... vector<uint16_t> index_list; for (int i = 0; i < am_letters; i++) { index_list.push_back(i); } int counter = 0; while (true) { counter += 1; cout << "[" << counter << "] "; signchain = form_new_word_by_indexes(signchain,index_list); for (int i = 0; i < index_list.size(); i++) { cout << index_list[i]; } cout << " "; for (int i = 0; i < am_letters; i++) { cout << signchain[i]; } cout << "\n"; } }
问题分析与修复方案
核心问题:参数权限限制
form_new_word_by_indexes的第二个参数是const std::vector<uint16_t>& indexes,const修饰导致无法修改容器内的元素,这就是std::swap失效的根本原因。此外还有几处逻辑问题需要修正:
1. 修改参数权限
把form_new_word_by_indexes的第二个参数改为非const引用,允许修改索引数组:
std::string form_new_word_by_indexes(const std::string& initial_word, std::vector<uint16_t>& indexes)
2. 修正随机数越界问题
原代码中max传入单词长度,但数组索引范围是0~length-1,会导致生成的随机数超出索引范围。调整随机数生成逻辑:
static uint16_t getRandomNumber(uint16_t min, uint16_t max) { // 生成[min, max]闭区间的随机数,避免越界 return min + rand() % (max - min + 1); }
调用时将max改为initial_word.length() - 1。
3. 同步交换逻辑
交换字母的同时,直接调用std::swap交换对应位置的索引即可,修正后的form_new_word_by_indexes:
std::string form_new_word_by_indexes(const std::string& initial_word, std::vector<uint16_t>& indexes) { uint16_t min = 0; uint16_t max = initial_word.length() - 1; std::string new_word = initial_word; uint16_t index_1, index_2; // 随机交换1到max+1次,避免0次交换 int swap_count = getRandomNumber(1, max + 1); for (int i = 0; i < swap_count; i++) { do { index_1 = getRandomNumber(min, max); index_2 = getRandomNumber(min, max); } while (index_1 == index_2); // 交换字母 std::swap(new_word[index_1], new_word[index_2]); // 同步交换索引 std::swap(indexes[index_1], indexes[index_2]); } return new_word; }
4. 增加循环终止条件
原mix_cycle是死循环,需判断当前单词是否等于初始单词,满足时退出:
void mix_cycle(const std::string& initial_word) { int am_letters = initial_word.length(); std::string signchain = initial_word; std::vector<uint16_t> index_list; for (int i = 0; i < am_letters; i++) { index_list.push_back(i); } int counter = 0; // 初始化随机种子,保证每次运行结果不同 srand(time(nullptr)); while (true) { counter += 1; signchain = form_new_word_by_indexes(signchain, index_list); // 打印当前状态 std::cout << "[" << counter << "] "; for (uint16_t idx : index_list) { std::cout << idx; } std::cout << " " << signchain << "\n"; // 恢复原单词时退出循环 if (signchain == initial_word) { std::cout << "已恢复初始单词,循环结束。" << std::endl; break; } } }
额外注意事项
- 必须包含必要头文件:
#include <iostream>,#include <string>,#include <vector>,#include <cstdlib>,#include <ctime> srand(time(nullptr))只需调用一次,放在主循环前即可,避免重复初始化导致随机数重复
内容的提问来源于stack exchange,提问作者VRK
相关产品推荐
相关产品推荐

