简体   繁体   中英

using fscanf to read in items

There is a file a.txt looks like this:

1 abc
2 
3 jkl

I want to read each line of this file as an int and a string, like this:

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.

So any way to jump to the next line?

Do it in two steps:

  1. Read a full line using 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.

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:

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

How to solve "using fscanf":

After the int , look for spaces (don't save), then look for char that are not '\\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 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 . Thus code can not use "%s" nor " " after the "%d" which both consume all (leading) white-space. The next fscanf() call will consume the '\\n' as part of leading white-space consumption via "%d" .

Minor note: reading the line with fgets() then parsing the buffer is usually a better approach, but coding goals may preclude that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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