0

I'm trying to break apart a string in C using strtok(), and assign the values I get to a property of a struct within an array.

Here is what the string (expected input) looks like:

steve 31516.john 31516.

And my code (ignoring variable definitions):

while(fgets(line, sizeof(line), f) != NULL);

char* tok = strtok(line, ".");
while(tok != NULL){
    char* buf = strdup(tok);
    calendar[i].user = strtok(tok, " ");
    char* date = strtok(NULL, " ");
    calendar[i].date = atoi(date);
    tok = strtok(NULL, ".");
    free(buf);
    i++;
}

The expected output I'd like to have is something like this:

calendar[0].user = "steve"
calendar[0].date = 31516
calendar[1].user = "john"
calendar[1].date = 31516

What I'm getting, however, is this:

calendar[0].user = "steve"
calendar[0].date = 31516

The problem I'm having, is that it seems that this loop only happens once, no matter how long the original input string is that strtok() is first running on. It is assigning the variables correctly within the loop, but it is only running once.

Ajv2324
  • 422
  • 8
  • 24
  • 3
    this line: `while(fgets(line, sizeof(line), f) != NULL);` is going to read every line in the file, and each line will overlay the previously read line. This is 'probably' not what you want – user3629249 Nov 02 '16 at 02:49
  • Currently, it gives me a string like the one that I have at the beginning of my question, which I'd like to parse by the delimiter '.'. Does this not seem like it'd be okay? – Ajv2324 Nov 02 '16 at 02:55
  • 2
    regarding this line: `char* buf = (char*)malloc(strlen(tok));` 1) in C, do not cast the returned value. it has type `void*` so can be assigned to any other pointer. The cast just clutters the code. 2) when calling any of the heap allocation functions (malloc, calloc, realloc) always check (!=NULL) the returned value to assure the operation was successful. 3) in general, use `strdup()` rather than `malloc()` / `strcpy()` cont: – user3629249 Nov 02 '16 at 02:56
  • 1
    cont: 4) strlen() does not return a value long enough to include the NUL termination char, so the call to `malloc()` (if you decide to still use it) would be: `char* buf = NULL; if( NULL == (buf = malloc(strlen(tok)+1) ) ) { perror( "malloc failed" ); exit( EXIT_FAILURE ); }` – user3629249 Nov 02 '16 at 02:56
  • this call to `strtok()` `tok = strtok(NULL, ".");` is very suspicious. Strongly suggest using a debugger an looking at what is being returned by `strtok()` on each call. – user3629249 Nov 02 '16 at 02:58
  • this line: `calendar[i].user = strtok(tok, " ");` copies a pointer, not what you want to do. as every call will copy a pointer to the same buffer – user3629249 Nov 02 '16 at 03:02
  • What is wrong with it? From my understanding, it either returns the next chunk before the next delimiter, or null if this doesn't exist? – Ajv2324 Nov 02 '16 at 03:02
  • your asking about a run time problem. Such questions require the input, the expected output, the actual output AND the (cleanly compiles) code that demonstrates the output. The posted question fails to supply all the needed information – user3629249 Nov 02 '16 at 03:04

1 Answers1

1

the following code should implement the actions that you want to perform.

#include <stdio.h>  // fopen(), fclose()
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <string.h> // strtok()
#include <ctype.h>  // isspace()

int main( void )
{
    FILE * f = NULL;
    if( NULL == ( f = fopen( myFile, "r" ) ) )
    {
        perror( "fopen for myFile failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful


    #define MAX_LINE_LEN (1024)

    char line[ MAX_LINE_LEN ];
    while(fgets(line, MAX_LINE_LEN, f) != NULL) )
    {

        char* tok = strtok( line, ".");
        while( tok )
        {                       
            for( x = 0; !isspace(tok[x]); x++)
            {
                 calendar[].user[x] = tok[x];
            }

            x++; // step by the space

            calendar[i].date        = atoi( &tok[x] );

            tok = strtok(NULL, ".");
            i++;
        }
    }

Do note that the above code is not complete, but rather just an example of what you need to do.

user3629249
  • 16,402
  • 1
  • 16
  • 17