1

I'm trying to split up a string (typed in by the user at run time) into words (separated by spaces), and put each word into a different slot into an array. So, for example, if I took the string "hello world", array[0] would contain "hello" and array[1] would contain "world". And the last slot (in this case array[2]) would contain NULL. Here's what I have so far, which doesn't seem to be working properly. Any help would be appreciated. (By the way, this is part of a program which will call execvp(argv[0],argv); )

char input[100];
char* argv[20];
char* token;
scanf("%s", input);

//get the first token
token = strtok(input, " ");

int i=0;
//walk through other tokens
while( token != NULL ) {
    argv[i] = token;
    i++;
    token = strtok(NULL, " ");
    } 
argv[i] = NULL; //argv ends with NULL
nettux
  • 5,270
  • 2
  • 23
  • 33
AnonyMouse
  • 29
  • 1
  • 1
  • 3
  • possible duplicate of [C - split string into an array of strings](http://stackoverflow.com/questions/11198604/c-split-string-into-an-array-of-strings) – indiv Oct 14 '14 at 22:26
  • You have to deal with couple of issues: reading the user data and splitting up the user data into tokens. Using `"%s"` format in `scanf` in a loop should adequately address both. – R Sahu Oct 14 '14 at 22:32
  • Can you explain what "isn't working properly" means here? Your loop is walking through the input character array, overwriting each space it finds with `'\0'`, and saving pointers to the beginning of each token. That sounds like what you're asking for. – iwolf Oct 14 '14 at 23:01

3 Answers3

3

You need to allocate memory for each argv[i] and copy the current token to argv[i]:

token = strtok(input, " ");

int i=0;
//walk through other tokens
while( token != NULL ) {
    argv[i] = malloc(strlen(token) + 1);
    strncpy(argv[i], token, strlen(token));
    //argv[i] = token;
    i++;
    token = strtok(NULL, " ");
    } 
argv[i] = NULL; //argv ends with NULL
Kaizhe Huang
  • 990
  • 5
  • 11
  • No, you don't need to allocate space, just for the pointers. `strtok(3)` walks through the original string putting `\0`'s at the first `char` encountered in the string, belonging also to the second string parameter to `strtok(3)`. you can use the original string `input` or a `dup(3)`'ed one, if you want to conserve/save `malloc()`'s. Also, in your example, you can call `strdup(3)` which does both, the malloc and the `strcpy(3)` for you. – Luis Colorado Oct 16 '14 at 11:20
1

I have created an example of what I think you want. I have used one malloc(3) for the whole line of strings and another for the array of pointers you will get from the function.

Also, the second parameter of strtok(3) is passed to give more flexibility (the shell normally uses the contents of IFS environment variable to separate arguments so you can use the same algorithm as the shell does) I think you should use " \n\t" at least. It has a main() test function, so it's complete for your purpose.

#include <assert.h> /* man assert(3) */
#include <stdlib.h> /* malloc lives here */
#include <string.h> /* strtok, strdup lives here */
#include <stdio.h> /* printf lives here */

char **split(const char *str, const char *delim)
{
    char *aux;
    char *p;
    char **res;
    char *argv[200]; /* place for 200 words. */
    int n = 0, i;

    assert(aux = strdup(str));
    for (p = strtok(aux, delim); p; p = strtok(NULL, delim))
        argv[n++] = p;
    argv[n++] = NULL;
    /* i'll put de strdup()ed string one place past the NULL,
     * so you can free(3), once finished */
    argv[n++] = aux;
    /* now, we need to copy the array, so we can use it outside
     * this function. */
    assert(res = calloc(n, sizeof (char *)));
    for (i = 0; i < n; i++)
        res[i] = argv[i];
    return res;
} /* split */

int main()
{
    char **argv =
        split("Put each word of a string into array in C", " ");
    int i;

    for (i = 0; argv[i]; i++)
        printf("[%s]", argv[i]);
    puts("");  /* to end with a newline */

    free(argv[i+1]);
    free(argv);
} /* main */

The sample code just outputs:

$ pru
[Put][each][word][of][a][string][into][array][in][C]
Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
0

I think I just figured out my problem: I need to use gets() instead of scanf(), because scanf() only gets the first word, up until a space, while I want to be able to get a string containing multiple words separated by spaces.

AnonyMouse
  • 29
  • 1
  • 1
  • 3