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

scanf读取管道输入首值不符合预期:无法读取为整数

问题分析与解决

你的核心问题大概率是第一个程序(prog1)的输出包含终端控制字符(比如颜色代码),这些字符在终端中会被解析为格式控制,不会显示,但通过管道传递给prog2时,会被当作普通输入数据,导致scanf("%d")无法匹配第一个字段(因为字段开头不是纯数字),而%s会把控制字符和数字一起读成字符串。

验证方法

先确认prog1的输出是否有隐藏字符:

./prog1 | cat -A

如果输出中出现类似^[[32m(ESC开头的序列),就说明存在终端控制字符。

解决方案

1. 修复prog1的输出逻辑

让prog1只在输出到终端时才输出控制字符(比如颜色),管道输出时输出纯文本:

#include <unistd.h>  // 引入isatty函数

// 替换原printf代码
int is_term = isatty(STDOUT_FILENO);
if (is_term) {
    // 如果是终端,保留原有的带格式输出(比如颜色)
    printf("\033[32m%d  %zu.%-6zu  %d  %3d  %9d\033[0m\n", 
           1, event1.time.tv_sec, event1.time.tv_usec, 
           event1.type, event1.code, event1.value);
} else {
    // 管道输出时,只输出纯文本
    printf("%d  %zu.%-6zu  %d  %3d  %9d\n", 
           1, event1.time.tv_sec, event1.time.tv_usec, 
           event1.type, event1.code, event1.value);
}

2. 更可靠的prog2解析方式

不管prog1的输出有没有问题,用fgets读取整行再解析,比直接用scanf更稳定,还能避免输入缓冲的问题:

#include <stdio.h>

int main() {
    char line[256];
    int event_num, type, code, value;
    long sec, usec;  // 用整数存储秒和微秒,避免double精度问题

    while (fgets(line, sizeof(line), stdin) != NULL) {
        // 解析整行数据,拆秒和微秒为整数
        int ret = sscanf(line, "%d  %ld.%ld  %d  %d  %d", 
                        &event_num, &sec, &usec, &type, &code, &value);
        if (ret == 6) {
            double time = sec + usec / 1000000.0;
            // 正常处理数据,比如打印验证
            printf("Parsed: %d, %.6f, %d, %d, %d\n", 
                   event_num, time, type, code, value);
        } else {
            fprintf(stderr, "Invalid input line: %s", line);
        }
    }
    return 0;
}

额外说明

  • 你之前尝试的%[^0-9]%d格式不适用,因为如果第一个字符就是数字,%[^0-9]会匹配失败,导致整个scanf返回0。
  • 直接读取double类型的时间可能存在精度损失,拆分秒和微秒为整数再计算更准确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:13:36