Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > sscanf fixed-width integer question

Reply
Thread Tools

sscanf fixed-width integer question

 
 
Brent Lievers
Guest
Posts: n/a
 
      04-22-2004
Greetings,

I have a question about parsing a fixed-width integer from a string.

Lines of data are being read from a file having a very strict
column-delimited format. In my example below, columns 0-7 are an integer
and columns 8-23 are a float. In _most_ files, the first few columns of
the float are blank space to make it human readable. But not always.
So, once they have been read from the file, I try to parse out the
different values using something like the following:

/*------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>

int main()
{
char line1[]= " 12 15.796473824857";
char line2[]= " 1215.7964738248571";
int id;
float num;

sscanf(line1, "%8d%16E", &id, &num);
printf("ID= %d\n", id);
printf("NUM= %f\n\n", num);

sscanf(line2, "%8d%16E", &id, &num);
printf("ID= %d\n", id);
printf("NUM= %f\n", num);

return EXIT_SUCCESS;
}
/*------------------------------------------*/

which works in one case and not the other.

I could read the first 8 columns as characters and strtol() them to an
integer. Is there another/better way?

Thanks,

Brent
 
Reply With Quote
 
 
 
 
- Kees van der Bent -
Guest
Posts: n/a
 
      04-22-2004
Brent Lievers wrote:
> Greetings,
>
> I have a question about parsing a fixed-width integer from a string.
>
> Lines of data are being read from a file having a very strict
> column-delimited format. In my example below, columns 0-7 are an integer
> and columns 8-23 are a float. In _most_ files, the first few columns of
> the float are blank space to make it human readable. But not always.
> So, once they have been read from the file, I try to parse out the
> different values using something like the following:
>
> /*------------------------------------------*/
> #include <stdio.h>
> #include <stdlib.h>
>
> int main()
> {
> char line1[]= " 12 15.796473824857";
> char line2[]= " 1215.7964738248571";
> int id;
> float num;
>
> sscanf(line1, "%8d%16E", &id, &num);
> printf("ID= %d\n", id);
> printf("NUM= %f\n\n", num);
>
> sscanf(line2, "%8d%16E", &id, &num);
> printf("ID= %d\n", id);
> printf("NUM= %f\n", num);
>
> return EXIT_SUCCESS;
> }
> /*------------------------------------------*/
>
> which works in one case and not the other.
>
> I could read the first 8 columns as characters and strtol() them to an
> integer. Is there another/better way?


You could temporarily insert a '\0' at position 8 (after
first saving its value of course). Then sscanf() the int.
Subsequently restore the saved position 8, and sscanf() the
float from position 8.

Cheers,

Kees

 
Reply With Quote
 
 
 
 
- Kees van der Bent -
Guest
Posts: n/a
 
      04-22-2004
- Kees van der Bent - wrote:
> Brent Lievers wrote:
>
>> Greetings,
>>
>> I have a question about parsing a fixed-width integer from a string.
>> Lines of data are being read from a file having a very strict
>> column-delimited format. In my example below, columns 0-7 are an integer
>> and columns 8-23 are a float. In _most_ files, the first few columns of
>> the float are blank space to make it human readable. But not always.
>> So, once they have been read from the file, I try to parse out the
>> different values using something like the following:
>>
>> /*------------------------------------------*/
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>> int main()
>> {
>> char line1[]= " 12 15.796473824857";
>> char line2[]= " 1215.7964738248571";
>> int id;
>> float num;
>>
>> sscanf(line1, "%8d%16E", &id, &num);
>> printf("ID= %d\n", id);
>> printf("NUM= %f\n\n", num);
>>
>> sscanf(line2, "%8d%16E", &id, &num);
>> printf("ID= %d\n", id);
>> printf("NUM= %f\n", num);
>>
>> return EXIT_SUCCESS;
>> }
>> /*------------------------------------------*/
>>
>> which works in one case and not the other.
>>
>> I could read the first 8 columns as characters and strtol() them to an
>> integer. Is there another/better way?

>
>
> You could temporarily insert a '\0' at position 8 (after
> first saving its value of course). Then sscanf() the int.
> Subsequently restore the saved position 8, and sscanf() the
> float from position 8.


By reversing the scan order (float first), you don't even have
to restore position 8.

Kees

 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      04-22-2004
Brent Lievers wrote:
>
> Greetings,
>
> I have a question about parsing a fixed-width integer from a string.
>
> Lines of data are being read from a file having a very strict
> column-delimited format. In my example below, columns 0-7 are an integer
> and columns 8-23 are a float. In _most_ files, the first few columns of
> the float are blank space to make it human readable. But not always.
> So, once they have been read from the file, I try to parse out the
> different values using something like the following:
>
> /*------------------------------------------*/
> #include <stdio.h>
> #include <stdlib.h>
>
> int main()
> {
> char line1[]= " 12 15.796473824857";
> char line2[]= " 1215.7964738248571";
> int id;
> float num;
>
> sscanf(line1, "%8d%16E", &id, &num);
> printf("ID= %d\n", id);
> printf("NUM= %f\n\n", num);
>
> sscanf(line2, "%8d%16E", &id, &num);
> printf("ID= %d\n", id);
> printf("NUM= %f\n", num);
>
> return EXIT_SUCCESS;
> }
> /*------------------------------------------*/
>
> which works in one case and not the other.
>
> I could read the first 8 columns as characters and strtol() them to an
> integer. Is there another/better way?


The problem is with those leading blank spaces: the
"%8d" conversion swallows them *without* counting them
as part of the 8-character field width, so the 8-character
count begins with the first digit encountered. Since the
number of leading spaces (and other whitespace, like the
'\n' at the end of a preceding input line) is variable, you
don't know what field width to use to make the conversion
stop at the desired spot. I can think of no way to get this
to work with just one application of sscanf().

