473,386 Members | 1,745 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Help with sscanf() needed desperately

Dear folks,

I need some help with using the sscanf() function. I need to parse a
string which has several parameters given in a "A=... B=... C=..." way,
and each has a different type (one is a text string, another is a
decimal, next one is float, etc.).

I have GCC 4.0.1 on Mac OS X Tiger.

Here is an example of what I am trying to do.

<code>

char A[16];
int B;
float C;

sscanf( "A=Test B=25 C=3.14159", "A=%s B=%d C=%f", A, &B, &C);

printf("%s %d %f",A,B,C);

</code>

This prints "Test 0 0.0000"

I also tried this:

<code>
....
sscanf( "A=Test B=25 C=3.14159", "A=%s",A);
sscanf( "A=Test B=25 C=3.14159", "B=%d",&B);
sscanf( "A=Test B=25 C=3.14159", "C=%f",&C);
....
</code>

but this gives same results...

What am I doing wrong? :-/
Thanks for any help.

Artemiy.

Jul 29 '06 #1
8 2369
On Sat, Jul 29, 2006 at 11:58:34AM -0700, Artemio wrote:
Dear folks,

I need some help with using the sscanf() function. I need to parse a
string which has several parameters given in a "A=... B=... C=..." way,
and each has a different type (one is a text string, another is a
decimal, next one is float, etc.).

I have GCC 4.0.1 on Mac OS X Tiger.

Here is an example of what I am trying to do.

<code>

char A[16];
int B;
float C;

sscanf( "A=Test B=25 C=3.14159", "A=%s B=%d C=%f", A, &B, &C);
printf("%s %d %f",A,B,C);
</code>
This prints "Test 0 0.0000"
Surrounding it with a main() {...} and adding the header include, I failed
to reproduce your problem (probably on the same system as yours).
I also tried this:

<code>
...
sscanf( "A=Test B=25 C=3.14159", "A=%s",A);
sscanf( "A=Test B=25 C=3.14159", "B=%d",&B);
sscanf( "A=Test B=25 C=3.14159", "C=%f",&C);
...
</code>
This one con better understand: sscanf does not keep the position information
within the string between subsequent calls. It always starts form the beginning
"A=...", so there is no match in the second and third line.
In case of a stream (file), it is a completely different story, then you
use fscanf and you will find the expected behaviour.

By the way: you could check the return value of sscanf (if you are interested
in handling erroneous cases).

If you split your string into a white separated list, or you get it already
so (e.g. from argv, the 2nd argument of main()), you can use the macros

#define dopt(name) sscanf(*argv,#name " = %lf",&name)
#define iopt(name) sscanf(*argv,#name " = %d",&name)
#define sopt(name,size) sscanf(*argv,#name " = %" #size "s",name)

I have in my parsing routine a line
while(*++argv) sopt(A,16) || iopt(B) || dopt(C) || fprintf(stderr,"No!\n");

Consider limiting the size of the read string as you see in the third macro.

Hmm, did it help anything?

Szabolcs Borsanyi
Jul 29 '06 #2
Artemio schrieb:
Here is an example of what I am trying to do.

<code>

char A[16];
int B;
float C;

sscanf( "A=Test B=25 C=3.14159", "A=%s B=%d C=%f", A, &B, &C);

printf("%s %d %f",A,B,C);

</code>
It is most of the time a good idea to copy&paste an actual
compiling minimal example showing your problem. With the following,
I obtain the desired results:

#include <stdio.h>

int main (void)
{
char A[16];
int B;
float C;

if (3 == sscanf("A=Test B=25 C=3.14159",
"A=%15s B=%d C=%f",
A, &B, &C)
)
{
printf("%s %d %f\n",A,B,C);
}

return 0;
}

Note
a) the inclusion of <stdio.hto have prototypes of
printf() and sscanf() in scope
b) checking the return value of sscanf() to make sure that
all conversions were successful
c) the '\n' as last output character to make sure that the
output actually happens (without, this is not guaranteed).
This prints "Test 0 0.0000"
My version using your printf() and a slightly altered sscanf()
call prints
Test 25 3.141590
I also tried this:

