在这种情况下,与fscanf() 一起阅读他非常脆弱。如何处理:
Jenny 16
Minnie Mouse 92
如果缺少空格怎么办?
Jenny16
Minnie Mouse92
fscanf() 还能用吗?
关键是使用fgets()(或POSIX getline())以面向行的方式处理输入,将整行读入缓冲区(字符数组),然后解析值你需要从缓冲区使用sscanf()(或一对指针)
解决此问题的一种方法是将直到第一个数字的所有内容分隔为name,然后转换剩余的age。然后,您只需通过用 nul-terminating 字符覆盖 whtiespace 字符来删除 name 中的所有尾随空格,以修剪 name 中的任何尾随空格。您可以使用strlen() 获取name 中所有字符的长度,然后使用指向最后一个字符的指针并从头开始删除空格,直到找到第一个非空格字符。
例如:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
#define MAXNM 64
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line of input */
char name[MAXNM]; /* name */
int age; /* age */
/* parse contents of buf into name and age -- VALIDATE */
if (sscanf (buf, "%63[^0-9]%d", name, &age) == 2) {
size_t len = strlen(name); /* get length of name */
char *p = name + len - 1; /* pointer to last char in name */
while (p > name && isspace(*p)) /* while char is whitespace */
*p-- = 0; /* overwrite with nul-terminating char */
printf ("name: '%s' age: %d\n", name, age);
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
}
(注意:“缓冲区”没有什么特别之处。它只是一个字符数组(或unsigned char 或uint8_t),足以容纳您的全部身份需要临时存储——不要吝啬缓冲区大小。如果在内存有限的微控制器上,您可以根据需要向下调整)
也不要硬编码文件名或数字(称为幻数),除非别无选择 --- 提供字段时如上所述-width 修饰符到%[^0-9] 转换说明符。否则,如果您需要一个常量#define,或者如果您有多个常量要定义,则使用全局enum。
使用/输出示例
使用dat/name_age.txt 中的原始示例,您将拥有:
$ ./bin/name_age dat/name_age.txt
name: 'Jenny' age: 16
name: 'Amy' age: 24
或者在"Minnie Mouse 92"的例子中:
$ ./bin/name_age <dat/name_age2.txt
name: 'Jenny' age: 16
name: 'Minnie Mouse' age: 92
检查一下,如果您有任何问题,请告诉我。