首页 > 解决方案 > 为什么从控制台读取字符串时,scanf 中的 %n 返回 0

问题描述

我试图编写一个程序,该程序从用户(控制台)获取一行,直到遇到逗号、句号或换行符,并告诉按照特定模式读取了多少个字符。

字符串被正确读取,但计数不准确。

#include <stdio.h>

int main()
{
    int n;
    char s[100];


    // The following line should read a string until (. or , or new-line in encountered) 
    // and %n should tell me the no of characters it read until that point
    scanf("%[^.,\n]s%n", s, &n);


    // The String in okay
    printf("%s\n", s);

    // But count of characters read is 0
    printf("%d\n",n);

    return 0;
}

标签: cstringscanf

解决方案


5个问题:

"s"in停止扫描,"%[^.,\n]s%n"因为之后无法's'读取%[^.,\n]%[^.,\n]会读完所有的's'。因此,后者"%n"从未发生过n,而后来打印的 a0是错误的代码-打印未初始化的代码n-这可能是任何代码int或陷阱。

扫描缺少宽度限制。在第 99 个字符之后发生了不好的事情。

使用,如果第一个字符是scanf("%[^.,\n]s%n", s, &n);,扫描将不保存任何内容。后来的打印很糟糕,因为未初始化。s.,\nss[]

代码无法检查 的返回值scanf()

scanf()肯定不会按照“编写一个从用户那里获取一行的程序”的指示读取一行scanf()- 它使用.
C Std Lib 定义如下一行,因此代码应尝试读取整行。

文本流是组成行的有序字符序列,每行由零个或多个字符加上一个终止换行符组成。


scanf()选择

int n = 0;
char s[100];
s[0] = '\0';

int cnt == scanf("%99[^.,\n]%n", s, &n);
if (cnt == EOF) puts("Nothing was read");
else printf("%s\n", s);

更好的选择

我建议使用fgets()而不是scanf():从 user 取一行

char s[100];
if (fgets(s, sizeof s, stdin)) {
  size_t n = strcspn(s, ".,\n");   // offset of string that does not have .,\n
  s[n] = '\0';
  printf("%s\n", s);
  printf("%zu\n", n);
}

注意:超过 100 行的行需要额外的代码。


推荐阅读