使用 fscanf 获取字符串和数字

gho*_*t12 1 c scanf

我正在使用 fscanf 从这种格式的文件中获取名称和号码并将其打印出来:

   Jim: 100.00
  John: 200.00
  Adam: 300.00
Miguel: 400.00
Run Code Online (Sandbox Code Playgroud)

我的输出没有正确打印。

我尝试过使用while(fscanf(filep, "%s %lf", name, balance) != EOF),但它似乎总是以这种格式打印:

   Jim:: 0.0000
  John:: 0.0000
  Adam:: 0.0000
Miguel:: 0.0000
Run Code Online (Sandbox Code Playgroud)

看起来它正确地读取了名称,但它在名称末尾添加了冒号(我在 printf 中有一个冒号,所以我想避免额外的冒号),但它不能正确读取数字。我不太确定我能做些什么来解决这个问题,所以我们将不胜感激。

chq*_*lie 5

以下是修复程序的一些指示:

  • 要读取 之前的名称:,您可以使用%[^:]

  • 为了避免潜在的缓冲区溢出,您应该指定要存储到目标数组中的最大字符数:

    char name[30];
    scanf("%29[^:]", name);
    
    Run Code Online (Sandbox Code Playgroud)
  • 要跳过挂起的换行符和潜在的初始空格,请在格式字符串的开头添加一个空格:

    char name[30];
    scanf(" %29[^:]", name);
    
    Run Code Online (Sandbox Code Playgroud)
  • 要使用,只需在转换格式后:添加一个即可。:

  • 要解析数字,请使用%lf转换 if balancehas type double,但传递变量的地址&

    char name[30];
    double balance;
    scanf(" %29[^:]: %lf", name, &balance);
    
    Run Code Online (Sandbox Code Playgroud)
  • 为什么不使用&forname您可能会问...因为它name是一个数组:将数组作为参数传递给函数会隐式传递指向其第一个元素的指针。您可以明确地执行此操作,&name[0]但直接传递更简单且更惯用name

  • 您应该检查转换是否成功:scanf()返回成功转换的数量,因此2如果输入被正确解析,它将返回。

  • 您的输出显示是Miguel:: 0.0000因为:被读取为名称的一部分,%s并且余额是以某种%.4f格式打印的。第一个问题通过%29[^:]转换解决了,第二个问题你应该使用%.2f输出 2 位小数。

  • 为了更容易检测文件结尾并从无效输入中恢复,建议一次读取一行并fgets()使用sscanf()尝试转换该行的内容。

这是解析文件的函数:

#include <stdio.h>

int read_file(FILE *fp) {
    char line[200];
    char name[30];
    double balance;
    int count = 0;

    while (fgets(line, sizeof line, fp)) {
        if (sscanf(line, " %29[^:]: %lf", name, &balance) == 2) {
            count++;
            printf("%s: %.2f\n", name, balance);
        } else {
            printf("invalid input: %s\n", line);
        }
    }
    return count; // return the number of lines converted
}
Run Code Online (Sandbox Code Playgroud)

请注意,此方法将接受并忽略上线余额后的额外内容。要检测并报告此问题,您可以使用%n转换来检索读取的字符数,并在该行具有额外的非空白内容时报告问题:

#include <stdio.h>

int read_file(FILE *fp) {
    char line[200];
    int count = 0;

    while (fgets(line, sizeof line, fp)) {
        char name[30];
        double balance;
        int len = 0;

        if (sscanf(line, " %29[^:]: %lf %n", name, &balance, &len) == 2) {
            count++;
            printf("%s: %.2f\n", name, balance);
            if (line[len] != '\0') {
                printf("extra characters: %s\n", line + len);
            }
        } else {
            printf("invalid input: %s\n", line);
        }
    }
    return count; // return the number of lines converted
}
Run Code Online (Sandbox Code Playgroud)