我正在使用 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 中有一个冒号,所以我想避免额外的冒号),但它不能正确读取数字。我不太确定我能做些什么来解决这个问题,所以我们将不胜感激。
以下是修复程序的一些指示:
要读取 之前的名称:,您可以使用%[^:]
为了避免潜在的缓冲区溢出,您应该指定要存储到目标数组中的最大字符数:
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)