【问题标题】:C How to use sscanf properly supportC 如何正确使用 sscanf 支持
【发布时间】:2016-01-01 19:40:27
【问题描述】:

我目前正在学习从 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);

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

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

非常感谢, 米夫

【问题讨论】:

  • 试试sscanf(line, "%s %[^;]; %d", accountNr, ownerName, &accountBalance);或检查它的返回值,int r = sscanf(line, "%s %[^;]; %d", accountNr, ownerName, &accountBalance); if(r == 3) /* accountNr, ownerName and accountBalance scanned successfully */ else if (r == 2) /* aaccountNr and ownerName scanned successfully */ else if (r == 1) /* aaccountNr scanned successfully */ else /* Nothing scanned successfully :( */
  • 打印 ownerName 时还要添加'\n'printf("%s\n", ownerName);

标签: c scanf enter


【解决方案1】:
%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-family 函数之一时,您应该检查返回码以确保它扫描的项目数量正确,如下所示:

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 之前有一个空格(尽管它不会造成任何伤害)。该特定格式说明符在尝试扫描数字之前会跳过空格。

【讨论】:

  • 完美。我也意识到我昨天可能走在了正确的轨道上,但作为一个新手,你不知道问题出在哪里,所以你最终试图修复好代码,认为它的坏代码。谢谢!
猜你喜欢
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多