Reading numbers with sscanf

I have the following line of data:
3563, LODpmedhos2_LAe, 0, 2063.132813, -1731.78125, 15.2734375, 0, 0, 0.7071068883, 0.7071066499, -1

and the code i'm using to read it:
http://pastebin.com/R6TTxKT2

the strings and int read just fine but the floats are always 0.0 and not the values from the file. I tired using e instead of f in the sscanf function but it made no difference. What am i missing here?
Hi,

Just post the code here, unless there is lots of it. It's also good to post a complete program that demonstrates the problem.


1
2
3
4
5
6
7
8
char szIPLData[512];
char szModelName[128];
int modelID=0, interior=0;
float posX=0.0f, posY=0.0f, posZ=0.0f;
float rotX=0.0f, rotY=0.0f, rotZ=0.0f, rotW=0.0f;

sscanf(szLineBuf, "%d, %s, %d, %f, %f, %f, %f, %f, %f, %f", 
&modelID, szModelName, &interior, posX, posY, posZ, rotX, rotY, rotZ, rotW);


The arguments have to be pointers, so put an & before each of the float arguments.

Also make use of the return value from the function, to see if it worked.

Prefer to use double rather than float, unless you have a good reason. Use %lf for that.
Edit: Actually you should use double here, some of the numbers have 9 digits, which exceeds the precision of a float. A float can have 6 or 7 digits, a double can have 15 or 16 depending on the implementation in the compiler.

Good Luck !!
Last edited on
To add to what @TheIdeasMan said,

Why are you reading the numbers 0 and 0 (using rotX and rotY ) as floating points? When 0 is an integer.

Also, you're not reading the last number "-1".
Why are you reading the numbers 0 and 0 (using rotX and rotY ) as floating points? When 0 is an integer.


0 is a valid FP number, so it is read in quite happily :+)
@TheIdeasMan

About posting the code; I tried to post it here put when submitting the message i got a error about incorrect form so i thought it was about the %'s and just posted it to pastebin (the code tag also dint work).

I changed the code to this but the result is still the same:
1
2
3
4
double posX=0.0f, posY=0.0f, posZ=0.0f;
double rotX=0.0f, rotY=0.0f, rotZ=0.0f, rotW=0.0f;
sscanf(szLineBuf, "%d, %s, %d, %lf, %lf, %lf, %lf, %lf, %lf, %lf",
&modelID, szModelName, &interior, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &rotW);

I checked with the debugger (using Visual Studio 2010) and all the values were at 0 after sscanf.

@TarikNeaj

I read all the numbers as float (now double) because there are multiple data lines in the file and most of them are floats (the example line just happened to have those values at 0).
Hi,

this works :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>

int main(void)
{
   const char szLineBuf[512] = "3563, LODpmedhos2_LAe, 0, 2063.132813, -1731.78125, 
            15.2734375, 0, 0, 0.7071068883, 0.7071066499, -1";

   char szModelName[128];
   int modelID=0; 
   int interior=0;
   double posX=0.0; /*always declare 1 var per line */ 
   double posY=0.0;
   double posZ=0.0;
   double rotX=0.0; 
   double rotY=0.0;
   double rotZ=0.0; 
   double rotW=0.0;

   int ScanReturnVal = 0;

   ScanReturnVal = sscanf(szLineBuf, "%d, %15s, %d, %lf, %lf, %lf, %lf, %lf, %lf, %lf,
 %*d",&modelID,szModelName, &interior, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &rotW);

   printf("Items scanned %3i\n", ScanReturnVal);
   printf("%d, %s, %d, %lf, %lf, %lf, %lf, %lf, %lf, %lf",
   modelID, szModelName, interior, posX, posY, posZ, rotX, rotY, rotZ, rotW);

     return 0;
}


Looks like the %s has to have a width specification in scanf.



Last edited on
@TheIdeasMan

Thanks! Now it seems to work well. :)
Okay now it doesn't work anymore after i did some needed changes.
Here is the full code for the loop that reads the file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#define READ_BUF_SIZE 256

#include <stdio.h>
#include <string>
#include <Windows.h>

