Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Help with sscanf()

Reply
Thread Tools

Help with sscanf()

 
 
Default User
Guest
Posts: n/a
 
      02-28-2005
I'm need to do some parsing of a line from a config file. The data
structure is:

typedef struct
{
unsigned int version;
unsigned char timestamp[8];
unsigned int num_clients;
unsigned int num_msgs;
unsigned int num_channels;
unsigned int num_minor_frames;
float minor_frame_time;
float ex_capacity;
} M1553_Config_File_T;


An example string from the file would be:

"001 2005022718023400 1 3 2 4 0.05 0.001";

Most of it isn't a problem reading via sscanf(), except for the
timestamp.

2005022718023400 is a time stamp of the form YYYYMMDDHHMMSSTZ. I'm
trying to store it in that array in the struct, such that:

timestamp[0] == 20;
timestamp[1] == 5;
timestamp[2] == 2;
timestamp[3] == 27;
timestamp[4] == 18;
timestamp[5] == 2;
timestamp[6] == 34;
timestamp[7] == 0;

Right now I'm scanning the timestamp values into a temp array of
unsigned int with a bunch of %02u sequences, then copying all those
values to the array in the struct. Works, but a bit messy.

unsigned int timestamp[8];

stat = sscanf(str,
"%u%02u%02u%02u%02u%02u%02u%02u%02u%u%u%u%u%f% f",
&(config->version),
&(timestamp[0]),
&(timestamp[1]),
&(timestamp[2]),
&(timestamp[3]),
&(timestamp[4]),
&(timestamp[5]),
&(timestamp[6]),
&(timestamp[7]),
&(config->num_clients),
&(config->num_msgs),
&(config->num_channels),
&(config->num_minor_frames),
&(config->minor_frame_time),
&(config->ex_capacity)) == NUM_HEADER_FIELDS ? 0 : -1;
#ifdef DEBUG
if (stat == -1)
{
printf("read_header_record: Error interpreting %s\n",
str);
}
#endif
for (i=0; i < 8; i++)
config->timestamp[i] = timestamp[i];

I'd like to do it directly via sscanf() but haven't come up with a scan
sequence. Some of you guys are hot-shot scanf() wizzes. Any ideas on a
magic (but safe and portable) way to do this?



Brian

 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      02-28-2005


Default User wrote:
> I'm need to do some parsing of a line from a config file. The data
> structure is:
>
> typedef struct
> {
> unsigned int version;
> unsigned char timestamp[8];
> unsigned int num_clients;
> unsigned int num_msgs;
> unsigned int num_channels;
> unsigned int num_minor_frames;
> float minor_frame_time;
> float ex_capacity;
> } M1553_Config_File_T;
>
>
> An example string from the file would be:
>
> "001 2005022718023400 1 3 2 4 0.05 0.001";
>
> Most of it isn't a problem reading via sscanf(), except for the
> timestamp.
>
> 2005022718023400 is a time stamp of the form YYYYMMDDHHMMSSTZ. I'm
> trying to store it in that array in the struct, such that:
>
> timestamp[0] == 20;
> timestamp[1] == 5;
> timestamp[2] == 2;
> timestamp[3] == 27;
> timestamp[4] == 18;
> timestamp[5] == 2;
> timestamp[6] == 34;
> timestamp[7] == 0;
>
> Right now I'm scanning the timestamp values into a temp array of
> unsigned int with a bunch of %02u sequences, then copying all those
> values to the array in the struct. Works, but a bit messy.
> [...]


If you have a C99 implementation, you can use the "hh"
length modifier as "%2hhu%2hhu..." and supply pointers to
the individual array elements: &config->timestamp[0],
&config->timestamp[1], ...

To the best of my knowledge, C89 *scanf() cannot do
what you want. However, your trick of scanning into an
intermediate variable and assigning to the array need not
be quite as verbose as the code you posted (see up-thread).
There is no requirement to scan an entire line in one gulp,
so you can do (error-checking omitted):

char *p = str + offset_of_first_timestamp_char;
int i;
for (i = 0; i < 8; p += 2, ++i) {
unsigned int temp;
sscanf(p, "%2u", &temp);
config->timestamp[i] = temp;
}

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
 
 
 
