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
3
  • possible duplicate of C - split string into an array of strings Commented Oct 14, 2014 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. Commented Oct 14, 2014 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. Commented Oct 14, 2014 at 23:01

3 Answers 3

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
Sign up to request clarification or add additional context in comments.

1 Comment

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.
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]

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.