this question bothers me this few days.
I want to read a string for example, input = (-0.001999,-0.919191,-0.777777,999999.999999)
using sscanf. And my code is
char x[10], y[10], z[10], angle[10];
sscanf( input+1, "%[^,],%[^,],%[^,],%[^)]", &x, %y, &z, &angle);
printf("%s %s %s %s\n", x, y, z, angle);
the expected result is x=-0.001999 y=-0.919191 z=-0.777777 a=999999.999999
but my printf shows : x=-0.001999 y=-0.919191 z=999 a=999999.999999
can somebody help me figure out where the problem is ??
thx!
angle is not big enough to hold the input data and thus z is getting overwritten. Try this:
char x[80], y[80], z[80], angle[80];
After fixing the odd buffer overflow and such, I get:
char input[] = "(-0.001999,-0.919191,-0.777777,999999.999999)";
char x[10], y[10], z[10], angle[14];
sscanf( input+1, "%9[^,],%9[^,],%9[^,],%13[^)]", x, y, z, angle);
printf("%s %s %s %s\n", x, y, z, angle);
and the output I get from this is:
-0.001999 -0.919191 -0.777777 999999.999999
Your sscanf like should be sscanf( input+1, "%[^,],%[^,],%[^,],%[^)]", x, y, z, angle); since your arrays are already pointers (and the y has a % in your example). The other responder has solved the root problem.
Related
I'm trying to read from a file that has the format:
ID: x y z ...... other crap
The first line looks like this:
0: 0.82 1.4133 1.89 0.255 0.1563 armTexture.jpg 0.340 0.241 0.01389
I only need the x y z float numbers, the rest of the line is garbage.
My code currently looks like this:
int i;
char buffer[2];
float x, y, z;
FILE* vertFile = fopen(fileName, "r"); //open file
fscanf(vertFile, "%i", &i); //skips the ID number
fscanf(vertFile, "%[^f]", buffer); //skip anything that is not a float (skips the : and white space before xyz)
//get vert data
vert vertice = { 0, 0, 0 };
fscanf(vertFile, "%f", &x);
fscanf(vertFile, "%f", &y);
fscanf(vertFile, "%f", &z);
fclose(vertFile);
It's been changed a little for debugging (originally the first two scanfs used * to ignore the input).
When I run this, x, y, z do not change. If I make it
int result = fscanf(vertFile, "%f", &x);
result is 0, which I believe tells me it isn't recognizing the numbers as floats at all? I tried switching xyz to doubles and using %lf as well, but that didn't work either.
What could I be doing wrong?
%[^f] doesn't skip non-floats, it skips anything that's not the letter 'f'.
Try %*d: instead. * discards the number read, and a literal : tells it to skip over the colon. You can also combine all those individual reads.
fscanf(vertFile, "%*d: %f %f %f", &x, &y, &z);
I am fairly new to the world of programming so please forgive me if this is a common mistake.
I'm trying to scan 3 double values and 3 strings out of one input string but it doesnt continue after the second value.
double total_weight_kg(char *s, int Length) {
double weights[3];
char units[3];
int test = sscanf(s, "%lf, %s, %lf, %s, %lf, %s",
&weights[0], &units[0],
&weights[1], &units[1],
&weights[2], &units[2]);
printf("%i\n", test);
printf("%s\n", &units[0]);
int main(void) {
total_weight_kg("5, g, 1, t, 175, kg", 3);
return 0;
The first print prints out 2 and the second the g.
Furthermore I'd like to compare units[i] in a loop but can't seem to get that working either.
for (int i = 0; i < Length; i++) {
w = weights[i];
if (strcmp(units[i], "kg") == 0) {
weight += w;
}
}
I hope you can help me find a solution for this problem,
edit: Everyting is working as intended now. Thank you very much for your help. ( 19[^,] was one major problem )
There are some problems in your code:
To scan the strings into units, you must define it as a 2D array of char:
char units[3][20];
You should modify the scanf format to stop the word parsing on , and spaces, as suggested by user3386109.
Also modify the printf to pass the array instead of its address.
Here is the modified code:
double total_weight_kg(char *s, int Length) {
double weights[3];
char units[3][20];
int test = sscanf(s, "%lf, %19[^, \n], %lf, %19[^, \n], %lf, %19[^, \n]",
&weights[0], units[0],
&weights[1], units[1],
&weights[2], units[2]);
printf("%i\n", test);
printf("%s\n", units[0]);
...
}
int main(void) {
total_weight_kg("5, g, 1, t, 175, kg", 3);
return 0;
}
I am trying to understand sscanf behaviour for that I have executed below two program.
void main()
{
char *a = "225.311";
int x = 0, y = 0;
sscanf(a, "%d.3%d", &x, &y);
printf("x is %d, y is %d\n", x, y);
}
output is
x is 255, y is 11
Below program is not working as per my expectation.
void main()
{
char *a = "225.311";
int x = 0, y = 0;
sscanf(a, "%d5.3%d", &x, &y);
printf("x is %d, y is %d\n", x, y);
}
I am expecting 25,11, but the output is
x is 255, y is 0
I am expecting sscanf behaviour should exact same as sprintf in reverse manner. But its not working in my second program. If the format specifed is %d5.3%d, then it has to consider 5 as delimeter. But its not considering and reading all digits for x, and then dot is not matching with 5.3%d so it quits there.
Can somebody please explain this.
That's because the %d conversion specifier means sscanf will keep reading from the buffer pointed to by a till it encounters a non-numeric character in the buffer. This means that %d will consume up till 225 in the string literal "225.311" in your second example.
If the format specifed is %d5.3%d, then it has to consider 5 as
delimeter.
No, that's not true. 5 in the format string means sscanf will match it exactly (after reading an int) in the buffer it reads from. If it fails to match it, then sscanf will return and the value of y is left unchanged. You can check for this by storing the result of sscanf. The return value is equal to the number of input items successfully matched and assigned.
char *a = "225.311";
int x = 0, y = 0;
int retval = sscanf(a, "%d5.3%d", &x, &y);
printf("%d\n", retval); // prints 1
However, note that if the sequence of numeric characters in the buffer is too long to fit into an int, then the behaviour is undefined because of signed integer overflow.
Suggest using a different format and checking the results of sscanf(). Also to distinguish fractions like "0.001" and "0.1", note positions.
const char *a = "225.0311";
int ipart = 0;
unsigned fractionpart;
int n1, n2;
if (sscanf(a, "%d.%n%u%n", &ipart, &n1, &fractionpart, &n2) != 2) {
Handle_BadInput();
}
printf("ipart is %d, fractionpart is %0*u\n", ipart, n2 - n1, fractionpart);
// ipart is 225, fractionpart is 0311
As #ajay discusses, "%d5.3%d" looks for an int, then "5.3" then another int.
I have int x and char c. I want to make a new string called str as "x c"; so the int, a space, and the char.
So for example:
x = 5, c = 'k'
//concatenate int and char with a space in between.
so the line printf("%s", str) will print:
5 k
How do I do this in C code?
Use sprintf or snprintf to avoid safety of your code to be built on assumption that your buffer will be always big enough:
char str[100];
sprintf(str, 100, "%d %c", x, c);
But in case the only purpose of str will be to be used it to with printf, then just printf directly:
printf("%d %c", x, c);
...just don't use itoa since "this function is not defined in ANSI-C and is not part of C++"
These questions might help you as well:
How to convert an int to string in C
Converting int to string in c
char tmp[32]={0x0};
sprintf(tmp, "%d %c", x, c);
printf("%s\n", tmp);
or
printf("%d %c\n", x, c);
sprintf() can do what you want:
sprintf(str, "%d %c", x, c);
Since you want to print the information out, there is no reason (that I can see) to convert the data into a string first. Just print it out:
printf("%d %c", x, c);
I am having trouble parsing the input file in the Auction Problem of Facebook HackerCup.
Every line of the input file contains 9 space-separated integers: N, P1, W1, M, K, A, B, C and D. According to the input constraints the numbers can be as big as 10^18. So, I decided to use long long int to store the variables.
I am doing:
FILE *fr;
long long int N, P1, W1, M, K, A, B, C, D;
char line[1024];
fr = fopen ("input.txt", "rt");
while(fgets(line, 1024, fr) != NULL)
{
sscanf(line, "%lld %lld %lld %lld %lld %lld %lld %lld %lld", &N, &P1, &W1, &M, &K, &A, &B, &C, &D);
printf("N:%lld P1:%lld W1:%lld M:%lld K:%lld A:%lld B:%lld C:%lld D:%lld\n\n", N, P1, W1, M, K, A, B, C, D);
}
For a line 81834165 9999991 1 9999991 9999989 389999650 169999844 799999121 149999837, I get N:81834165 P1:4367 W1:9999991 M:4078336 K:1 A:2292512 B:9999991 C:2292488 D:9999989
Can you please help me to point out the problem in this code? Any recommendation about parsing a similar file would also be appreciated.
Edit: I should add that it works for int variables as in:
char line[1024];
int N, P1, W1, M, K, A, B, C, D;
strcpy(line, "81834165 9999991 1 9999991 9999989 389999650 169999844 799999121 149999837");
printf("Line: %s", line);
sscanf(line, "%d %d %d %d %d %d %d %d %d", &N, &P1, &W1, &M, &K, &A, &B, &C, &D);
printf("ret_val:%d\n\n", ret_val);
printf("N:%d P1:%d W1:%d M:%d K:%d A:%d B:%d C:%d D:%d\n\n", N, P1, W1, M, K, A, B, C, D);
I just noticed something strange. Printing more than one long long int variables in one printf() outputs wrong values while printing them in separate printf()s outputs right values. I mean:
printf("N:%lld P1:%lld\n", N, P1);
printf("N:%lld\n", N);
printf("P1:%lld\n", P1);
outputs:
N:81834165 P1:2009288239
N:81834165
P1:9999991
Do you have any idea about it?
SOLUTION
I have found out that the problem was with the compiler I was using (gcc on MinGW)
On this compiler, I needed to replace %lld with %I64d. I found a similar problem at this post.
Apparently, %lld doesn't work correctly. According to this page, "You should use %I64d instead of %lld as MinGW uses MSVCRT."
Hope this helps!
Make sure to check the return value of sscanf(). There might be subtle errors in your input that causes it to abort after the first few conversions.