int main(int argc, char* args[])
{
	if(argc < 2)
		return 0;

	bool bInstFound = false;
	FILE *pIPL = fopen(args[1], "r");

	char szLineBuf[READ_BUF_SIZE];
	char szBuf[READ_BUF_SIZE];

	while (fgets(szLineBuf, sizeof(szLineBuf), pIPL) != NULL)
	{
		while(bInstFound)
		{
			sscanf(szLineBuf, "%s", szBuf);
			if(strncmp(szBuf, "end", 3) == 0)
			{
				bInstFound = false;
				break;
			}
			else
			{
				char szIPLData[512];
				char szModelName[128];

				int modelID=0;
				int interior=0;

				double posX=0.0; 
				double posY=0.0;
				double posZ=0.0;
				double rotX=0.0;
				double rotY=0.0;
				double rotZ=0.0;
				double rotW=0.0;

				int iReturnVal = -1;

				//Doesnt read the position and rotation values anymore
				iReturnVal = sscanf(szLineBuf, "%d, %s, %d, %lf, %lf, %lf, %lf, %lf, %lf, %lf",
					&modelID, szModelName, &interior, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &rotW);
				
				sprintf(szIPLData, "%d %s %d %f %f %f %f %f %f %f",
					modelID, szModelName, interior, posX, posY, posZ, rotX, rotY, rotZ, rotW);

				printf("iReturnVal:%d %s\n", iReturnVal, szIPLData);
				
				fgets(szLineBuf, sizeof(szLineBuf), pIPL); // Get next line form file
			}
		}

		//////////////////////////////////////////////////////////////////////////
		sscanf(szLineBuf, "%s", szBuf);
		if(strncmp(szLineBuf, "inst", 4) == 0)
			bInstFound = true;

		szBuf[0] = 0;
	}

	fclose(pIPL);

	//system("PAUSE");
	return 0;
}


It reads modelID and szModelName correctly but the rest of the values stay at 0.
Here is a example datafile:
1
2
3
4
5
6
7
8
9
10
11
inst
16769, desn2_ammun04, 0, 1034.75, -2743, 4.05, 1.3268e-06, 1.3268e-06, -1, -1.3268e-06, -1
1493, Gen_doorSHOP01, 0, 1037.75, -2735.58, 4.05, 0, 0, 1, 1.32679e-06, -1
1431, DYN_BOX_PILE, 0, 1039.75, -2737, 7.9, 0, 0, 0, 1, -1
1431, DYN_BOX_PILE, 0, 1036.2, -2737, 7.9, 0, 0, 0, 1, -1
1431, DYN_BOX_PILE, 0, 1037.99, -2737, 8.5, 0, 0, 0, 1, -1
1431, DYN_BOX_PILE, 0, 1038.4, -2737, 7.9, 0, 0, 0, 1, -1
1431, DYN_BOX_PILE, 0, 1024.2, -2736, 4.599, 0, 0, 0, 1, -1
760, sm_bush_small_1, 0, 772.7, -2864, 3.9, 1.87059e-06, 1.87059e-06, -0.649449, -0.760405, -1
760, sm_bush_small_1, 0, 772.7, -2865.5, 3.4, 1.77941e-06, 1.77941e-06, -0.894934, -0.446199, -1
end


I'm probaby missing something simple but i just couldn't work out what it was..
I'd appreciate if someone pointed out whats wrong with it.
Last edited on
Hi,

In my example I had %15s. The 15 is a minimum width specification. When I was testing my code, it wouldn't work without this.

Also, I should have shown how to use the return value to check whether the read has worked or not:

1
2
3
4
5
6
7
8
9
10
const int NumberFields =10;

iReturnVal = sscanf(szLineBuf, "%d, %15s, %d, %lf, %lf, %lf, %lf, %lf, %lf, %lf",
					&modelID, szModelName, &interior, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &rotW);

If (iReturnVal != NumberFields ) { 
    printf ("Incomplete read, only %i fields read", iReturnVal);
} else {
   /*   All OK */
}


I notice you have an i in your variable name to signify that it is an int. This is a form of Hungarian Notation which is frowned upon these days.

Also, you could do with some functions in your code.

Finally, If you change the settings in your editor to make tabs into 4 spaces say, then it will display on this website better. The site transforms tabs into 8 spaces.
TheIdeasMan wrote:
In my example I had %15s. The 15 is a minimum width specification. When I was testing my code, it wouldn't work without this.


It's the maximum number of characters to extract. With the scanf family of functions the string specifier (%s) scans a single whitespace-delimited token. The comma following the string is not whitespace, therefore it is read as part of the token (except in the case where the input was limited to the size of the token you desired to extract.)

In the case where the comma was read as part of the string, scanf will still try to match a comma after the string and there won't be one, so it will fail.

Using a width specifier will work if all of your strings are expected to be exactly 15 characters in length, but it is a pretty fragile solution if that could ever change. Instead, you might consider removing the comma after the string specifier in the format string and just trim it from the string after the scanf call.
After removing the comma from the sscanf function, it started working fine.
Thank you guys for helping me out!
Topic archived. No new replies allowed.