HarryQ
HarryQ

Reputation: 1423

fscanf reading in space delimited data until return

I was trying to read in data from a txt file. The txt file has multiple entries each occupies a new line, and each entry has variable length of hex byte data delimited by some symbols (say space ' '). A sample txt file looks like the below

e4 e2 e2 e1 ff\n
f2 a2 22 34\n
ff ee dd\n

Using scanf(fp,"%2x",buffer+offset) in a loop, I was trying to load each byte into a byte buffer until the end of each line, marking a complete record. The main problem is to detect the newline character as scanf ignores it completely and jump into the next line. My original code was

do{
    counter=fscanf(datain,"%2x",buffer1+offset);
    fprintf(stdout,"%#2x ",buffer1[offset]);
    offset+=counter;
}while(!feof(datain));

Upvotes: 1

Views: 2048

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 753665

An alternative and usually simpler way to do such work is to read the entire line with fgets() or getline() and then process the symbols on the line using sscanf(). In many ways, this is similar to the current scheme, but you need to be able to progress through the string, so the %n conversion specification often comes in helpful here:

while (fgets(line, sizeof(line), datain) != 0)
{
    int line_offset = 0;
    int new_offset;
    while (sscanf(line + line_offset, "%2x%n", &buffer1[offset], &new_offset) == 1)
    {
        printf("%#.2x ", buffer1[offset]);
        offset++;
        line_offset += new_offset;
    }
}

The %n conversion is not counted in the return from sscanf().

Note that this avoids some other problems seen in another answer. It doesn't try processing data when there wasn't a line to read, and it doesn't try processing data when there isn't any left.

Also, one of the advantages of reading a line at a time is that error reporting is often easier/better when you can give the entire context (line) where the error occurred, rather then being stuck with what's left of the line after some indeterminate number of successful conversions. If there's an erroneous character in the sixth field on the line, you can show the previous five fields as well as where the error is quite simply.

Upvotes: 2

HarryQ
HarryQ

Reputation: 1423

by appending a %c after each hex specifier, I could extract the space and newline character from the stream. By testing on the this character, I could know a new line has reached.

do{
    counter=fscanf(datain,"%2x%c",buffer1+offset,&followsymbol);
    fprintf(stdout,"Counter:%i\n",counter);
    if (counter==2)
         {fprintf(stdout,"data:%5x\tfollowsymbol:%5x\n",buffer1[offset],followsymbol);
          offset+=1;
         }
    if(followsymbol==0x0a && counter==2)
          printf("a nl symbol has been detected\n");
}while(!feof(datain));

The output from the terminal

Counter:2
data:ffffffe4   followsymbol:   20
Counter:2
data:ffffffe2   followsymbol:   20
Counter:2
data:ffffffe2   followsymbol:   20
Counter:2
data:ffffffe1   followsymbol:   20
Counter:2
data:ffffffff   followsymbol:    a
a nl symbol has been detected
Counter:2
data:fffffff2   followsymbol:   20
Counter:2
data:ffffffa2   followsymbol:   20
Counter:2
data:   22      followsymbol:   20
Counter:2
data:   34      followsymbol:    a
a nl symbol has been detected
Counter:2
data:ffffffff   followsymbol:   20
Counter:2
data:ffffffee   followsymbol:   20
Counter:2
data:ffffffdd   followsymbol:    a
a nl symbol has been detected
Counter:65535

Upvotes: 0

Related Questions