C++成绩评级系统中switch适配字符串及带加减后缀成绩输出异常咨询
C++ 成绩评级系统问题修复
现有代码核心问题清单
- 自定义
string_hash方案不适配当前业务:原哈希函数对多字符成绩串(如A+)的计算结果,与单字符后缀(+/-)的哈希值完全不匹配,后续switch分支永远无法命中;同时原哈希的位移逻辑容易出现碰撞和溢出,不同字符串可能生成相同哈希值。 - 后缀判断的if条件语法错误:
if (atzime[1] == '-' || '+')中,||后的+是常量非0,等价于永远为真,哪怕输入只有单个字母(如A)也会进入分支,越界访问atzime[1]触发未定义行为。 - 逻辑顺序混乱:基础成绩分支提前输出结果,后续后缀计算完成后没有复用调整后的值,甚至会重复输出。
- 变量赋值未生效:计算完
pluss/minuss后,输出的仍是原始atzime_sk,没有把调整后的值赋值给输出变量。
针对成绩系统的简化修复方案
你当前的业务场景不需要对整个成绩字符串做switch,仅需判断首字母和后缀字符即可,完全可以去掉冗余的字符串哈希逻辑,修复后核心代码如下:
#include <iostream> #include <string> using std::cin; using std::cout; using std::string; int main() { cout << "Ievadiet atzimi ar burtiem (A, B, C, D, F) ==> "; string atzime; cin >> atzime; // 输入合法性校验 if (atzime.empty() || atzime.size() > 2) { cout << "Nederiga atzime!"; return 1; } char burts = atzime[0]; double atzime_sk; // 先计算基础成绩,不提前输出 switch(burts) { case 'A': atzime_sk = 4; break; case 'B': atzime_sk = 3; break; case 'C': atzime_sk = 2; break; case 'D': atzime_sk = 1; break; case 'F': atzime_sk = 0; break; default: cout << "Nederiga atzimes burts!"; return 1; } // 修正后缀判断逻辑:先校验长度,再判断字符 if (atzime.size() == 2) { char piedeva = atzime[1]; // F等级无+/-,单独处理边界 if (burts != 'F') { if (piedeva == '+') { atzime_sk += 0.3; } else if (piedeva == '-') { atzime_sk -= 0.3; } else { cout << "Nederiga piedeva!"; return 1; } } } // 统一输出最终成绩 cout << "Tava atzime ir ==> " << atzime_sk; return 0; }
如果仍需要实现字符串switch的可行哈希方案
如果你后续确实需要用switch匹配字符串类型,原自定义哈希需要替换为编译期可校验、低碰撞的实现(如FNV-1a哈希),示例如下:
// 编译期FNV-1a哈希,低碰撞率 constexpr long long string_hash(const char *s) { long long hash = 0xcbf29ce484222325; // FNV偏移基值 while (*s) { hash ^= static_cast<long long>(*s++); hash *= 0x100000001b3; // FNV质数 } return hash; } constexpr long long operator"" _sh(const char *s, size_t) { return string_hash(s); } // 用法示例(需匹配完整字符串,如"A+"_sh) switch (string_hash(atzime.c_str())) { case "A+"_sh: cout << "A+"; break; case "A-"_sh: cout << "A-"; break; // 其他成绩分支 }
注意:该方案仅适合已知少量固定字符串的场景,编译期可通过静态断言校验哈希碰撞,运行时仍需注意极端场景的冲突处理。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

