Search code examples
cstrtok

How to copy the returned token by strtok in c


When I try to copy the strtok through strcpy as suggested by the other answers on this forum. I don't get the respective number. File format is something like this 43,789,127.0.0.1 on each particular line. However I get 127 in the temp[2] location which should be 127.0.0.1 . What am I missing over here?

FILE *f = fopen("somefile", "r");
char *temp[3];
temp[0] = malloc(20);
temp[1] = malloc(20);
temp[2] = malloc(20);
const char s[1] = ",";
char *pch;
if(f != NULL)
{
  char line[1024];
  while(fgets(line, sizeof line, f) != NULL)
  {
    pch = strtok(line, s);
    for(int i = 0; i<3; i++)
    {
      strcpy(temp[i],pch);
      pch = strtok (NULL, s);
    }
  }
  fclose(f);
} else 
{
  perror("somefile");
}
for(int i = 0; i<3; i++)
{
  printf ("%s\n",temp[i]);  
}

Solution

  • s is not a proper C string: const char s[1] = ","; defines it to have a size of 1, without a null terminator.

    Use this instead:

    const char *s = ",";
    

    Note that a line with fewer than 2 commas will cause the program to have undefined behavior as you do not check that strtok() returns a non NULL pointer. Here is an alternative using sscanf():

    #include <stdio.h>
    
    int main(void) {
        FILE *fp = fopen("somefile", "r");
        char temp[3][20];
        if (fp != NULL) {
            char line[1024];
            while (fgets(line, sizeof line, fp) != NULL)  {
                if (sscanf(line, "%19[^,],%19[^,],%19[^\n]", temp[0], temp[1], temp[2]) == 3) {
                    printf("%s\n%s\n%s\n\n", temp[0], temp[1], temp[2]);
                }
            }
            fclose(fp);
        }
        return 0;
    }
    

    Note however that the above code will fail to parse lines with empty fields such as ,, because sscanf() requires a non empty string for the %[^,] conversion specifier.

    Note also that strtok() would be inappropriate for such parsing too as it treats sequences of separators as a single separator, which is OK for white space but probably incorrect for ,.