strtok is the correct function, however you are using it wrong.
man strtok
The strtok() function breaks a string into a sequence of zero or more nonempty tokens.
On the first call to strtok(), the string to be parsed should be specified
in str. In each subsequent call that should parse the same string, str
must be NULL.
I made the most important part of the quote bold.
Also bear in mind that strtok modifies the source, if you need the source
afterwards, you have to make a copy.
// assuming that line is either a char[] or char*
char *token = strtok(line, " ");
if(token == NULL)
{
// error detection
}
while(token = strtok(NULL, " "))
{
// do the work
}
Also I recommend not to use sizeof(<data type>) in
malloc/calloc/realloc calls. It's easy to overlook a * and make
mistakes. Better:
int *myarray = malloc(size * sizeof *myarray);
// or
int *mayarray = calloc(size, sizeof *myarray);
Using sizeof *var is better because it will always returns the correct size.
One last thing:
while(!feof(stdin))
See Why is “while ( !feof (file) )” always wrong?
better
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
// do the work here
}
EDIT
Here you have a sample implementation using strtok. My implementation uses
an array of MAPs. Look at the way I construct/destruct the the MAP objects and how the memory is allocated. Obviously this can be done with less code and less strdups, but I think this shows more precisely how to use these functions. You can use this code as your base or just use it as a basic idea.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef struct{
char *destination;
char *type_present;
int no_available_presents;
char *direction;
} MAP;
MAP *create_map(const char *dest, const char *type, int present, const char *dir);
void free_map(MAP *map);
void print_map(MAP *map);
MAP *create_map(const char *dest, const char *type, int present, const char *dir)
{
MAP *map = calloc(1, sizeof *map);
if(map == NULL)
return NULL;
int errors = 0;
if(!(map->destination = strdup(dest)))
errors++;
if(!(map->type_present = strdup(type)))
errors++;
if(!(map->direction = strdup(dir)))
errors++;
map->no_available_presents = present;
if(!errors)
return map;
free_map(map);
return NULL;
}
void free_map(MAP *map)
{
if(map == NULL)
return;
free(map->destination);
free(map->type_present);
free(map->direction);
free(map);
}
void print_map(MAP *map)
{
if(map == NULL)
{
puts("(null)");
return;
}
printf("destination: %s\n", map->destination);
printf("type: %s\n", map->type_present);
printf("present: %d\n", map->no_available_presents);
printf("direction: %s\n", map->direction);
}
int main(char argc, char **argv)
{
FILE *fp;
if(argc != 1 && argc != 2)
{
fprintf(stderr, "usage: %s [database]\n", argv[0]);
return 1;
}
if(argc == 1)
fp = stdin;
else
fp = fopen(argv[1], "r");
if(fp == NULL)
{
fprintf(stderr, "Could not open '%s': %s\n", argv[1], strerror(errno));
return 1;
}
MAP **maps = NULL;
size_t map_len = 0;
char line[1024];
const char *delim = " \r\n";
while(fgets(line, sizeof line, fp))
{
int pres;
char *dest = NULL, *type = NULL, *dir = NULL, *token;
token = strtok(line, delim);
dest = strdup(token);
token = strtok(NULL, delim);
type = strdup(token);
token = strtok(NULL, delim);
pres = atoi(token);
token = strtok(NULL, delim);
dir = strdup(token);
if(dest == NULL || type == NULL || dir == NULL)
{
// ignore line
free(dest);free(type);free(dir);
continue;
}
MAP *new_map = create_map(dest, type, pres, dir);
if(new_map == NULL)
{
// ignore line
free(dest);free(type);free(dir);
continue;
}
MAP **tmp_map = realloc(maps, (map_len + 1) * sizeof *tmp_map);
if(tmp_map == NULL)
{
// ignore line
free_map(new_map);
free(dest);free(type);free(dir);
continue;
}
maps = tmp_map;
maps[map_len++] = new_map;
free(dest);free(type);free(dir);
}
for(int i = 0; i < map_len; ++i)
{
print_map(maps[i]);
puts("---");
free_map(maps[i]);
}
free(maps);
if(fp != stdin)
fclose(fp);
return 0;
}
The output:
destination: BERLIN
type: CAR
present: 1
direction: U
---
destination: BERLIN
type: CAR
present: 1
direction: R
---
destination: BUCHAREST
type: JACKET
present: 2
direction: D
---
destination: NEW_YORK
type: DOLL
present: 7
direction: U
---
destination: BERLIN
type: ROBOT
present: 5
direction: L
---
destination: BUCHAREST
type: BALL
present: 4
direction: L
---