Default User
Guest
Posts: n/a
 
      02-28-2005

Eric Sosman wrote:
> Default User wrote:
> > I'm need to do some parsing of a line from a config file.


> > Right now I'm scanning the timestamp values into a temp array of
> > unsigned int with a bunch of %02u sequences, then copying all those
> > values to the array in the struct. Works, but a bit messy.
> > [...]

>
> If you have a C99 implementation, you can use the "hh"
> length modifier as "%2hhu%2hhu..." and supply pointers to
> the individual array elements: &config->timestamp[0],
> &config->timestamp[1], ...


I don't.

> To the best of my knowledge, C89 *scanf() cannot do
> what you want. However, your trick of scanning into an
> intermediate variable and assigning to the array need not
> be quite as verbose as the code you posted (see up-thread).
> There is no requirement to scan an entire line in one gulp,
> so you can do (error-checking omitted):
>
> char *p = str + offset_of_first_timestamp_char;


As I don't know for certain what the offset would be, that sounds
brittle.

> int i;
> for (i = 0; i < 8; p += 2, ++i) {
> unsigned int temp;
> sscanf(p, "%2u", &temp);
> config->timestamp[i] = temp;
> }



I'll probably leave it as is.

Thanks.



Brian

 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-28-2005


Default User wrote:
> Eric Sosman wrote:
>> [...]
>> To the best of my knowledge, C89 *scanf() cannot do
>>what you want. However, your trick of scanning into an
>>intermediate variable and assigning to the array need not
>>be quite as verbose as the code you posted (see up-thread).
>>There is no requirement to scan an entire line in one gulp,
>>so you can do (error-checking omitted):
>>
>> char *p = str + offset_of_first_timestamp_char;

>
>
> As I don't know for certain what the offset would be, that sounds
> brittle.


The "%n" specifier is often helpful for this sort
of thing.

--
(E-Mail Removed)

 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      03-01-2005

Eric Sosman wrote:
> Default User wrote:


> > As I don't know for certain what the offset would be, that sounds
> > brittle.

>
> The "%n" specifier is often helpful for this sort of thing.


Indeed it was. Here's what I ended up with, after incorporating your
previous suggestions:

int read_header_record(M1553_Config_File_T *config)
{
int stat = 0;
int i;
int offset;
const char *p;
int fields;

/* scan the version, then skip whitespace up to the next field
record how many characters were scanned */

fields = sscanf(str,"%u %n", &(config->version), &offset);

p = str + offset;

for (i = 0; i < 8; p += 2, ++i)
{
unsigned int temp;
fields += sscanf(p, "%2u", &temp);
config->timestamp[i] = temp;
}

fields += sscanf(p,
"%u%u%u%u%f%f",
&(config->num_clients),
&(config->num_msgs),
&(config->num_channels),
&(config->num_minor_frames),
&(config->minor_frame_time),
&(config->ex_capacity));

if (fields != NUM_HEADER_FIELDS)
{
stat = -1;
}

return stat;
}

Some of the man pages for scanf() had this to say about %n, "Probably
it is wise not to make any assumptions on the effect of %n conversions
on the return value."

This was initially a concern. However, the C89 and C99 draft standards
indicated that this should not be a problem, so I didn't break the
"skip step" into a separate scan.


Thanks, Eric.


Brian

 
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
Help Help Help Pentax S5i Help needed (Please) The Martian Digital Photography 14 06-20-2008 07:56 AM
HELP - HELP - HELP =?Utf-8?B?S2ltb24gSWZhbnRpZGlz?= ASP .Net 4 03-09-2006 12:46 PM
HELP WANTED HELP WANTED HELP WANTED Harvey ASP .Net 1 07-16-2004 01:12 PM
HELP WANTED HELP WANTED HELP WANTED Harvey ASP .Net 0 07-16-2004 10:00 AM
HELP! HELP! HELP! Opening Web Application Project Error =?Utf-8?B?dHJlbGxvdzQyMg==?= ASP .Net 0 02-20-2004 05:16 PM



Advertisments