简体   繁体   English

使用fscanf读取项目

[英]using fscanf to read in items

There is a file a.txt looks like this: 有一个文件a.txt看起来像这样:

1 abc
2 
3 jkl

I want to read each line of this file as an int and a string, like this: 我想将此文件的每一行读取为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
}

But there is a problem, if a line in a.txt contains just a num, no string (just like line 2), then the above code will be stuck in that line. 但是有一个问题,如果a.txt中的一行仅包含一个num,没有任何字符串(就像第2行一样),那么上面的代码将停留在该行中。

So any way to jump to the next line? 有什么办法跳到下一行吗?

Do it in two steps: 分两个步骤进行:

  1. Read a full line using fgets() . 使用fgets()阅读整行。 This assumes you can put a simple static limit on how long lines you want to support, but that's very often the case. 假设您可以对要支持的行数设置简单的静态限制,但是通常是这种情况。
  2. Use sscanf() to inspect and parse the line. 使用sscanf()检查并分析该行。

This works around the problem you ran into, and is generally the better approach for problems like these. 这可以解决您遇到的问题,通常是解决此类问题的更好方法。

UPDATE : Trying to respond to your comment. 更新 :试图回应您的评论。 The way I see it, the easiest approach is to always read the full line (as above), then parse out the two fields you consider it to consist of: the number and the string. 以我的方式来看,最简单的方法是始终读取完整的行(如上),然后解析出您认为由其组成的两个字段:数字和字符串。

If you do this with sscanf() , you can use the return value to figure out how it went, like you tried with fscanf() in your code: 如果使用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 */

Not sure when you wouldn't "need" the string; 不知道什么时候不需要“字符串”; it's either there or it isn't. 它在那儿或不在那儿。

If the first character of the string is \\r or\\n this will be an empty string. 如果字符串的第一个字符为\\r or\\n则为空字符串。 You can use the comparison. 您可以使用比较。 fscanf() is not suitable if words contain spaces(or empty lines) in them .In that case better to use fgets() 如果单词中包含空格(或空行),则fscanf()不适合。在这种情况下,最好使用fgets()

How to solve "using fscanf": 如何解决“使用fscanf”:

After the int , look for spaces (don't save), then look for char that are not '\\n' . 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();

ret will be 2 if something was scanned into str , else ret will typically be 1. The trick to the above is not to scan in a '\\n' after the int . 如果将某些内容扫描到strret将为2,否则ret通常将为1。上面的技巧是不要在int之后扫描'\\n' Thus code can not use "%s" nor " " after the "%d" which both consume all (leading) white-space. 因此,代码不能使用"%s"" " "%d"之后的"%d" ,它们都占用了所有(前导)空白。 The next fscanf() call will consume the '\\n' as part of leading white-space consumption via "%d" . 下一个 fscanf()调用将通过"%d"消耗'\\n'作为前导空白消耗的一部分。

Minor note: reading the line with fgets() then parsing the buffer is usually a better approach, but coding goals may preclude that. 小注释:使用fgets()读取行然后解析缓冲区通常是一种更好的方法,但是编码目标可能会阻止这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM