07-27-2009 10:37 AM
Hi guys,
I experienced a strange effect, and if I didn't have error (TBC) , a problem inside the vsscanf function and, possibly, all the scanf, sscanf family...
In fact, to summarize the context, i did few line of code to read inside a file where some data are written in ASCII.
10 columns, the 1st will receive an integer 'index' and the 9 columns remaining will receive some 'analog' value with 3 or 6 digit.
Here is 3 lines extracted from the file
000007~0.000280~0.020~-148.535~149.590~0.124~0.180~7.671~38.356~0.170
000008~0.000320~0.020~-148.535~149.590~0.124~0.180~7.671~38.356~0.170
000009~0.000360~ 0.023~-148.535~149.590~0.149~0.139~7.721~38.606~0.170 (where ~ is the tabulation char: "\t")
To have a fairly easily editable file, i kept the number of digit in the 1st field constant, to always the same number of digit (here 6)... That's why in this case, we have 5 zeros before.
The problem is ALWAYS the same :
When i have at least 1 zero in 1st character of the line (for example 000008 but also 0124824 or 001542 but NOT 100020 or 106430)
AND
The 1st field include the digit: 8 or 9, and only these digit (for example 000008 but not 000007)
THEN, my 1st analog value converted (double1 in the code) in the following argument will receive in float the value of the 1st field :
double1 will receive 0.000280 during the parsing of the 1st line, it's normal.
double1 will receive 8.0000 and 9.0000 for the 2 last lines extracted from the file. it's NOT normal at all
Obviously, it's always the same function used, same format string, i aslo checked the data before the vsscanf (Templine string) and the return of the vsscanf is always 10 and it's correct according to the number of parameter parsed.
Is somebody have already experienced somethings like that ?
Is somebody able to reproduce this problem ?
Is somebody having a kind of explaination or just detected a possible error in my code.
Any help is welcome
Thanks in advance.
Damien Hoyen
Now, i used following code:
int LineIndex;
double double1,double2,double3 --- until --- double9;
ReadLineFromFile (FileHandle,"%i\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",&LineIndex,
&double1,
&double2,
&double3,
&double4,
&double5,
&double6,
&double7,
&double8,
&double9};
with:
int ReadLineFromFile (int FileHandle,char *FmtStr,...)
{
char TempLine[1024];
int Status;
//start multi arg
va_list args;
va_start (args, FmtStr);
// Check validity of FmtStr
assert (FmtStr != NULL);
memset(TempLine,0,1024);
//Read the line
Status = ReadLine (FileHandle,TempLine, (1023));
//Parse
Status = vsscanf(TempLine, FmtStr, args);
va_end (args);
return(Status);
}
Solved! Go to Solution.
07-27-2009 11:26 AM
You have encountered one of C's features! You might think that the number 10 and the number 010 were the same. You'd be wrong. A leading 0 in a numeric literal signifies the presence of an octal number by default (unless there is an 8 or 9 in the number), not a decimal one. I think there is an option somewhere in the scanf() syntax to override this default behaviour, but I can't lay my hands on it just now. Google should help - or just re-arrange your file data to suit.
JR
07-28-2009 04:39 AM
a nice catch from jr_2005.
i will complete its answer: using %d in the format string always reads a decimal number, while %i tries to find the base of the number and reads an octal number if it starts with 0.
(i have never seen something so flawed as specifying an octal number by prepending only a 0, as if people do never prepend a 0 to decimal numbers... this is just another screw-up in the long list of why C is one of the worst programming language ever invented.)
08-04-2009 11:13 AM
Hi guys,
Yes, both of you have 100% true.
By default, the %i will try to determine by itself the format (Hex, decimal or Octal) of the string,and if starting by 0, will use a octal base.
I was not in touch with this fact.
Just used a: %u, where the: %i was, and works, a: %d should work.
Thanks.
damien