fscanf question

I want to use fscanf read some variables from a text file but I have some problems.

The string format in the text file is like below(I can use any delimiter in the text file):

Material 800 69900 27600 100 Back

I use something like this:

fscanf(fr,"%s %d %d %d %d %s",&material,&depth,&l,&w,&q,&code);
printf("%s %0.2d %4d %4d %4d %s\n",material,depth,l,w,q,code);

The problem is that Material sometimes can consist of two strings e.g Cherry Something...
If I change the delimiter in my text file to ";"...

Cherry Something;800;69900;27600;100;Back

what fscanf format string should I create?
How can I read the material until the character ";" is found...

The below string will not work.
fscanf(fr,"%s;%d;%d;%d;%d;%s",&material,&depth,&l,&w,&q,&code);


Thank you
Last edited on
 
fscanf( fr, "%[^;];%d;%d;%d;%d;%s", ... );



Thank you jsmith...

Any help on what exactly [^;] means...
I think it's some sort of regular expression...but I could be wrong...I also don't know much about them XD
Yes you're absolutely right about this...found some info.

The Dot Matches (Almost) Any Character
http://www.regular-expressions.info/dot.html

%[ is used to indicate what characters should be matched.

%[abcdef0123456789ABCDEF] would match any string consisting of only those characters. Scanning would stop as soon as a non-match was found.

Using a chevron (^) at the beginning inverts the logic ... it says to match all characters EXCEPT the ones that follow. So %[^;]; means to match any string that does not contain a semicolon, and then the last ; says to match the semicolon that terminated the previous string.
Thank you again jsmith...

Let's say that I want to read all the values to string variables...

MELAMINH OXYA;800;699;27600;100;Back5

I have:

char material[20], depth[5], l[5], w[5], q[4], code[10]
fscanf(fr,"%[^;];%s;%s;%s;%s;%s",&material,&depth,&l,&w,&q,&code)

It works when depth, l, w, and q are integers but I get some unpredicted results when I use strings.
"%s" is essentially equal to "%[ \n" -- it stops when it encounters a space or a newline. Looking at the example string you gave above, I don't see any spaces after the first semicolon. Hence I'd expect that your fscanf will read the entire remainder of the line into depth and then l, w, q, and code will be left uninitialized.

You have three options -
If depth, l, w, and q are always integers, then read them as %d (%u for unsigned int).
Or, leave the fscanf alone and modify the input such that there is a space before the
2nd, 3rd, 4th, and 5th semicolons (not recommended)
Or, use %[^;] to read depth, l, w, and q.

OK I decided to use the third option.

1
2
3
4
5
6
while ((fscanf(fr,"%[^;];%[^;];%[^;];%[^;];%[^;];%s",&material,&depth,&l,&w,&q,&code))!=EOF)
	{
			
		printf("%s %s %s %s %s %s",material,depth,l,w,q,code); //console preview
		fprintf(fw,"%s %s %s %s %s %s",material,depth,l,w,q,code);
	}


The input file ends with a empty line.
For the following input 3 lines(2 records and an empty(new) line):

Oak;18,00;542,00;362,00;1;K_RAFI
Oak;18,00;364,00;100,00;1;CR Front


I get an output like this:

Oak 18,00 542,00 362,00 1 K_RAFI
Oak 18,00 364,00 100,00 1 CR Front
18,00 364,00 100,00 1 CR

I get the last line one more time but without the material variable.
If I delete the last empty line in the input file the output is the one that I want...

Oak 18,00 542,00 362,00 1 K_RAFI
Oak 18,00 364,00 100,00 1 CR Front
Last edited on
fscanf returns the number of "matches" made (ie, in your case, the number of parameters filled in). If fscanf does not return 6, then not all of your parameters were read in.
You'll need to check the return code of fscanf() and ONLY process lines in which fscanf returns 6.

Also, *INSIDE* the loop you need to check EOF. Something like this:

1
2
3
4
5
6
7
while( true ) {
    int vals_read = fscanf( /* ... */ );
    if( vals_read == 6 ) {
       // process the line
    } else if( feof( fr ) )
       break;
}

Topic archived. No new replies allowed.