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

在C语言中使用fgetc(stdin)时如何正确检测Ctrl-D输入?

问题分析与解决

核心错误原因

你代码的关键问题在于错误地将fgetc的int类型返回值直接赋值给char类型的缓冲区元素,再与EOF比较:

  • fgetc返回int类型,目的是区分EOF(值为-1,属于int)和所有合法字符(unsigned char范围的0-255,提升为int后是0-255)。
  • 若直接把这个int值赋值给char数组元素:
    • 若系统默认char是无符号类型,EOF(-1)会被转换为0xFF(255),再提升为int后是255,与EOF(-1)不相等,循环会持续执行,最终导致缓冲区越界,触发I/O错误,ferror返回真,从而打印"error"。
    • 即使char是有符号类型,这种写法也会把EOF这个非字符值写入缓冲区,浪费空间且可能引发后续处理逻辑错误。

正确实现方式

应该先将fgetc的返回值存入int变量,判断是否为EOF后,再决定是否存入缓冲区:

#include <stdio.h>
#include <stdlib.h>

#define INIT_BUF_SIZE 100

int main() {
    int read_chars = 0;
    int c; // 用int存储fgetc的返回值,正确区分EOF与合法字符
    char *buf = malloc(INIT_BUF_SIZE * sizeof(char));
    if (!buf) {
        perror("malloc failed");
        return EXIT_FAILURE;
    }
    size_t buf_size = INIT_BUF_SIZE;

    while ((c = fgetc(stdin)) != EOF) {
        // 缓冲区扩容逻辑(示例)
        if (read_chars >= buf_size - 1) { // 留一个位置存字符串终止符
            buf_size *= 2;
            char *new_buf = realloc(buf, buf_size * sizeof(char));
            if (!new_buf) {
                perror("realloc failed");
                free(buf);
                return EXIT_FAILURE;
            }
            buf = new_buf;
        }
        // 遇到换行符终止读取(示例)
        if (c == '\n') {
            break;
        }
        buf[read_chars] = (char)c;
        read_chars++;
    }

    // 循环结束后判断终止原因
    if (feof(stdin)) {
        printf("eof\n");
        buf[read_chars] = '\0'; // 给缓冲区添加字符串终止符
        printf("读取内容: %s\n", buf);
    } else if (ferror(stdin)) {
        printf("error\n");
        perror("读取失败");
    }

    free(buf);
    return EXIT_SUCCESS;
}

关键要点

  • 用int类型变量存储fgetc的返回值,确保能正确区分EOF和合法字符。
  • 仅当返回值不是EOF时,才将其转换为char存入缓冲区。
  • 循环结束后,优先判断feof(stdin):为真则是正常EOF(比如按下Ctrl-D);ferror(stdin)为真时,才是真正的I/O错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:53:34