<code>
...
sscanf( "A=Test B=25 C=3.14159", "A=%s",A);
sscanf( "A=Test B=25 C=3.14159", "B=%d",&B);
sscanf( "A=Test B=25 C=3.14159", "C=%f",&C);
...
</code>
This is wrong.
What am I doing wrong? :-/
I cannot tell -- you did not give us said complete programme.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Jul 29 '06 #3
Hello guys, and thanks so much for the replies!

Here come my questions:

1. I am trying to parse a line this way:

char WaveType[2];
float B0, B1;
int Angle, Repeat;

sscanf( Line, "W=%s a=%d R=%d B0=%f B1=%e", WaveType, &Angle, &Repeat,
&B0, &B1);

The "Line" string contains:

W=TE a=45 R=3 B0=1.0 B1=1e-9

Now the WEIRD thing: when I do it like above it WORKS, but if I read
this string from a file line-by-line, and one of the lines is like
this, it DOESN'T work! Only the WaveType variable gets it's data
properly.

E.g.

while( fgets( Line, sizeof Line, File ) != NULL ){
sscanf( Line, "W=%s a=%d R=%d B0=%f B1=%e", WaveType, &Angle,
&Repeat, &B0, &B1);
}

:-/

2. What is the best way to read this line from a file and parse it into
variables defined above, but in a random order? E.g. sometimes the
string may be W=TE a=45 R=3 B0=1.0 and next time it'll look like W=TE
R=3 B0=1.0 a=45.
Thanks again,

Artemiy.

