0

有一个文件 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行一样),那么上面的代码就会卡在该行。

那么有什么方法可以跳到下一行?

4

3 回答 3

2

分两步进行:

  1. 使用 阅读整行fgets()。这假设您可以对要支持的行的长度设置一个简单的静态限制,但这种情况经常发生。
  2. 用于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 */

不知道什么时候你不会“需要”这个字符串;它要么存在,要么不存在。

于 2013-01-24T08:31:13.613 回答
1

如果字符串的第一个字符是\r or\n这将是一个空字符串。您可以使用比较。如果单词中包含空格(或空行),则 fscanf() 不适合。在这种情况下,最好使用 fgets()

于 2013-01-24T08:15:44.427 回答
1

如何解决“使用 fscanf”:

在 之后int,寻找空格(不要保存),然后寻找char不是'\n'

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();

ret如果某些内容被扫描到中,则为 2 str,否则ret通常为 1。上面的技巧是不要在.'\n'之后扫描int。因此,代码既不能使用"%s"也不能使用它们" ""%d"它们都消耗所有(前导)空白。下一次 fscanf()调用将'\n'通过"%d".

小提示:读取行fgets()然后解析缓冲区通常是一种更好的方法,但编码目标可能会排除这种情况。

于 2014-07-04T20:17:33.980 回答