CS50 Substitution作业:tolower()在重复字符校验代码中失效原因求解
问题根源
你的条件判断语句存在括号位置的语法错误,不管使用toupper还是tolower,原有逻辑本身就是错误的,之前能正确识别部分重复字符只是巧合。
你写的判断代码:
if (toupper(argv[1][j] == toupper(argv[1][k])))
实际执行逻辑是:
- 先计算括号内的
argv[1][j] == toupper(argv[1][k]),这个比较运算的结果是布尔值:相等为1,不相等为0 - 再把得到的
1或0传入toupper函数执行,toupper(1)和toupper(0)的返回值还是非0和0,刚好和布尔结果一致,所以你误以为这段代码是对的
但这个逻辑有两个致命问题:
- 无法识别大小写不同的重复字符,比如
a和A,比较a == toupper(A)也就是a == A结果为0,会被判定为不重复 - 你改成
tolower版本后逻辑完全一致,之所以突然失效,大概率是你测试时用了大小写混合的重复密钥,刚好触发了原有逻辑的漏洞
修复方法
把括号位置调整为两个字符分别转大小写后再比较即可:
// 正确写法1:统一转大写后比较 if (toupper(argv[1][j]) == toupper(argv[1][k])) // 正确写法2:统一转小写后比较 if (tolower(argv[1][j]) == tolower(argv[1][k]))
可选优化
你当前用双重循环判断重复的时间复杂度是O(n²),对于固定长度26的密钥虽然影响不大,但可以用更高效的方案:用一个长度26的布尔数组记录字符是否出现过,遍历一次就能完成校验,时间复杂度O(n):
bool existed[26] = {false}; for (int i = 0, n = strlen(argv[1]); i < n; i++) { int idx = toupper(argv[1][i]) - 'A'; if (existed[idx]) { count_repeated_char++; break; } existed[idx] = true; }
内容的提问来源于stack exchange,提问作者ErmaloJr
相关产品推荐
相关产品推荐

