[英]using fscanf to read in items
有一个文件a.txt看起来像这样:
1 abc
2
3 jkl
我想将此文件的每一行读取为int
和字符串,如下所示:
fp = fopen("a.txt", "r");
while (1) {
int num;
char str[10];
int ret =fscanf(fp, "%d%s", &num, str);
if (EOF == ret)
break;
else if (2 != ret)
continue;
// do something with num and str
}
但是有一个问题,如果a.txt中的一行仅包含一个num,没有任何字符串(就像第2行一样),那么上面的代码将停留在该行中。
有什么办法跳到下一行吗?
分两个步骤进行:
fgets()
阅读整行。 假设您可以对要支持的行数设置简单的静态限制,但是通常是这种情况。 sscanf()
检查并分析该行。 这可以解决您遇到的问题,通常是解决此类问题的更好方法。
更新 :试图回应您的评论。 以我的方式来看,最简单的方法是始终读取完整的行(如上),然后解析出您认为由其组成的两个字段:数字和字符串。
如果使用sscanf()
进行此操作,则可以使用返回值来弄清楚它的运行方式,就像您在代码中使用fscanf()
进行尝试一样:
const int num_fields = sscanf(line, "%d %s", &num, str);
if( num_fields == 1 )
; /* we got only the number */
else if( num_fields == 2 )
; /* we got both the number and the string */
else
; /* failed to get either */
不知道什么时候不需要“字符串”; 它在那儿或不在那儿。
如果字符串的第一个字符为\\r or\\n
则为空字符串。 您可以使用比较。 如果单词中包含空格(或空行),则fscanf()不适合。在这种情况下,最好使用fgets()
如何解决“使用fscanf”:
在int
,查找空格(不保存),然后查找不是'\\n'
char
。
int num;
char str[10];
#define ScanInt "%d"
#define ScanSpacesDontSave "%*[ ]"
#define ScanUntilEOL "%9[^\n]"
int ret = fscanf(fp, ScanInt ScanSpacesDontSave ScanUntilEOL, &num, str);
if (EOF == ret) break;
else if (1 == ret) HandleNum(num);
else if (2 == ret) HandleNumStr(num, str);
else HadleMissingNum();
如果将某些内容扫描到str
, ret
将为2,否则ret
通常将为1。上面的技巧是不要在int
之后扫描'\\n'
。 因此,代码不能使用"%s"
或" "
"%d"
之后的"%d"
,它们都占用了所有(前导)空白。 下一个 fscanf()
调用将通过"%d"
消耗'\\n'
作为前导空白消耗的一部分。
小注释:使用fgets()
读取行然后解析缓冲区通常是一种更好的方法,但是编码目标可能会阻止这种情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.