strtok problem

R

Ram Laxman

Hi all,
I have written the following code:


/* strtok example */
#include <stdio.h>
#include <string.h>

static const char * const resultFileName = "param.txt";

int main ()
{

FILE *fPtr;
char str[300];
char * pch;
int len;
char savedstr[300];

fPtr =fopen(resultFileName, "r");

if(fPtr == NULL)
{
printf("File doesnot exist");
return 1;
}

else
{
while(!feof(fPtr))
{
fgets(str,288,fPtr);
len = strlen(str);
str[len-1]=0;
for ( (pch=strtok(str,","));(pch = strtok(NULL,","));(pch
!=NULL))
{
strncpy(savedstr,pch,len);
printf("Saved String =%s\n",savedstr);
}


}

}

fclose(fPtr);
return 0;

}

I have a text file as the following:
param.txt:

"ram","lax","deepak"
10,20,30
40,80,100
70,90,100
and so on...

When I use strtok(delim ,) the problem is that the string "ram" never
gets stored in savedstr array while from "lax" onwards it gets stored.

1.Could any body suggest a better method so that I can store "ram"
also in the saved string and tokenize based on comma separated
delimiter?

2.Is there anything in C like (map in C++) so that I can store:

(key)
"ram"---->10,40,70(In an array of integer values)
"lax"---->20,80,90

Could anybody help me in this regard?

Regards
Ram Laxman
 
S

Sam Dennis

Ram said:
for (pch = strtok(str, ","); pch = strtok(NULL, ","); pch != NULL)

You almost certainly meant to swap the last two expressions.

for (a;b;c) {...} is equivilant to a; while (b) {{...} c;}
while(!feof(fPtr))

