tags:

views:

219

answers:

3

How do one read different records of data that are separated with semicolons into an array in C?

from textfile: Text One; 12.25; Text Two; 5; Text Three; 1.253

fopen ...
for(i = 0; i < nrRecords; i++) {
fscanf(myFile, " %[^;];", myRecords[i].firstText);  /* Ok first text*/
fscanf(myFile, "%lf", &myRecords[i].myDouble1);     /* But goes wrong with first double */
fscanf(myFile, " %[^;];", myRecords[i].secondText); 
fscanf(myFile, "%d", &myRecords[i].myInt1);     
fscanf(myFile, " %[^;];", myRecords[i].thirdText); 
fscanf(myFile, "%lf",&myRecords[i].myDouble2);    
}
fclose...
A: 

One way is to use strtok. And then typecast the result in int or float.

bhups
A: 

The usual advice is to read whole lines and then parse it with sscanf or strtok, or whatever. It's too easy to lose your place in the input file if you sscanf directly from the file. (i.e. the first time something doesn't match, you need a way to skip past it, unless you want to just abort there.)

Peter Cordes
How is it easy to lose your place? It's not hard to skip the rest of the line, which is all you're otherwise doing if you toss the current line on error: `void ignoreline(FILE* f) { char c; for (;;) switch (fgetc(f)) { case '\n': case EOF: return; default:; } `.
Roger Pate
A: 

I would use fgets to read a line from the file, strtok to break it on the semicolons, strcpy to copy strings, strtod to convert to double and strtol to convert to long (and then cast down to integer).

Or, read the line and use a state machine to walk each character and perform the correct operation. For example, you're going to copy each character into firstText until you reach a semicolon, then use strtod to eat the double, skip over the semicolon, copy bytes to secondText, etc.

Or, use a single scanf format string to break the line down into all fields

fscanf(myFile, " %[^;];%lf;%[^;];%d;%[^;];%lf", 
    myRecords[i].firstText,
    &myRecords[i].myDouble1,
    myRecords[i].secondText,
    &myRecords[i].myInt1,
    myRecords[i].thirdText,
    &myRecords[i].myDouble2);

And, as mentioned by others, check the return value of fscanf.

I prefer reading a line at a time, to avoid having a single bad line screw up all of the conversions that follow.

tomlogic