CS50替换密码程序修改else分支后失效的原因咨询
替换密码程序的逻辑错误分析
问题描述
我正在编写一个替换密码程序,采用CS50的语法规范。当代码保留else分支时,程序运行完全正常;但如果将else分支替换为仅匹配'!'、'.'、','、空格的else if分支后,程序只会复制原输入字符串。请问这是什么原因?
原代码片段
#include <cs50.h> #include <stdio.h> #include <string.h> #include <ctype.h> int main(void) { string key_upper = "YTNSHKVEFXRBAUQZCLWDMIPGJO"; string key_lower = "ytnshkvefxrbauqzclwdmipgjo"; string alphabet_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string alphabet_lower = "abcdefghijklmnopqrstuvwxyz"; string word = "Hello daniel, ! .."; char letter_switch[strlen(word)]; for (int i = 0; i < 26; i++) { for (int j = 0; j < strlen(word); j++) { if (word[j] == alphabet_upper[i]) { letter_switch[j] = key_upper[i]; } else if (alphabet_lower[i] == word[j]) { letter_switch[j] = key_lower[i]; } else { letter_switch[j] = word[j]; } } } for (int k = 0; k < strlen(word); k++) { printf("%c", letter_switch[k]); } printf("\n"); return 0; }
修改后的分支代码
else if (word[j] == '!' || word[j] == '.' || word[j] == ',' || word[j] == ' ') { letter_switch[j] = word[j]; }
原因分析
1. 循环顺序完全错误
你的代码当前是先遍历26个字母(i循环),再遍历输入字符串的每个字符(j循环),这会导致逻辑彻底混乱:
- 对于任意一个字母字符,比如
H,只有当i循环到对应索引(i=7)时,会被替换成密码字符;但后续的i循环(从8到25)会通过else分支把这个字符重新覆盖为原字符。 - 最终只有最后一个字母(
Z/z)的字符会保留替换结果,其他字母都会被改回原字符——你所谓的“原代码运行正常”其实是错觉,它根本没有正确执行替换。
正确的循环顺序应该是先遍历输入字符串的每个字符(j循环),再遍历26个字母找匹配(i循环),这样每个字符只会被处理一次:
for (int j = 0; j < strlen(word); j++) { // 默认保留原字符,无需单独处理标点空格 letter_switch[j] = word[j]; for (int i = 0; i < 26; i++) { if (word[j] == alphabet_upper[i]) { letter_switch[j] = key_upper[i]; break; // 找到匹配后跳出循环,避免无效遍历 } else if (word[j] == alphabet_lower[i]) { letter_switch[j] = key_lower[i]; break; } } }
2. 修改分支后的逻辑漏洞
当你把else换成仅匹配标点/空格的else if后,结合错误的循环顺序,会出现以下问题:
- 对于字母字符,当
i不是对应字母时,既不满足if/else if的匹配条件,也不属于标点/空格,因此letter_switch[j]不会被赋值。 - 后续的
i循环中,只有当i恰好对应该字母时才会替换,但之后的i循环又不会再修改它——但因为原循环顺序的问题,大部分字母会被后续循环的无操作保留为初始的随机值,而你看到的原字符串,其实是之前错误循环中else分支覆盖的结果残留。
内容的提问来源于stack exchange,提问作者Kalle
相关产品推荐
相关产品推荐

