基于字符串键的哈希表文件逐行哈希遇下标越界问题求助
解决哈希函数下标越界的问题
嘿,我来帮你搞定这个下标越界的bug!咱们一步步拆解问题,找到根源再解决:
问题根源分析
你遇到的下标越界,大概率不是因为传入的字符串“应该”是16位,而是实际运行时拿到的字符串长度根本不够14位。仔细看你的代码,有几个明显的坑:
非法变量名导致读取错误
你代码里写的account number是带空格的,这在C++里是语法错误——编译器会把它当成两个变量account和number,根本没法正确存储读取到的账号字符串!这直接导致hashFunction拿到的是空或者无效的字符串,自然会下标越界。错误的文件循环逻辑
用while (!(myfile.eof()))来控制循环是常见的坑:eof()只会在读取失败后才会置位,这意味着最后一行会被重复读取一次,或者当文件结尾有空行时,会读取到空字符串,此时key长度为0,取key[14]必然越界。硬编码下标太危险
就算预期账号是16位,也不能直接写key[14]——万一文件里有格式错误的行(比如账号长度不足、空行),直接硬编码下标就会触发越界。
具体修复方案
1. 修正变量名,确保合法
把带空格的变量名改成合法的,比如account_number:
string input, pass, account_number;
2. 改进文件读取逻辑
用getline的返回值作为循环条件,同时检查文件是否成功打开:
void HashTable::read_from_file() { fstream myfile; string pass, account_number; myfile.open(address1.c_str(), ios::in); // 先检查文件是否成功打开 if (!myfile.is_open()) { cerr << "Failed to open file!" << endl; return; } // 用getline的返回值控制循环,避免读取无效数据 while (getline(myfile, account_number, ',') && getline(myfile, pass)) { // 先校验账号长度,跳过无效数据 if (account_number.size() != 16) { cerr << "Skipping invalid account: " << account_number << endl; continue; } int hashValue = hashFunction(account_number); // 这里记得把数据存入哈希表,比如: // insert(account_number, pass, hashValue); } myfile.close(); }
3. 重构哈希函数,避免硬编码下标
动态获取最后一个字符,同时增加空字符串的判断:
int HashTable::hashFunction(string key) { // 先处理空字符串的情况 if (key.empty()) { cerr << "Empty key passed to hash function!" << endl; return 0; // 或者根据需求抛出异常 } // 用back()获取最后一个字符,比key[key.size()-1]更直观 char last_char = key.back(); // 用'0'代替48,可读性更好 int ila = last_char - '0'; return ila % hashGroups; }
额外建议
- 每次读取数据后都做长度校验,可以避免很多格式错误导致的崩溃;
- 可以在哈希函数里加入断言,方便调试:
assert(!key.empty() && key.size() == 16);(记得包含<cassert>头文件); - 如果账号可能包含非数字字符,还要加一个判断,确保最后一个字符是数字,避免转换出错。
内容的提问来源于stack exchange,提问作者Soheil_mtr
相关产品推荐
相关产品推荐

