parsing a file and writing tokens to char array

parsing a file and writing tokens to char array

Post by gaius.petroni » Thu, 29 Aug 2002 19:54:39



(void)memset(&aline[0], '\0', sizeof(aline));
if ((svcs = fopen("/usr/local/etc/anth.svcs", "r")) != NULL) {
        while (fgets(inbuf,  MAXLINES, svcs))
                for (cp = strtok(inbuf, DELIM, svcs), tokenpos = 0, numlines++;
                        cp && tokenpos < MAXTOKENS ;
                        cp = strtok(NULL, DELIM))
                        aline[numlines].atoken[tokenpos++] = strdup(cp);
        fclose(svcs);

Quote:}

the compiler says
Segmentation fault

the warnings were
main.c: In function `main':
main.c:114: warning: passing arg 1 of `strtok' makes pointer from
integer without a cast
main.c:114: warning: passing arg 2 of `strtok' makes pointer from
integer without a cast
main.c:114: too many arguments to function `strtok'
main.c:116: warning: passing arg 2 of `strtok' makes pointer from
integer without a cast

the variables were defined as
#define DELIM '\n'
#define LINE 64
#define MAXTOKENS 32
#define MAXLINES 32
int numlines = 0;
int tokenpos ;
char inbuf[LINE], *cp ;
struct {
        char *atoken[MAXTOKENS];

Quote:} aline[MAXLINES];

  FILE  *host ;
  FILE  *svcs ;
  int   c;
  char token[31];
  char *data[1024];
  char *svcsar[32][32];
  char hostname[64];

i copied this code from the group and modified the variable names
slightly

he said that the data would all be in memory.  however the program
apparently can't make it that far.

i suspect it dies on a strtok

 
 
 

parsing a file and writing tokens to char array

Post by John Gordon,217-352-6511x7418,CEERD-CF- » Thu, 29 Aug 2002 22:46:15



>            for (cp = strtok(inbuf, DELIM, svcs), tokenpos = 0, numlines++;

strtok() generally takes two arguments, both of which should be strings.
you're using three, only one of which is a string.

John Gordon
---
"She even named one city after Robert, her ex-boyfriend, just to annoy
me.  I have it in a saved game on my laptop.  Every now and then I boot
it up just to let Robertville starve itself off the map."  -- Tom Chick

 
 
 

parsing a file and writing tokens to char array

Post by Jens.Toerr.. » Thu, 29 Aug 2002 22:50:29



> (void)memset(&aline[0], '\0', sizeof(aline));

That's a bit dangerous becaus it only will work on architectures
where a NULL pointer is represented by the number 0. Anyway, the
use of '\0' looks a bit fishy anyway and will make other people
reading your program quite nervous because it gives the impression
that you don't distinguish carefully between chars and char pointers.
If you really want to set the arrays of char pointers in aline to NULL
it's probably better to use a loop and set them explicitely. I don't
think that this really will slow down your program significantly.

Quote:> if ((svcs = fopen("/usr/local/etc/anth.svcs", "r")) != NULL) {
>    while (fgets(inbuf,  MAXLINES, svcs))

Are you sure MAX_LINES is correct here? I would suspect you want
something like MAX_CHARS_PER_LINE. You probably also should compare
num_lines with MAX_LINES here and stop if there are too many lines or
your array of aline structures will overflow.

Quote:>            for (cp = strtok(inbuf, DELIM, svcs), tokenpos = 0, numlines++;

1. The second argument to strtok is a char pointer, you can have more
   than one delimeter character. Use '#define DELIM "\n"' instead.
2. strtok() only takes 2 arguments, but you pass it 3.
3. No idea why the compiler complains about the first argument here.

Quote:>                    cp && tokenpos < MAXTOKENS ;
>                    cp = strtok(NULL, DELIM))
>                    aline[numlines].atoken[tokenpos++] = strdup(cp);
>    fclose(svcs);
> }
> the compiler says
> Segmentation fault

Your compiler crashed or did your program crash when you tried to
run it? Did you run it under a de* to find out where it happens?

                                     Regards, Jens
--
      _  _____  _____

  _  | |  | |    | |
 | |_| |  | |    | |          http://www.veryComputer.com/~toerring
  \___/ens|_|homs|_|oerring

 
 
 

parsing a file and writing tokens to char array

Post by Jens.Toerr.. » Thu, 29 Aug 2002 23:07:34




>>   while (fgets(inbuf,  MAXLINES, svcs))
>>                for (cp = strtok(inbuf, DELIM, svcs), tokenpos = 0, numlines++;
> 1. The second argument to strtok is a char pointer, you can have more
>    than one delimeter character. Use '#define DELIM "\n"' instead.
> 2. strtok() only takes 2 arguments, but you pass it 3.
> 3. No idea why the compiler complains about the first argument here.

And another problem: since fgets() stops reading after a newline it won't
work anyway with newline as DELIM, because there's never more than 1
newline in our buffer. Perhaps you should be looking for a different
delimiter, e.g. white-spaces?
                                      Regards, Jens
--
      _  _____  _____

  _  | |  | |    | |
 | |_| |  | |    | |          http://www.physik.fu-berlin.de/~toerring
  \___/ens|_|homs|_|oerring
 
 
 

parsing a file and writing tokens to char array

Post by Friedrich Dominicu » Fri, 30 Aug 2002 01:46:52



> (void)memset(&aline[0], '\0', sizeof(aline));
> if ((svcs = fopen("/usr/local/etc/anth.svcs", "r")) != NULL) {
>    while (fgets(inbuf,  MAXLINES, svcs))
>            for (cp = strtok(inbuf, DELIM, svcs), tokenpos = 0, numlines++;
>                    cp && tokenpos < MAXTOKENS ;
>                    cp = strtok(NULL, DELIM))
>                    aline[numlines].atoken[tokenpos++] = strdup(cp);
>    fclose(svcs);
> }

May I ask why you write such dense code?

Now to the code, others have pointed out the problematic points

a) memset usage does not guarantee to work, suggestoin write a
function clear struct which set the fields. than the call is simply
clear_some_struct(&aline); which looks IMHO very nice.

b) what will happen if fopen fails? Won't you check for errors?
suggestion
svcs = fopne ...
if (NULL == scvs){
   error_handling

Quote:}

c) fgets just reads till it ecounters a '\n'. So you will always have
all the string on the first call. The whole strtok stuff doese therfor
do not much sense.

d) you might be better of not writing so much into the for head. It
makes it IMHO much more difficult to follow. suggestion:
cp = strtok (line, DELIMITERS)
while (NULL != cp){
   ...
   cp = strtok (NULL, DELIMITERS);

Quote:}

e) this is probaly a matter of taste. But how about hiding the
Datastructure details and not to access those things directly? It could
pay off soonner than you believe.

f) what happens if strdup fails?

Quote:

> the compiler says
> Segmentation fault

> the warnings were
> main.c: In function `main':
> main.c:114: warning: passing arg 1 of `strtok' makes pointer from
> integer without a cast
> main.c:114: warning: passing arg 2 of `strtok' makes pointer from
> integer without a cast
> main.c:114: too many arguments to function `strtok'
> main.c:116: warning: passing arg 2 of `strtok' makes pointer from
> integer without a cast

