sscanf help

J

JoeT

Hello all...

I have to read in formatted input records that were generated on a
mainframe computer.
Each record is 80-characters long and divided up into 'fields' of some
specified length.
A synthetic record is shown below:


Problem I have is I have no idea how to write the format statement in
a sscanf to read this record (or those like it). I can't seem to
sscanf even the first 'field', since that has embedded blanks and %s
won't work and %36c didn't work. So...in short, I'm stumped.

Any assistance here would be appreciated.

Thanks,
Joe
 
S

Seebs

I have to read in formatted input records that were generated on a
mainframe computer.
Each record is 80-characters long and divided up into 'fields' of some
specified length.
A synthetic record is shown below:



Problem I have is I have no idea how to write the format statement in
a sscanf to read this record (or those like it). I can't seem to
sscanf even the first 'field', since that has embedded blanks and %s
won't work and %36c didn't work. So...in short, I'm stumped.

Don't use sscanf, it is the wrong tool for the job. There are few jobs
for which sscanf is the right tool.

Since you know the format, I'd suggest that you copy chunks of it
out and then parse them separately; if you need to parse numbers, look
at strtol().

-s
 
C

Chad

Don't use sscanf, it is the wrong tool for the job.  There are few jobs
for which sscanf is the right tool.

Since you know the format, I'd suggest that you copy chunks of it
out and then parse them separately; if you need to parse numbers, look
at strtol().


I got this really ugly solution using sscanf()....

[cdalten@localhost oakland]$ more data
userName 01 02 03 agency 4
01

[cdalten@localhost oakland]$ more drunk.c
#include <stdio.h>
#include <stdlib.h>

#define PATH "/home/cdalten/oakland/data"
#define MAX_SIZE 81

int main(void)
{
FILE *fp;
int n;
char buf[BUFSIZ], pattern[MAX_SIZE];
char name[MAX_SIZE], data1[MAX_SIZE], data2[MAX_SIZE],
data3[MAX_SIZE], \
agency[MAX_SIZE], data4[MAX_SIZE], data5[MAX_SIZE];

if ((fp = fopen(PATH, "r")) == NULL) {
fprintf(stderr, "Can't open data file\n");
exit(1);
}
sprintf(pattern, "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", \
MAX_SIZE-1, MAX_SIZE-1, MAX_SIZE-1, MAX_SIZE-1, MAX_SIZE-1,
\
MAX_SIZE-1, MAX_SIZE-1);
while (fgets(buf, BUFSIZ, fp) != NULL) {
n = sscanf(buf, pattern, name, data1, data2, data3, agency, data4,
data5);
if(n == 7)
printf("The line is: %s %s %s %s %s %s %s\n", \
name, data1, data2, data3, agency, data4, data5);
}

fclose(fp);
exit(0);
}
[cdalten@localhost oakland]$ ./drunk
The line is: userName 01 02 03 agency 4 01
[cdalten@localhost oakland]$
 
C

Chad

I got this really ugly solution using sscanf()....

[cdalten@localhost oakland]$ more data
    userName                     01  02  03   agency             4
01

[cdalten@localhost oakland]$ more drunk.c
#include <stdio.h>
#include <stdlib.h>

#define PATH "/home/cdalten/oakland/data"
#define MAX_SIZE 81

int main(void)
{
  FILE *fp;
  int n;
  char buf[BUFSIZ], pattern[MAX_SIZE];
  char name[MAX_SIZE], data1[MAX_SIZE], data2[MAX_SIZE],
data3[MAX_SIZE], \
    agency[MAX_SIZE], data4[MAX_SIZE], data5[MAX_SIZE];

  if ((fp = fopen(PATH, "r")) == NULL) {
    fprintf(stderr, "Can't open data file\n");
    exit(1);
  }
  sprintf(pattern, "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", \
          MAX_SIZE-1, MAX_SIZE-1, MAX_SIZE-1, MAX_SIZE-1, MAX_SIZE-1,
\
          MAX_SIZE-1, MAX_SIZE-1);
  while (fgets(buf, BUFSIZ, fp) != NULL) {
    n = sscanf(buf, pattern, name, data1, data2, data3, agency, data4,
data5);
    if(n == 7)
      printf("The line is: %s %s %s %s %s %s %s\n", \
             name, data1, data2, data3, agency, data4, data5);
  }

  fclose(fp);
  exit(0);}

[cdalten@localhost oakland]$ ./drunk
The line is: userName 01 02 03 agency 4 01
[cdalten@localhost oakland]$

And for whatever reasons, I seem to have on going issues with tabs vs
spaces with my current editor.
 
M

Mark

Seebs said:
Don't use sscanf, it is the wrong tool for the job. There are few jobs
for which sscanf is the right tool.

Could you tell what are the main cons and pros of using 'sscanf' ? Does
your comment concern *only* sscanf, but not scanf/fscanf ?
 
S

Seebs

Could you tell what are the main cons and pros of using 'sscanf' ? Does
your comment concern *only* sscanf, but not scanf/fscanf ?

Actually, it's much more true of scanf/fscanf. By contrast, sscanf is
pretty livable.

Basically, scanf has to make too many assumptions (e.g., skipping
whitespace automatically) to be at all functional, meaning that it is
full of surprising behaviors and corner cases. It is nearly always
safer to just write your own string-parsing code, or to use the str*()
functions.

-s
 
N

Nick Keighley

And for whatever reasons, I seem to have on going issues with tabs vs
spaces with my current editor.

configure your editor so it replaces tabs with spaces
 
D

David Thompson

I have to read in formatted input records that were generated on a
mainframe computer.
Each record is 80-characters long and divided up into 'fields' of some
specified length.
A synthetic record is shown below:



Problem I have is I have no idea how to write the format statement in
a sscanf to read this record (or those like it). I can't seem to
sscanf even the first 'field', since that has embedded blanks and %s
won't work and %36c didn't work. So...in short, I'm stumped.
Yes, %s won't work for embedded (or leading) blanks.

%36c should work assuming 36 is the correct length (which it looks to
be), and you give it a buffer to store to that is (at least) 36 chars.
Or if you want to use the result as a string in C, the buffer must be
(at least) 1 more char and you must put a terminating null=zero byte
there yourself, %c doesn't add it for you (as %s and %[..] do).
(You can, and some people do, just fill the buffer with nulls first
before putting in the data. That's a bit wasteful, but simple.)

And assuming of course that you have the correct record in the buffer
you're scanning from. And that does need to be null-terminated, so
that buffer needs to be (at least) 80+1.

There are other ways to do this, as noted, but that doesn't mean that
sscanf is impossible or inherently wrong. If you still have this
problem, post actual code, as small as you can make it, that
demonstrates the problem. For example, have a buffer initialized to a
fixed string which is an example record, and show the sscanf(s) you
are trying to do from it, what you get, and what you expected.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top