如何在C++中正确实现字符串数组的随机打乱操作?
问题原因
你写的random_shuffle(names->begin(), names->end());存在逻辑错误:
names是string类型的数组,数组名直接用->调用成员时,会自动退化为指向第一个数组元素的指针,等价于&names[0]- 所以你实际调用的是
names[0].begin()和names[0].end(),自然只会打乱第一个姓名字符串内部的字符顺序,不会打乱整个数组的元素顺序。
解决方法
- 给
random_shuffle传入整个数组的首尾迭代器,语法为std::begin(names)和std::end(names),也可以直接写names和names + 197(因为你的数组长度固定为197) - 额外修正你代码中读取文件的逻辑错误:你同时用了
getline和>>读文件,会出现读入内容重复、空行、甚至越界的问题,直接用>>循环读即可,同时要控制读入数量不超过数组长度 - 建议加上随机数种子,否则每次运行程序打乱的顺序都是固定的;如果用C++11及以上版本,更推荐用已标准化的
std::shuffle替代已被弃用的random_shuffle
修正后的完整代码
#include <iostream> #include <fstream> #include <string> #include <algorithm> #include <ctime> using namespace std; int main() { srand((unsigned int)time(nullptr)); // 设置随机种子 ifstream readName("names.txt"); string names[197]; int i = 0; // 修正读文件逻辑,控制不越界 while (i < 197 && readName >> names[i]) { i++; } readName.close(); // 打乱整个数组的元素,i是实际读入的姓名数量,只打乱有效元素 random_shuffle(names, names + i); // 只输出实际读入的有效姓名 for (int j = 0; j < i; j++) { cout << names[j] << endl; } return 0; }
补充说明
如果使用C++11及以上版本,更推荐用std::shuffle实现,效果更稳定,写法如下:
// 引入额外头文件 #include <random> // 替换random_shuffle行 std::random_device rd; std::mt19937 g(rd()); std::shuffle(names, names + i, g);
内容的提问来源于stack exchange,提问作者Tim's
相关产品推荐
相关产品推荐

