You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言凯撒密码代码中循环自增的异常行为疑问

凯撒密码实现中的循环索引与字符串终止问题

先看你给出的代码:

char arr[SIZE];
fgets(arr, SIZE, stdin);
char brr[SIZE];
int i;
for(i=0; arr[i] != '\0'; i++){
    if(arr[i] != ' ') brr[i] = (arr[i] + shift - 'a')%26 + 'a';
    else brr[i] = ' ';
}
brr[i-1] = '\0';

你的疑惑点在于:明明觉得应该用brr[i] = '\0',但实际必须用i-1,而且循环结束后i会自增一次——这本质是fgets读取的字符串包含换行符,再加上for循环的执行逻辑导致的。

问题拆解

  1. fgets的行为:当你输入car并按下回车时,fgets会把'c'、'a'、'r'、'\n'(换行符)都读入arr数组,最后自动追加'\0'作为字符串终止符。此时arr的内容是:['c','a','r','\n','\0']。
  2. for循环的执行流程:for循环是先判断条件arr[i] != '\0',满足就执行循环体,然后执行i++。所以整个循环的执行过程是:
    • i=0:arr[0]='c'≠'\0',处理字符,i变成1
    • i=1:arr[1]='a'≠'\0',处理字符,i变成2
    • i=2:arr[2]='r'≠'\0',处理字符,i变成3
    • i=3:arr[3]='\n'≠'\0',处理字符(因为'\n'不是空格,会被移位),i变成4
    • i=4:arr[4]='\0',条件不满足,退出循环
      此时i的值是4,你用brr[i-1] = '\0'其实是把brr[3](也就是处理后的换行符)覆盖成终止符,但这不是正确的处理方式——你本来就不该处理换行符。

解决方案

核心是先去掉fgets读入的换行符,让循环只处理用户输入的有效文本:

char arr[SIZE];
fgets(arr, SIZE, stdin);
// 移除换行符
size_t len = strlen(arr);
if (len > 0 && arr[len - 1] == '\n') {
    arr[len - 1] = '\0';
}

char brr[SIZE];
int i;
for(i=0; arr[i] != '\0'; i++){
    if(arr[i] != ' ') brr[i] = (arr[i] + shift - 'a')%26 + 'a';
    else brr[i] = ' ';
}
// 现在i的值等于有效字符的长度,直接设置终止符
brr[i] = '\0';

这样处理后,输入car回车,arr的内容会变成['c','a','r','\0'],循环到i=3时,arr[3]是'\0',条件不满足,退出循环,此时i=3,brr[i] = '\0'正好把终止符放在处理后的字符后面,得到正确的'ect'。

另外你提到while循环也有同样问题,道理是一样的——只要arr里包含换行符,循环就会遍历到它,最后导致i的位置超出有效字符范围。

内容的提问来源于stack exchange,提问作者ahmet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:45:29