C++循环生成随机字符串报string subscript out of range错误
错误根因
抛出下标越界错误的直接原因是:对空的std::string对象直接使用下标运算符赋值,属于非法越界访问。
具体细节:
string* list = new string[7];创建的7个std::string实例都是默认构造的空字符串,初始长度为0。和C风格字符数组不同,std::string的[]运算符只能访问字符串长度范围内的已存在位置,不会在你写下标时自动扩容,因此哪怕你访问list[i][0](第一个字符位置),都已经超出了空串的合法下标范围,直接触发越界检查抛出异常。- 代码中
list[i][5] = '\0';是多余的错误操作:std::string内部独立维护长度属性,不需要像C风格字符串那样靠末尾的\0标记结束位置,这行本身也属于越界写入。 - 额外逻辑瑕疵(不触发越界但不符合生成随机字母的预期):
rand() % 20 + 96生成的ASCII范围是96(反引号)到115(小写s),无法覆盖全部26个小写英文字母,要生成a-z的随机字符应该使用rand()%26 + 'a'。另外代码中缺少随机数种子初始化,不添加srand(time(nullptr))`的话每次运行生成的字符串会完全一致。
修正代码
可以通过提前给字符串分配长度、或者用追加接口的方式避免越界,参考实现:
#include<iostream> #include<string> // C++ std::string对应的头文件,原代码引入的string.h是C风格字符串处理头文件 #include<cstdlib> #include<ctime> using namespace std; void generate(string*, int); int main() { srand((unsigned int)time(nullptr)); // 初始化随机数种子 string* list = new string[7]; generate(list, 7); // 测试打印结果 for(int i = 0; i < 7; i++){ cout << list[i] << endl; } delete[] list; // 释放堆内存避免泄漏 return 0; } void generate(string* list, int a) { for (int i = 0; i < a; i++) { list[i].resize(5); // 预先分配5个字符的空间,此时下标0~4为合法可写位置 for (int j = 0; j < 5; j++) { list[i][j] = rand() % 26 + 'a'; } } }
如果不想手动预分配长度,也可以用push_back接口逐字符追加,该接口会自动扩容,不会出现越界:
void generate(string* list, int a) { for (int i = 0; i < a; i++) { for (int j = 0; j < 5; j++) { list[i].push_back(rand() % 26 + 'a'); } } }
内容的提问来源于stack exchange,提问作者Huuulk99
相关产品推荐
相关产品推荐

