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

关于K&R习题1-12代码修改后失效的技术疑问

关于K&R习题1-12代码修改后失效的技术疑问

嘿,这个问题其实是你在修改代码时踩了一个很经典的坑——重复调用getchar()带来的副作用,咱们慢慢拆解清楚:

首先得说你最初的代码为什么能正常工作:
你在外层循环读到一个字符ch后,先判断它是不是非空白字符,如果是,就进入内层循环——先输出当前的ch,然后继续读下一个字符,直到遇到空白或EOF再换行。整个过程里每个输入字符只会被读取一次,逻辑连贯,不会漏掉任何字符。

但修改后的代码就出大问题了!你在内层while的条件里连续写了4次(ch = getchar()),这意味着每判断一个条件分支,都会读取一个新的输入字符,而且每次赋值都会覆盖掉ch原来的值。举个实际的例子,假设输入是hello world:

  1. 外层循环读到'h',因为不是空白,进入if块;
  2. 进入内层while的条件判断:
    • 第一个条件(ch = getchar()) != ' ':读取'e'赋值给ch,判断不是空格,继续;
    • 第二个条件(ch = getchar()) != '\n':读取'l'覆盖ch,判断不是换行,继续;
    • 第三个条件(ch = getchar()) != '\t':读取'l'覆盖ch,判断不是制表符,继续;
    • 第四个条件(ch = getchar()) != EOF:读取'o'覆盖ch,判断不是EOF,进入循环体输出'o';
  3. 再次进入内层while的条件判断,第一个动作是读入空格,赋值给ch,判断空格 != ' '不成立,直接退出内层循环,输出换行。

你看,原本的"hello"里的h、e、l、l都被白白读取却没有输出,只留下了o,后续的字符也被乱序消耗,完全破坏了逐个处理字符的逻辑。

核心问题就是:在条件表达式里多次调用有副作用的函数(比如getchar(),每次调用都会消耗一个输入字符),会让逻辑彻底偏离预期。你本来是想判断当前的ch是不是空白/EOF,但实际上每次判断都在刷新ch的值,大部分读取的字符都没被处理就丢了。

如果想遵循K&R里“把赋值写在条件里”的建议,正确的做法是只做一次赋值,然后用这个值去判断所有条件,同时还要注意不要漏掉外层已经读到的那个非空白字符。修正后的代码应该是这样:

#include <stdio.h>

int main(void) {
    int ch; // 这里用int就够了,EOF是int类型,long没必要
    while ((ch = getchar()) != EOF) {
        if (ch != ' ' && ch != '\n' && ch != '\t') {
            putchar(ch); // 先输出外层读到的非空白字符
            // 继续读取并输出后续的非空白字符
            while ((ch = getchar()) != ' ' && ch != '\n' && ch != '\t' && ch != EOF) {
                putchar(ch);
            }
            putchar('\n');
        }
    }
    return 0;
}

这样既符合K&R的写法建议,又能保持和你最初代码一致的正确逻辑。

备注:内容来源于stack exchange,提问作者Anadelta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 12:54:38