• Welcome to Valhalla Legends Archive.
 

sscanf function

Started by touchstone, February 04, 2004, 12:40 PM

Previous topic - Next topic

touchstone



include<stdio.h>
#include<stdlib.h>


int main()


{

FILE *infile = fopen("d:\\sample.txt","r");

if(infile ==NULL) printf("can not open ");


char buff[90];

int n ;

while(!feof(infile))

{

fgets(buff,70,infile);

sscanf(buff,"%d",&n);

printf("%d\n",n);

}

}



sample.txt
--------------
16 18 20 25 18  23 22 55

11 22 23 25 28 29 27 31

4 2 78 67 90 23 25 56

12 0  16 17 87 79 0 89


ouput of the program
-----------------------------
16
16
11
11
4
4
12
12
12


why the data has been repeated  two times ?

why not the output like below?

16
11
4
12

any explanation?


Yoni

Haven't read entire source code, but I spotted the most likely source of the problem.

Quote from: touchstone on February 04, 2004, 12:40 PM

sscanf(buff,"%d",&n);

When you use "%d" as a format string for *scanf, it reads an integer and that's it. The next time you try to read, it'll encounter the whitespace and fail.
You can instruct *scanf to skip whitespaces by adding a space in the format string, as such:


sscanf(buff, "%d ", &n);


(I changed the string from "%d" to "%d ", by adding a space after the d.)

MoNksBaNe_Agahnim


while(!feof(infile))


maybe make it f.eof() ... not sure but that is what you have to do with fstream

Kp

Quote from: MoNksBaNe_Agahnim on February 04, 2004, 02:56 PMwhile(!feof(infile))maybe make it f.eof() ... not sure but that is what you have to do with fstream

No.  If you look at his code, nowhere does there exist a variable f which could even have an eof method.

If you're only scanning one number, I'd suggest using strtol instead.  Just a matter of preference.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

touchstone

hi  i did  this (added space after %d)
as per your suggestion....


sscanf(buff, "%d ", &n);



still... it it did not give me  result.

why it is not giving. i am  learning to use fgets() and sscanf()

do you think i have done any mistake in the code?

...but according to logic it should print the number only once. is not it?i think my logic is correct.

datas are poured into buff and then sscanf is extracting out the integer from  the buff string.

i am trying a lot to find out  the cause....but could not....whats wrong?

iago

#5
Your code looks fine, except:
Max Length should be a constant (your buffer length and the amount you get can be the same)
If the file can't be opened, it will still try reading it
Besides those, it looks great.. I don't have a C compiler here, but I will try it in Linux

<edit>
include <stdio.h> should be #include <stdio.h> (I assume that's a copy mistake)
<edit2>
hah, I found the problem just before I ran it.  The problem is that the file has blank lines, which are read in and they aren't parsed correctly.  
</edit2>
</edit>
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


touchstone

>Max Length should be a constant

what do you mean? i have alloted maximum 90 character in the buff[]....its enough.

>If the file can't be opened

 well,   file is opening... i did not do NULL checking.
...but no doubt its opening

>include <stdio.h> should be #include <stdio.h>
yes....its a copy mistake.

> found the problem just before I ran it.  The problem is that the file has blank lines, which are read in and they aren't parsed correctly.  

....i am not agree with you.

let me explain why....

fget() will read  70 elements ...... as soon as it gets a newline it will stop and it will insert newline into buff and also a  '\0' character will be automatically added into buff.

file pointer is now in the next row(because of newline)


now sscanf() will extract the first  integer stored in the buff.


this  should be the case for one go of the while loop.

same thing will be repeating  until  fget() returns end of file.

i am just  experimenting with this code to  understand the behaviour of fgets() and sscanf()

but i did not find any answer  why  i am getting wrong output.

thanks









iago

Quote from: touchstone on February 05, 2004, 08:01 AM
>Max Length should be a constant

what do you mean? i have alloted maximum 90 character in the buff[]....its enough.
I mean, it is better coding practice to do this:
#define MAXLENGTH 90
...
char line[MAXLENGTH];
...
fgets(line, MAXLENGTH, file);
...

Quote
>If the file can't be opened

 well,   file is opening... i did not do NULL checking.
...but no doubt its opening
But if the file doesn't open for some reason, it will still attempt to process and die.

Quote> found the problem just before I ran it.  The problem is that the file has blank lines, which are read in and they aren't parsed correctly.  

....i am not agree with you.

let me explain why....

fget() will read  70 elements ...... as soon as it gets a newline it will stop and it will insert newline into buff and also a  '\0' character will be automatically added into buff.

file pointer is now in the next row(because of newline)

You're exactly right.  But your file looks like this:
16 18 20 25 18  23 22 55\n
\n
11 22 23 25 28 29 27 31\n
\n
4 2 78 67 90 23 25 56\n
\n
12 0  16 17 87 79 0 89EOF


After it reads the first line, it reads the second, which is simply "\n".  The sscanf() runs and does nothing, because there is nothing there to parse.  Then the string is displayed, but because sscanf() did nothing, the string hasn't changed.

Try checking the return value of sscanf() (I forget what it should be, but you can look it up) to see if anything happened before displaying.

This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Skywing

sscanf returns the number of arguments scanned in, so you should compare it to 1 in this situation.

iago

Quote from: Skywing on February 05, 2004, 01:42 PM
sscanf returns the number of arguments scanned in, so you should compare it to 1 in this situation.

Ah, that's what I thought, but I wasn't 100% sure so I didn't want to say.  Thanks!
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


touchstone

hi, i was away for some days....

however, i am convinced by your  explanation....i hava understood the cause of mine previous output.

and  i should go for checking of sscanf() conversion before printing.

i wrote


.........
..........
int p = sscanf(buff,"%d",&n);
if(p==1)
{

printf("%d\n",n);
............



....and this checking is giving
16
11
4
12

its ok now. ....thanks

iago

Another way to do it would be this:
if(sscanf(buff,"%d",&n) == 1)
{
 ....
}
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*