Jul 30 '06 #4
Hey guys, sorry, reading with sscanf( Line, "W=%s a=%d R=%d B0=%f
B1=%e", WaveType, &Angle, &Repeat, &B0, &B1) works fine, it appears the
data was not printed in a correct way, that's all.

Anyway, the important thing now, what is the best way to parse the Line
string if the order of these X=... variables can change?

Thanks again,

Artemiy.

Jul 30 '06 #5
In article <11*********************@h48g2000cwc.googlegroups. com>
Artemio <ar*****@kdemail.netwrote:
[question 1 already solved, turned out to be error elsewhere]
>[In general, a] "Line" string contains [something like]:
W=TE a=45 R=3 B0=1.0 B1=1e-9
[which can be read relatively easily with sscanf().]
>
2. What is the best way to read this line from a file and parse it into
variables defined above, but in a random order? E.g. sometimes the
string may be W=TE a=45 R=3 B0=1.0 and next time it'll look like W=TE
R=3 B0=1.0 a=45.
Your best bet is probably to write your own "line parser". You
have a number of decisions to make:

- What happens if a line is malformed?

W==1=1=1=47= R:hello, B0=1.2.3.4

- What happens if a line is missing one or more values?

W=TE B1=1.0 R=3 # but no value for "a" or "B0"

If all entries are of the form <text1>=<text2>, where text1 and
text2 never contain any whitespace, you can easily break up a line
into whitespace-separated groups, then break up the broken-up parts
into "="-separated pieces, then look up the <text1part to see
whether it is "W", "a", "R", "B0", or "B1". The result of that
will determine how the <text2part is to be treated (as a "word"
for W, as an integer for "R" and "a", and as a floating-point value
for B0 and B1).

Although the strtok() function is quite ugly, it happens to be
fairly well suited for the first task. The second can be done
with a simple "strchr" (do not use strtok() inside the outer
loop!):

#include <string.h>
...
#define WHITESPACE " \t\n" /* add \b \r \f \v if desired */
...

/* handle one line of input */
char *entry, *value;

for (entry = strtok(line, WHITESPACE); entry != NULL;
entry = strtok(NULL, WHITESPACE)) {
value = strchr(entry, '=');
if (value == NULL)
... do something about malformed entry ...

/* wipe out "=" and leave "value" pointing to the value */
*value++ = 0;

if (strcmp(entry, "W") == 0)
... handle W value ...
else if (strcmp(entry, "a") == 0)
... handle "a" value ...
else if (strcmp(entry, "R") == 0)
... handle R value ...
else if (strcmp(entry, "B0") == 0)
... handle B0 value ...
else if (strcmp(entry, "B1") == 0)
... handle B1 value ...
else
... do something about unknown variable ...
}
... check to make sure all 5 values were specified, if needed ...
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 30 '06 #6
Wow Chris, thank you *so* much for the suggestions! I learned strtok()
a bit but never managed to write anything working with it. Thanks a lot
again, I will learn your code.

Jul 30 '06 #7
Artemio wrote:
>
Here come my questions:
1. I am trying to parse a line this way:

char WaveType[2];
float B0, B1;
int Angle, Repeat;

sscanf( Line, "W=%s a=%d R=%d B0=%f B1=%e", WaveType, &Angle, &Repeat,
&B0, &B1);

The "Line" string contains:

W=TE a=45 R=3 B0=1.0 B1=1e-9

Hmm, you are filling a 3-char-long string into a two-char-long array.
If you are lucky, the final NUL written after WaveType does not affect
other variables (alignment holes), but this is still an undefined behaviour.
while( fgets( Line, sizeof Line, File ) != NULL ){
sscanf( Line, "W=%s a=%d R=%d B0=%f B1=%e", WaveType, &Angle,
&Repeat, &B0, &B1);
}
Well, that's it. You are reading from a file. So my previous posting in the
thread can work in arbitrary order. (But you don't know if an entry is
in the same line or in then next one.)

After you tokenized with strtok or simply with

while( fgets( Line, sizeof Line, File ) != NULL ){
char tokens[8][9]; /* suppose you have at most 8 fields, rest ignored */
int i,s;
/* give default values to your parameters */
s=sscaf(line,"%9s %9s %9s %9s %9s %9s %9s %9s", /* type a lot */
tokens[0],tokens[1],.... );
/* no space between '=' and name and value*/
for(i=0;i<s;i++) {
/* here come my dopt,iopt, sopt macros */
/* read the parameters in the order they appear in the file */
}
}

If you know that you do not accept more than say 8 fields, each 8 char long,
this is (perhaps) the simplest way for random field order.

Szabolcs Borsanyi
Jul 30 '06 #8
Artemio wrote:
Wow Chris, thank you so much for the suggestions! I learned strtok()
a bit but never managed to write anything working with it. Thanks a
lot again, I will learn your code.

Please quote enough of the previous message for context. Google does
that automatically now. Your replies belong following or interspersed
with properly trimmed quotes. See the vast majority of posts here for
examples.


Brian
Jul 30 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Ramprasad A Padmanabhan | last post by:
Hello all I want to read into a string an input from QUERY_STRING how do I ensure that scanf reads more chars into the string that it can hold eg { char* s1; char* data; long n;
7
by: Allan Bruce | last post by:
If I have sscanf("FL:%s:%d:%s\n", lGuid, &lID, lFileName); and the last string contains spaces, e.g. my complete string "FL:1234ABCD:3:FileName With Spaces.txt\n" does sscanf just make...
12
by: Simone Mehta | last post by:
hi All, I am parsing a CSV file. I want to read every row into a char array of reasonable size and then extract strings from it. <snippet> char foo="hello,world,bye,bye,world"; ........
33
by: Martin Jørgensen | last post by:
Hi, In continuation of the thread I made "perhaps a stack problem? Long calculations - strange error?", I think I now got a "stable" error, meaning that the error always seem to come here now...
2
by: den_cse_here | last post by:
Hello, I've to take the input from a file in which data will be something like this: FENC~!+SG001~!+1~!+TEST DATA~!+SGSIN~!+KRPUS~!+LOOP1~!+LOOP1 DESC~!+KRPUS~!+GBSOU~!+LOOP2~!+LOOP2...
10
by: nk | last post by:
Hi, I'm a newbie. The code below sorts names entered. ---------------------------------------------------------------------------- #include <stdio.h> #include <conio.h> #include <string.h>...
5
by: a | last post by:
After reading FAQ comp.lang.c section 12 and googling again, still there is no threads talking about reading a series of numbers. The input files, somehow structured, is exemplified below: ...
16
by: Chad | last post by:
Given the following #include <stdio.h> int main(void) { char line; long arg1, arg2; while(fgets(line, BUFSIZ, stdin) != NULL){
11
by: A.C. | last post by:
hi i m declaring a structure globally & there is func1 & main. i m assigning the value to variable(this is a pointer) of structure in fun1 & want to print it in main. this is same kind of...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.