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