You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:23:13