This is generally quite a bad idea in C; in your case...
{
fgets(str,288,fPtr);

A file ending with a new-line character will loop once more, but is
already at the end of the file; str is untouched and you repeat the
processing, which is probably not what you want.

while(fgets(str, 288, fPtr)) might be more appropriate.
str[strlen(str)-1]=0;

If the file does not end with a new-line character, this drops what
would've been the last character of the line; a check that the last
character is a new-line before overwriting it or that feof(fPtr) is
not true will prevent such behaviour.
return 1;

You might like to change this to EXIT_FAILURE, from <stdlib.h>, for
a portable interpretation.
 
A

Al Bowers

Ram said:
Hi all,
I have written the following code:


/* strtok example */
#include <stdio.h>
#include <string.h>

static const char * const resultFileName = "param.txt";

int main ()
{

FILE *fPtr;
char str[300];
char * pch;
int len;
char savedstr[300];

fPtr =fopen(resultFileName, "r");

if(fPtr == NULL)
{
printf("File doesnot exist");
return 1;
}

else
{
while(!feof(fPtr))
{
fgets(str,288,fPtr);
len = strlen(str);
str[len-1]=0;
for ( (pch=strtok(str,","));(pch = strtok(NULL,","));(pch
!=NULL))
{
strncpy(savedstr,pch,len);
printf("Saved String =%s\n",savedstr);
}


}

}

fclose(fPtr);
return 0;

}

I have a text file as the following:
param.txt:

"ram","lax","deepak"
10,20,30
40,80,100
70,90,100
and so on...

When I use strtok(delim ,) the problem is that the string "ram" never
gets stored in savedstr array while from "lax" onwards it gets stored.

1.Could any body suggest a better method so that I can store "ram"
also in the saved string and tokenize based on comma separated
delimiter?

The method you are using is not bad although I personally don't
like using fixed sizes like str[300], savedstr[300] when you are
storing into them data from a file. However, using these fixed
sizes makes the coding easier(IMO). The major problems in your
code is that you need to change the declaraion of savedstr to something
like char savedstr[MAXSTRINGS][MAXPARM+1] where the macros have
been appropriated defined. Also, you loop using feof is not
neccessary. You can loop with function fgets. fgets will return
NULL should the end of the file be encountered and there have
been no characters read into the character array.

To salvage your code make these changes mentioned:

/* strtok example */
#include <stdio.h>
#include <string.h>

#define MAXLINE 100
#define MAXSTRINGS 300
#define MAXPARM 30

static const char * const resultFileName = "param.txt";

int main (void)
{
FILE *fPtr;
char str[MAXLINE];
char * pch;
size_t i, count;
char savedstr[MAXSTRINGS][MAXPARM+1];

fPtr =fopen(resultFileName, "r");

if(fPtr == NULL)
{
printf("File doesnot exist");
return 1;
}
for(count = 0; (fgets(str,288,fPtr)) && count != MAXSTRINGS; )
for (pch=strtok(str,",");pch; pch = strtok(NULL,","))
{
strncpy(savedstr[count],pch,MAXPARM);
savedstr[count++][MAXPARM] = '\0';
}
fclose(fPtr);
for(i = 0 ;i < count;i++)
printf("savedstr[%u] = %s\n",i,savedstr);
return 0;
}

2.Is there anything in C like (map in C++) so that I can store:

(key)
"ram"---->10,40,70(In an array of integer values)
"lax"---->20,80,90

Could anybody help me in this regard?

This makes the code a little more complicated. You should
probably create datatypes to store the data parsed from the file.
The actucal code depends on how the data is stored in the file.
In the following example, the contents in param.txt is:
"ram",10,20,30
"lax",40,80,100,500
"deepak",70,90,100,30,11

And the code(little tested) to parse the data in the file gives
the output:
Parm Name is "ram"
The values are: 10 20 30

Parm Name is "lax"
The values are: 40 80 100 500

Parm Name is "deepak"
The values are: 70 90 100 30 11

The code:
/* strtok example */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXLINE 100
#define MAXPARM 30

typedef struct PARM
{
char parmname[MAXPARM+1];
int *parmvalue;
size_t valuecount;
} PARM;

typedef struct PARM_ARR
{
PARM *parm;
size_t parmcount;
} PARM_ARR;

PARM init;

int parseline(PARM_ARR *p, FILE *fp);
void freePARM_ARR(PARM_ARR *p);
void printPARM( PARM *p);

static const char * const resultFileName = "param.txt";

int main (void)
{
FILE *fPtr;
size_t i;
PARM_ARR my = {NULL};

fPtr =fopen(resultFileName, "r");
if(fPtr == NULL)
{
printf("File doesnot exist");
return 1;
}
while(parseline(&my,fPtr)) ;
fclose(fPtr);
for(i = 0; i < my.parmcount; i++)
printPARM(&my.parm);
freePARM_ARR(&my);
return 0;
}

int parseline(PARM_ARR *p, FILE *fp)
{ /* TODO: write more robust code to validate file data */
char *s,buf[MAXLINE];
size_t count;
PARM *tmp;
int *itmp;

while(1)
{ /* skip empty? line */
if(!fgets(buf,sizeof buf,fp)) return 0;
if(*buf != '\n') break;
}
tmp = realloc(p->parm,(p->parmcount+1)*(sizeof *tmp));
if(!tmp) return 0;
p->parm = tmp;
p->parm[p->parmcount] = init;
for(count = 0,s = strtok(buf,","); s ;
s = strtok(NULL,","), count++)
{
if(count == 0)
{
strncpy(p->parm[p->parmcount].parmname,s,MAXPARM);
p->parm[p->parmcount].parmname[MAXPARM] = '\0';
}
else
{
itmp = realloc(p->parm[p->parmcount].parmvalue,
(p->parm[p->parmcount].valuecount+1)*(sizeof *itmp));
if(!itmp) return 0;
p->parm[p->parmcount].parmvalue = itmp;
p->parm[p->parmcount].parmvalue[p->parm[p->parmcount].
valuecount++] =(int)strtol(s,NULL,10);
}
}
p->parmcount++;
return 1;
}

void freePARM_ARR(PARM_ARR *p)
{
size_t i;

for(i = 0;i < p->parmcount;i++)
free(p->parm.parmvalue);
free(p->parm);
p->parm = NULL;
p->parmcount = 0;
return;
}
void printPARM( PARM *p)
{
size_t i;

printf("Parm Name is %s\nThe values are: ", p->parmname);
for(i = 0;i < p->valuecount;i ++)
printf("%d ",p->parmvalue);
puts("\n");
return;
}
 
R

Ram Laxman

Thanks Al Bowers,

But I see I could able to store only "A"--->10,40. But could not able to store
"B"---->20,80 and "C"-->30,100 in the array.

Regards
Ram Laxman


Al Bowers said:
Ram said:
Hi all,
I have written the following code:


/* strtok example */
#include <stdio.h>
#include <string.h>

static const char * const resultFileName = "param.txt";

int main ()
{

FILE *fPtr;
char str[300];
char * pch;
int len;
char savedstr[300];

fPtr =fopen(resultFileName, "r");

if(fPtr == NULL)
{
printf("File doesnot exist");
return 1;
}

else
{
while(!feof(fPtr))
{
fgets(str,288,fPtr);
len = strlen(str);
str[len-1]=0;
for ( (pch=strtok(str,","));(pch = strtok(NULL,","));(pch
!=NULL))
{
strncpy(savedstr,pch,len);
printf("Saved String =%s\n",savedstr);
}


}

}

fclose(fPtr);
return 0;

}

I have a text file as the following:
param.txt:

"ram","lax","deepak"
10,20,30
40,80,100
70,90,100
and so on...

When I use strtok(delim ,) the problem is that the string "ram" never
gets stored in savedstr array while from "lax" onwards it gets stored.

1.Could any body suggest a better method so that I can store "ram"
also in the saved string and tokenize based on comma separated
delimiter?

The method you are using is not bad although I personally don't
like using fixed sizes like str[300], savedstr[300] when you are
storing into them data from a file. However, using these fixed
sizes makes the coding easier(IMO). The major problems in your
code is that you need to change the declaraion of savedstr to something
like char savedstr[MAXSTRINGS][MAXPARM+1] where the macros have
been appropriated defined. Also, you loop using feof is not
neccessary. You can loop with function fgets. fgets will return
NULL should the end of the file be encountered and there have
been no characters read into the character array.

To salvage your code make these changes mentioned:

/* strtok example */
#include <stdio.h>
#include <string.h>

#define MAXLINE 100
#define MAXSTRINGS 300
#define MAXPARM 30

static const char * const resultFileName = "param.txt";

int main (void)
{
FILE *fPtr;
char str[MAXLINE];
char * pch;
size_t i, count;
char savedstr[MAXSTRINGS][MAXPARM+1];

fPtr =fopen(resultFileName, "r");

if(fPtr == NULL)
{
printf("File doesnot exist");
return 1;
}
for(count = 0; (fgets(str,288,fPtr)) && count != MAXSTRINGS; )
for (pch=strtok(str,",");pch; pch = strtok(NULL,","))
{
strncpy(savedstr[count],pch,MAXPARM);
savedstr[count++][MAXPARM] = '\0';
}
fclose(fPtr);
for(i = 0 ;i < count;i++)
printf("savedstr[%u] = %s\n",i,savedstr);
return 0;
}

2.Is there anything in C like (map in C++) so that I can store:

(key)
"ram"---->10,40,70(In an array of integer values)
"lax"---->20,80,90

Could anybody help me in this regard?

This makes the code a little more complicated. You should
probably create datatypes to store the data parsed from the file.
The actucal code depends on how the data is stored in the file.
In the following example, the contents in param.txt is:
"ram",10,20,30
"lax",40,80,100,500
"deepak",70,90,100,30,11

And the code(little tested) to parse the data in the file gives
the output:
Parm Name is "ram"
The values are: 10 20 30

Parm Name is "lax"
The values are: 40 80 100 500

Parm Name is "deepak"
The values are: 70 90 100 30 11

The code:
/* strtok example */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXLINE 100
#define MAXPARM 30

typedef struct PARM
{
char parmname[MAXPARM+1];
int *parmvalue;
size_t valuecount;
} PARM;

typedef struct PARM_ARR
{
PARM *parm;
size_t parmcount;
} PARM_ARR;

PARM init;

int parseline(PARM_ARR *p, FILE *fp);
void freePARM_ARR(PARM_ARR *p);
void printPARM( PARM *p);

static const char * const resultFileName = "param.txt";

int main (void)
{
FILE *fPtr;
size_t i;
PARM_ARR my = {NULL};

fPtr =fopen(resultFileName, "r");
if(fPtr == NULL)
{
printf("File doesnot exist");
return 1;
}
while(parseline(&my,fPtr)) ;
fclose(fPtr);
for(i = 0; i < my.parmcount; i++)
printPARM(&my.parm);
freePARM_ARR(&my);
return 0;
}

int parseline(PARM_ARR *p, FILE *fp)
{ /* TODO: write more robust code to validate file data */
char *s,buf[MAXLINE];
size_t count;
PARM *tmp;
int *itmp;

while(1)
{ /* skip empty? line */
if(!fgets(buf,sizeof buf,fp)) return 0;
if(*buf != '\n') break;
}
tmp = realloc(p->parm,(p->parmcount+1)*(sizeof *tmp));
if(!tmp) return 0;
p->parm = tmp;
p->parm[p->parmcount] = init;
for(count = 0,s = strtok(buf,","); s ;
s = strtok(NULL,","), count++)
{
if(count == 0)
{
strncpy(p->parm[p->parmcount].parmname,s,MAXPARM);
p->parm[p->parmcount].parmname[MAXPARM] = '\0';
}
else
{
itmp = realloc(p->parm[p->parmcount].parmvalue,
(p->parm[p->parmcount].valuecount+1)*(sizeof *itmp));
if(!itmp) return 0;
p->parm[p->parmcount].parmvalue = itmp;
p->parm[p->parmcount].parmvalue[p->parm[p->parmcount].
valuecount++] =(int)strtol(s,NULL,10);
}
}
p->parmcount++;
return 1;
}

void freePARM_ARR(PARM_ARR *p)
{
size_t i;

for(i = 0;i < p->parmcount;i++)
free(p->parm.parmvalue);
free(p->parm);
p->parm = NULL;
p->parmcount = 0;
return;
}
void printPARM( PARM *p)
{
size_t i;

printf("Parm Name is %s\nThe values are: ", p->parmname);
for(i = 0;i < p->valuecount;i ++)
printf("%d ",p->parmvalue);
puts("\n");
return;
}
 

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

Similar Threads

strtok problem 16
strtok problem 6
strtok 6
Why does strcat mess up the tokens in strtok (and strtok_r)? 92
strtok ( ) help 13
strtok problem 5
strtok question 6
Help with strtok 8

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top