Alice S
Alice S

Reputation: 11

Storing value of strtok() tokens?

I'm wanting to use the strtok() function to parse a string, and I'd like to create a copy of the values in the tokens returned (as I gather that the tokens returned from this function are pointers).

Essentially, my AIM is to create a pointer which points to an array of strings, which hold copies of the values at the address of each token. My code attempting this so far (And failing) is below: (Also I want the tokens to be able to hold enough space for three characters).

(NOTE I'm not interested in changing my method of how to split a string - and I'm aware there are disadvantages to strtok)

char words[] = "red, dry, wet, gut"; // this is the input string

char* words_split[100];
char token[3]; // creates space for a token to hold up to 3 characters (?)

int count = 0;

char* k = strtok(words, ",");   // the naming of k here is arbitrary
while (k != NULL) { 
   k = strtok(NULL, ",");
   token[0] = *k; // I'm aware the 0 here is wrong, but I don't know what it should be
   words_split[count] = token;
   count++;
}

And then I'd like to be able to access each of the individual elements, i.e. red, from words_split.

Upvotes: 1

Views: 2622

Answers (3)

Seeker
Seeker

Reputation: 126

This is basically a makeover version of mnistic's answer. Adding just in case it might help you.

#include <bits/stdc++.h>
using namespace std;


int main()
{
    char sentence[] = "red, dry, wet, gut"; // this is the input string

    vector<char *> words;

    for(char *token=strtok(sentence,","); token != NULL; token=strtok(NULL, ","))
    {
        const int wordLength = strlen(token) + 1;
        char *word = new char [wordLength];
        strcpy(word, token);
        words.push_back(word);
        cout << "\nWord = " << word;
    }


    // cleanup
    for(int i=0; i<words.size(); i++)
    {
        delete[] words[i];
    }

    return 0;
}

Upvotes: 0

Barmar
Barmar

Reputation: 781096

You don't need the token variable. Your code is setting every element of words_split to point to the same token, which will end up being just the last token in the string.

Just store the addresses returned by strtok:

int count = 0;
k = strtok(words, ",");
while (k) {
    words_split[count++] = k;
}

If you need to make copies, you can use the strdup() function:

    words_split[count++] = strdup(k);

This is a POSIX function, not standard C++. See usage of strdup for an implementation if you need it.

Or use std::string instead of C strings, as in mnistic's answer.

Upvotes: 0

mnistic
mnistic

Reputation: 11020

Since you are using C++, just use a vector to hold the strings:

  char words[] = "red, dry, wet, gut"; // this is the input string

  std::vector<std::string> strs;

  char* k;
  for (k = strtok(words, " ,"); k != NULL; k = strtok(NULL, " ,")) { 
    strs.push_back(k);
  }

  for(auto s : strs)
  {
    std::cout << s << std::endl;
  }

If you need to access the raw pointer from a string stored in the vector, just do s.c_str().

Upvotes: 2

Related Questions