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

C语言scanf读取输入时i、n字符被异常存为换行符问题咨询

问题描述
  • 预期功能:实现用户输入end时程序自动终止的逻辑
  • 代码设计逻辑:读取输入时,数值存入firstArray.content[index],非数字字符存入end[whileCounter]
  • 异常表现:绝大多数场景逻辑运行正常,仅当end接收字符i或n时触发异常:对应位置会被存入换行符'\n',而非用户实际输入的i或n字符
  • 复现特征:输入4lol时程序运行完全符合预期,但输入4null时,字符数组中仅存入ull,开头的n字符丢失
  • 已排除项:该问题不是scanf常见的尾随换行符残留问题,因为异常仅在输入特定字符时触发

可复现异常的完整代码如下:

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

struct HeapArrRealNums {
    size_t size;
    size_t nextIndex;
    size_t currentIndex;
    double* content;
};

int main() {

    struct HeapArrRealNums firstArray = { 0 };
    firstArray.size = 4;
    firstArray.nextIndex = 1;
    firstArray.currentIndex = 0;
    firstArray.content = malloc(firstArray.size * sizeof(double));

    #define NOT_A_NUMBER  0
    int scanCheck;
    size_t index = firstArray.currentIndex;
    char end[6] = { 'c' };
    size_t whileCounter = 0;

    while ((scanCheck = scanf("%lf", &firstArray.content[index])) != 1) {
        if (scanCheck == EOF) {
            printf("\n----EOF. Program terminated----");
            firstArray.currentIndex = index;
            //return true;
        }
        if (scanCheck == NOT_A_NUMBER) {

            (void)scanf("%c", &end[whileCounter]);
            whileCounter++;
            printf("-%s-", end);
            //continue;
        }
    }
}
异常根因

问题出在对scanf("%lf")匹配规则的认知偏差:%lf读取双精度浮点数时,并非遇到非数字字符就立刻停止、完全不消费缓冲区内容。
除了普通数字、小数点、正负号、科学计数法的e/E之外,%lf还会尝试匹配C标准定义的特殊浮点值字面量:

  • 以n开头的nan/nan(...)(表示非数值)
  • 以i开头的inf/infinity(表示无穷大)

当输入流中出现n或i开头的内容时,scanf会先将开头的n/i从输入缓冲区读走,继续向后读取字符尝试拼接成完整的特殊浮点值;如果后续字符不符合nan/inf的格式要求,scanf会判定匹配失败、返回0,但按照C语言标准,scanf匹配失败时最多只会向输入流回推1个字符——也就是最后读到的那个不匹配的字符,之前已经读走的首字符n/i会被直接丢弃,不会放回缓冲区。

这完全对应观察到的所有异常现象:

  • 输入i后按回车:scanf读走i,读到后续的换行符时发现无法凑成合法的inf格式,匹配失败,仅把换行符推回缓冲区,后续scanf("%c")读到的就是这个换行符,表现为i的位置被存入了'\n'
  • 输入4null时,开头的数字4会被正常解析为浮点数存入数组,缓冲区剩余null,scanf读走首字符n,读到后续的u时发现无法凑成合法的nan格式,匹配失败,仅把u推回缓冲区,后续逐字符读取时只能读到u、l、l,开头的n直接丢失
  • 输入4lol时,开头的数字4被正常解析后,缓冲区剩余lol,scanf读到第一个字符l就发现完全不可能匹配浮点数格式,会直接把l推回缓冲区,不会消费任何字符,因此逐字符读取逻辑完全正常,这也是其他场景看起来运行符合预期的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:19:52