How to split a string into multiple strings?

Hello, I’m very new to openFrameworks and C++ as well. I’ve only done some work with Processing before.

What I’m trying to figure out, and can’t seem to find the answer, is how to split one string into multiple strings. For instance, in Processing, I would do it roughly like this:

String[] all = loadStrings("data.txt");
    fruits = new String[all.length];
    vegetables = new String[all.length];    

for(int i=0; i<all.length; i++) {
    String[] list = split(all[i], ";");
    fruits[i] = list[0];
    vegetables[i] = list[1];
}

So if say, the text inside data.txt went something like this:

apple; lettuce; pear; onion; banana; spinach;

then the two new strings would look something like this:

fruits[] = { apple, pear, banana }
vegetables[] = { lettuce, onion, spinach }

I’m sorry if this is a silly question or something that’s been answered before and I just couldn’t get it. I might just be searching with the wrong keywords. If it already has been answered, than a point in the right direction would be appreciated. openFrameworks/C++ just seems so much harder to get the hang of than Processing, but Processing can’t handle the amount of data I want to load.

Thanks in advance!

@siephe, OF has it’s own function for splitting a body of text into strings ofSplitString( string& str, string& delimiter). It returns a vector of string, which is pretty similar to an array of string.

There’s some info in the documentation

http://www.openframeworks.cc/documentation/utils/ofUtils.html#show_ofSplitString

But here’s an example of what you might do with your list of fruits.

string myString = "apple;lettuce;pear;onion;banana;spinach;"

// divide the string using a ';' as a delimiter 
// notice that i removed the spaces after the individual words 
vector<string> splitString = ofSplitString( myString, ";");

// loop through the results
for(int i=0; i<splitString.size(); i++){

     printf( "element %i is %s\n", i, splitString[i].c_str() );
}
1 Like

@mantissa Thank you for your reply. However

for(int i=0; i<splitString.size(); i++){
     printf( "element %i is %s\n", i, splitString[i].c_str() );
}

is just printing out the list of fruits and vegetables. I have no trouble up till that part. What I’m having trouble with is how to divide the list so that it prints out two lists, such as:

Fruits: apple, pear, banana
Vegetables: lettuce, onion, spinach

Note that in the original list, every first word is a fruit, every second is a vegetable.

Thanks. =)

If that’s the case that every first word is a fruit and every second is a vegetable, then you can change the way that you step through the list (by changing the values in the for loop).

to count the fruits (0, 2, 4, 6 … )

for(int i=0; i<splitString.size(); i+=2){
    printf( "fruit is %s\n", i, splitString[i].c_str() );
}

to count the vegetables (1, 3, 5, 7 … )

for(int i=1; i<splitString.size(); i+=2){
    printf( "vegetable is %s\n", i, splitString[i].c_str() );
}

when you’re looping trough the list and extracting your individual fruit and veg names, you can then add them to separate lists of fruits and vegetables. you’ll want to create a new vector for fruits and another for vegetables to store this info.

Here’s a tutorial on working with vectors in OF

http://www.openframeworks.cc/tutorials/c++%20concepts/001_stl_vectors_basic.html

1 Like

@mantissa Thank you! =D

@mantissa

So I tried adapting the code like so:

string myString = "apple;lettuce;pear;onion;banana;spinach;";

// divide the string using a ';' as a delimiter
// notice that i removed the spaces after the individual words
vector<string> splitString = ofSplitString( myString, ";");

// loop through the results
for(int i=0; i<splitString.size(); i+=2){
    fruits = ofSplitString(splitString[i], ";");
    cout << fruits[i] << endl;
}

However, only apple is printed out and I’m getting the following error:

Thread 1: EXC_BAD_ACCESS (code=1, address=0xfffffff5)

on this line: { return _M_rep()->_M_length; } down in the code below:

public:
      // Capacity:
      ///  Returns the number of characters in the string, not including any
      ///  null-termination.
      size_type
      size() const
      { return _M_rep()->_M_length; }

which, I believe, is part of the framework code.

this is that’s creating those errors.

fruits = ofSplitString(splitString[i], ";");
cout << fruits[i] << endl;

the array fruits isn’t large enough for the element in the vector that you’re requesting. remember the fruits vector is a different size than the splitString vector … so your loop goes out of bounds and you get that nasty EXC_BAD_ACCESS error.

since your string has already been split up (above), you don’t need to do this again in the for loop

instead try adding the string located at splitString[i] to a new vector that’s declared outside of the for loop.

// loop through the results
vector<string>fruits;
for(int i=0; i<splitString.size(); i+=2){
    cout << splitString[i] << endl;
    fruits.push_back( splitString[i] );
}

Apologies for my last post, I just realised you’re trying to split your fruit and veg :smile:

You could do this,

vector<string> fruitNVeg = ofSplitString( myString, ";");

vector<string> fruit;
vector<string> veg;
for (int i=0; i < fruitNVeg.size(); i+=2) {
    fruit.push_back(fruitNVeg[i]);
    veg.push_back(fruitNVeg[i+1]);
}

for (int i=0; i <fruit.size(); i++) {
    cout << "Tasty fruit = " << fruit[i] << endl;
}
for (int i=0; i < veg.size(); i++) {
    cout << "Tasty veg = " << veg[i] << endl;
}

@mindtree Thanks for your reply, however I’m getting a Thread 1: EXC_BAD_ACCESS error in the last line here:

// _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 402. wrong new expression in [some_] allocator::construct
      void 
      construct(pointer __p, const _Tp& __val) 
      { ::new(__p) _Tp(__val); }

@mantissa Thank you. This works just the way I want it to. =D