C++读取文本文件生成密码时ispunct()抛出异常问题求解
问题排查与修复
崩溃根因
你遇到的ispunct位置抛异常是非法内存访问导致的,代码里存在两处明确的下标越界问题:
- 检查首字母外大写的循环
for (int i = b.length(); i; --i),std::string的有效下标范围是0 ~ 长度-1,直接访问b[b.length()]属于越界读,触发未定义行为,直接导致字符判断函数异常。 - 检查标点、数字的循环
for (int i = b.length() - 1; i; --i)终止条件为i非零,i=0时直接停止循环,漏掉了首字符的标点、数字校验。
其他逻辑错误
acceptWord的第一个参数string a是值传递,函数内的a = b不会修改外层变量,属于无效代码,冗余参数可以直接删掉。- main函数中
tokens是初始化的空vector,直接用tokens[i] = token赋值属于越界写,会触发崩溃,需要用push_back方法添加符合条件的单词。 rand()仅在程序启动时调用一次,所有密码组合都会使用同一个单词,不符合随机选4个单词的要求。- 输出20组密码的逻辑写在读取文件的while循环内,会每读取一个单词就输出20次,逻辑错位。
- 缺少
<cctype>头文件,ispunct/isdigit/isupper等字符处理函数属于该头文件,部分编译器未引入时会有未定义行为。 - 未初始化随机种子,每次程序运行生成的随机序列完全一致。
修复后代码
#include <iostream> #include <fstream> #include <vector> #include <cctype> #include <cstdlib> #include <ctime> using namespace std; bool acceptWord(const string& b) { // 单词长度至少4位 if (b.length() <= 3) { return false; } // 检查所有字符无标点、无数字 for (int i = 0; i < b.length(); ++i) { if (ispunct(b[i]) || isdigit(b[i])) { return false; } } // 首字母大写的情况下,剩余字母不能大写 if (isupper(b[0])) { for (int i = 1; i < b.length(); ++i) { if (isupper(b[i])) { return false; } } } return true; } int main() { srand(time(nullptr)); // 初始化随机种子 fstream file; string word, filename; vector<string> tokens; filename = "input.txt"; file.open(filename.c_str()); if (!file.is_open()) { cout << "File not found" << endl; exit(1); } // 读取所有符合条件的单词 while (file >> word) { if (acceptWord(word)) { tokens.push_back(word); } } file.close(); // 单词库不足的情况处理 if (tokens.size() < 4) { cout << "符合条件的单词数量不足,无法生成密码" << endl; return 1; } // 输出20组密码,每组4个随机单词 for (int i = 0; i < 20; ++i) { string w1 = tokens[rand() % tokens.size()]; string w2 = tokens[rand() % tokens.size()]; string w3 = tokens[rand() % tokens.size()]; string w4 = tokens[rand() % tokens.size()]; cout << w1 << " " << w2 << " " << w3 << " " << w4 << endl; } return 0; }
内容的提问来源于stack exchange,提问作者user17466917
相关产品推荐
相关产品推荐