If I were doing this, I'd start by reading the entire line
into a buffer. Then I'd use strtod() to convert the second
number first. Then I'd stuff a '\0' into the buffer at the
eighth position and use strtol() to convert the first number.
(You could use sscanf() in place of both strxxx() functions,
if desired.)

By the way, what's the "%16E" conversion? I've assumed
above that it's something akin to "%16e", but if it's more
esoteric you may need something fancier than strtod() to
imitate it.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Dan Pop
Guest
Posts: n/a
 
      04-22-2004
In <c68p9l$ech$(E-Mail Removed)> Brent Lievers <(E-Mail Removed)> writes:

>I have a question about parsing a fixed-width integer from a string.
>
>Lines of data are being read from a file having a very strict
>column-delimited format. In my example below, columns 0-7 are an integer
>and columns 8-23 are a float. In _most_ files, the first few columns of
>the float are blank space to make it human readable. But not always.
>So, once they have been read from the file, I try to parse out the
>different values using something like the following:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main()
> {
> char line1[]= " 12 15.796473824857";
> char line2[]= " 1215.7964738248571";
> int id;
> float num;
>
> sscanf(line1, "%8d%16E", &id, &num);


"%8d" means: skip any white space characters in the input, then convert
at most 8 digits. It's obvious that this is not going to work for line2,
as the conversion will stop at the decimal point.

To solve the problem, we need two sscanf calls and a char buffer for the
integer input:

char buff[8 + 1] = { 0 };

sscanf(line1, "%8c%16E", buff, &num);
sscanf(buff, "%d", &id); /* or id = atoi(buff); */

You may also want to check the return values of the sscanf calls, to be
sure that the input was OK and you're not propagating garbage into the
rest of the program.

Other solutions require an additional statement and destroy a byte of
input data (can be restored, if necessary), but may have a lower overall
overhead:

num = atof(line1 + ;
line1[8] = 0;
id = atoi(line1);

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: (E-Mail Removed)
 
Reply With Quote
 
Brent Lievers
Guest
Posts: n/a
 
      04-23-2004
Brent Lievers <(E-Mail Removed)> wrote:
> I have a question about parsing a fixed-width integer from a string.


<snip>

Thanks to everyone for your responses!

Brent
 
Reply With Quote
 
Dan Pop
Guest
Posts: n/a
 
      04-23-2004
In <(E-Mail Removed)> Eric Sosman <(E-Mail Removed)> writes:

> By the way, what's the "%16E" conversion? I've assumed
>above that it's something akin to "%16e", but if it's more
>esoteric you may need something fancier than strtod() to
>imitate it.


14 The conversion specifiers A, E, F, G, and X are also valid and
behave the same as, respectively, a, e, f, g, and x.

or, if you prefer the C89 version:

The conversion specifiers E, G, and X are also valid and behave
the same as, respectively, e, g, and x.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: (E-Mail Removed)
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      04-23-2004
Dan Pop wrote:
>
> In <(E-Mail Removed)> Eric Sosman <(E-Mail Removed)> writes:
>
> > By the way, what's the "%16E" conversion? I've assumed
> >above that it's something akin to "%16e", but if it's more
> >esoteric you may need something fancier than strtod() to
> >imitate it.

>
> 14 The conversion specifiers A, E, F, G, and X are also valid and
> behave the same as, respectively, a, e, f, g, and x.
>
> or, if you prefer the C89 version:
>
> The conversion specifiers E, G, and X are also valid and behave
> the same as, respectively, e, g, and x.


Aha! Thanks for the information. (Why do you suppose
the fprintf() description lists and describes the upper- and
lower-case specifiers together, while fscanf() shows only the
lower-case forms in the big list and relegates the upper-case
to a separate paragraph? Was the Committee trying to make a
point about the asymmetry of fprintf() and fscanf()?).

--
(E-Mail Removed)
 
Reply With Quote
 
Dan Pop
Guest
Posts: n/a
 
      04-26-2004
In <(E-Mail Removed)> Eric Sosman <(E-Mail Removed)> writes:

>Dan Pop wrote:
>>
>> In <(E-Mail Removed)> Eric Sosman <(E-Mail Removed)> writes:
>>
>> > By the way, what's the "%16E" conversion? I've assumed
>> >above that it's something akin to "%16e", but if it's more
>> >esoteric you may need something fancier than strtod() to
>> >imitate it.

>>
>> 14 The conversion specifiers A, E, F, G, and X are also valid and
>> behave the same as, respectively, a, e, f, g, and x.
>>
>> or, if you prefer the C89 version:
>>
>> The conversion specifiers E, G, and X are also valid and behave
>> the same as, respectively, e, g, and x.

>
> Aha! Thanks for the information. (Why do you suppose
>the fprintf() description lists and describes the upper- and
>lower-case specifiers together, while fscanf() shows only the
>lower-case forms in the big list and relegates the upper-case
>to a separate paragraph? Was the Committee trying to make a
>point about the asymmetry of fprintf() and fscanf()?).


In fprintf, the behaviour is different. In fscanf, the behaviour is
identical, so fprintf and fscanf *are* assymetrical

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: (E-Mail Removed)
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
sscanf question sieg1974@yahoo.com C Programming 5 11-23-2006 07:39 PM
How to sscanf return integer only Yogi_Bear_79 C Programming 17 05-22-2006 12:45 AM
Programmer wannabee question about sscanf broeisi C Programming 10 03-05-2006 05:16 AM
sscanf() question? jchludzinski@gmail.com C Programming 5 06-09-2005 05:45 PM
Question on sscanf Dan Smith C Programming 3 08-14-2003 12:42 AM



Advertisments