C 如何正确使用sscanf support

C How to use sscanf properly support

我目前正在学习用 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 也被注册了。不知道,我只是猜测。

我做错了什么?为什么?我该如何解决?

非常感谢, 米夫

%s %[^;] %d 

表示一个字符串以白色 space、可选的白色 space、不是 ; 的字符序列、可选的白色 space,然后是一个数字结尾。

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

#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系列函数之一时,你应该检查return代码以确保它扫描正确数量的项目,如:

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 之前的 space(尽管这不会造成任何伤害)。在尝试扫描数字之前,该特定格式说明符会跳过白色 space。