【问题标题】:scanf with %n giving wrong output带有 %n 的 scanf 给出错误的输出
【发布时间】:2016-10-25 12:17:20
【问题描述】:

我正在读取带有scanf 的整数,同时检查scanf 读取的位数,格式为%n,第一个输出始终正确,但之后输出增加了一个。即scanf 读取最后一个"\n" 为第二个scanf

我知道scanfchar 的这种问题,即scanf("%c",&cval) ---> 到scanf(" %c",&cval) 留下一些空间以避免scanf 读取行尾。但是整数是什么?

我已经在这里看到了一些问题Link here 并且他们似乎都认为scanf()"retarted" 并且应该始终使用 fget() .. 真的是这样吗?在项目中避免它是否很好?我的意思是消除所有此类错误,有没有办法防止这种情况发生。 我必须为此使用fget(),还是有办法在scanf() 中解决这个问题。欢迎所有 cmets,感谢您的宝贵时间。我只是想知道有没有办法修复它,我知道如何使用 %n。

#include <stdio.h>
int main(void) {


    int i =0 ,byte_count = 0,val;

    printf("Enter a number: ");

    scanf("%d%n",&val,&byte_count);
    while (i < 3){
        printf("byte count is: %d\n",byte_count);


        scanf("%d%n",&val,&byte_count);
        i++;
    }

    return 0;
}

【问题讨论】:

  • @J.Piquard 我没有说我不知道​​“%n”代表什么,当然也不是重复的。我知道 %n 做了什么。
  • 首先你可以检查scanf()的返回值是否等于2。
  • \n3049 :一个换行符 + 4 个数字 = 5。
  • @J.Piquard %n 不计入输入元素。

标签: c scanf


【解决方案1】:

第一个输出总是正确的,但之后输出又增加了一个。

后续扫描中n 的值比预期大一,因为它们扫描的是前一个条目的尾随'\n'@BLUEPIXY

\n3876  --> 5 characters
not 
3876

如果"%d" 的扫描失败,还会在每个循环中重置n

int val = 0; // add initialization

while (i < 3){
    printf("byte count is: %d\n",byte_count);
    byte_count = 0; // add
    scanf("%d%n",&val,&byte_count);
    i++;
}

要消耗stdin 中的空白,请使用" "

while (i < 3){
    printf("byte count is: %d\n",byte_count);
    byte_count = 0;
    scanf(" "); scanf("%d%n",&val,&byte_count);
    i++;
}

【讨论】:

    【解决方案2】:

    %n 捕获所有由 scanf 处理的字符,包括前导空格。使用 %n 两次可以纠正这个问题。格式字符串跳过前导空格,然后获取字符的开始计数。然后扫描整数,最后捕获字符总数。计数的差异是整数中的字符。
    始终检查 scanf 的返回,因为输入流可能需要清理。

        int begin = 0;
        int end = 0;
        int val = 0;
        int clean = 0;
        int result = 0;
    
        do {
            if ( ( result = scanf(" %n%d%n",&begin,&val,&endn)) != 1) {// scan one int
                while ( ( clean = getchar ( )) != '\n') {//clean bad input
                    if ( clean == EOF) {
                        fprintf ( stderr, "problem reading input\n");
                        exit ( 1);
                    }
                }
            }
            else {//scanf success
                printf("byte count is: %d\n",end-begin);
            }
        } while ( result != 1);
    

    【讨论】:

      【解决方案3】:

      确实,您应该始终使用fgets() 加上sscanf()strtod()strtol() 等。不要费心试图让简单的scanf() 工作,它只是不如您的其他选项有效。

      【讨论】:

      • 能否请您详细说明为什么这些更好?尤其是 sscanf > scanf。
      • 这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review
      • @TobySpeight:你错了,问题的字面意思是“应该始终使用 fget()。真的是这样吗?在项目中避免使用它好不好?”我直接回答了这个问题。
      • 啊,对不起 - 我以为您有足够的经验来标记寻求意见的问题而不是回答它们。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-08
      • 2021-04-08
      • 1970-01-01
      • 2021-02-11
      • 2013-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多