C如何使用sscanf正确支持

时间:2015-10-05 07:53:20

标签: c scanf enter

我目前正在学习读取C中的文件。 无论如何,切入追逐:

文字文件内容:

123456 James Doakes; 0
987987 Dexter Morgan; 0
010203 Masuka Perv; 0
int main()
{
char accountNr[ACCOUNTNRSIZE], ownerName[NAMESIZE], enter[3];
int accountBalance = 0;
char filename[] = "breg.txt";
FILE *file = fopen(filename, "r");
if (file != NULL) {
    char line[128];
    while (fgets(line, sizeof(line), file) != NULL) {
        sscanf(line, "%s %[^;] %d ", accountNr, ownerName, &accountBalance);
        printf("%s", ownerName);
        //fflushstdin();
    }
    fclose(file);
} else {
    perror(filename);
}
return 0;
}

我写这篇文章是为了检查James Doakes的名称是否正确注册:

printf("%s", ownerName);

但是当它打印出来时就像stdout仍然处于活动状态,我可以按Enter键,它会再次输入名称。我的目标当然是能够将数字,全名和最后一个数字作为单独的变量进行扫描。但它显然不起作用。我猜是一个\ n也被注册了。不知道,我只是在猜测。

我做错了什么?为什么?我该如何解决这个问题?

非常感谢, 米夫

1 个答案:

答案 0 :(得分:3)

%s %[^;] %d 

表示以空格,可选空格,不是;的字符序列,可选空格,然后是数字终止的字符串。

您似乎没有扫描实际的;字符本身,因此,当您尝试获取数字时,输入流中的;将导致它失败。您可以通过以下方式看到:

#include <stdio.h>

#define ACCOUNTNRSIZE 100
#define NAMESIZE 100

int main (void) {
    char accountNr[ACCOUNTNRSIZE], ownerName[NAMESIZE], enter[3];
    int accountBalance = 0;
    char filename[] = "breg.txt";
    FILE *file = fopen(filename, "r");
    if (file != NULL) {
        char line[128];
        while (fgets(line, sizeof(line), file) != NULL) {
            int count = sscanf(line, "%s %[^;] %d ", accountNr, ownerName, &accountBalance);
            printf ("%d [%s] [%s] [%d]\n", count, accountNr, ownerName, accountBalance);
        }
        fclose(file);
    } else {
        perror(filename);
    }
    return 0;
}

输出:

2 [123456] [James Doakes] [0]
2 [987987] [Dexter Morgan] [0]
2 [010203] [Masuka Perv] [0]

实际上,即使您将breg.txt文件更改为:

123456 James Doakes; 314159
987987 Dexter Morgan; 271828
010203 Masuka Perv; 42

您仍然可以获得0帐户余额,因为扫描只能成功读取两个项目。

每当使用其中一个scanf - 系列函数时,您应该检查返回代码以确保它扫描正确数量的项目,如:

int count = sscanf (line, "%s %[^;] %d ", accountNr, ownerName, &accountBalance);
if (count != 3) {
    fprintf (stderr, "Catostrophic failure, count is %d\n", count);
    return 1;
}

此处的修复相对简单,只需使用%s %[^;]; %d作为格式字符串。

通过该更改,您看到的输出是:

3 [123456] [James Doakes] [314159]
3 [987987] [Dexter Morgan] [271828]
3 [010203] [Masuka Perv] [42]

请记住,%d之前实际上并没有需要空格(尽管它不会造成伤害)。在尝试扫描数字之前,该特定格式说明符会跳过空格。