Reputation: 1423
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
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
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