> the variables were defined as
> #define DELIM '\n'
> #define LINE 64
> #define MAXTOKENS 32
> #define MAXLINES 32
> int numlines = 0;
> int tokenpos ;
> char inbuf[LINE], *cp ;
> struct {
>    char *atoken[MAXTOKENS];
> } aline[MAXLINES];
>   FILE  *host ;
>   FILE  *svcs ;
>   int   c;

g) I would suggest not using "magic" numbers but 0 and 1 you have you
constants define above. I would use them here and add the missing
ones.

Quote:>   char token[31];
>   char *data[1024];
>   char *svcsar[32][32];
>   char hostname[64];

> i copied this code from the group and modified the variable names
> slightly

> he said that the data would all be in memory.  however the program
> apparently can't make it that far.

> i suspect it dies on a strtok

Well strtok just takes two parameters. You compiler does warn you.

May I suggest too to check you code with splint? You'll write better
code while using it.

Regards
Friedrich

 
 
 

1. fprintf() over-writes line for line (rather than char for char)?

Hi all,

    If I fseek() into the middle of a text file and start fprintf(),
then it seems that each new character over-writes a single old one.
if I start from the beginning of a line of 60 characters, and
fprintf() 80 characters, then the 60 characters are over-written
(which is what I wanted), and in addition, 20 more characters
in the next line are also over-written (which is NOT what I wanted).
I would prefer fprintf() leaves the next line alone.

    Is there a method by which I have what I wanted (line-for-line
over-writing, and do not have what I do not want? I tried this
on AIX (cc).

    Any help and pointers are appreciated. Thanks in advance,

Mingzuo Shen

2. 100 dpi fonts issues

3. How to parse and write a .XXrc file?

4. Something to think about...

5. Q: writing char data with write()

6. Where do you want Linux to go today?

7. read/write array to file with csh (tcsh)

8. FreeBSD and Windows XP

9. reversing lines char by char, but not the line order in a file

10. drivers/char/Kconfig:640: can't open file "drivers/char/ipmi/Kconfig"

11. How to grab a token from a line in file then compute all of these tokens

12. char *strcasestr(char *haystack, char *needle) a simple case independent strstr()

13. parsing command line: array problems