28

I am trying to insert a string separated by spaces into an array of strings without using vector in C++. For example:

using namespace std;
int main() {
    string line = "test one two three.";
    string arr[4];

    //codes here to put each word in string line into string array arr
    for(int i = 0; i < 4; i++) {
        cout << arr[i] << endl;
    }
}

I want the output to be:

test
one
two
three.

I know there are already other questions asking string > array in C++, but I could not find any answer satisfying my conditions: splitting a string into an array WITHOUT using vector.

Cœur
  • 37,241
  • 25
  • 195
  • 267
txp111030
  • 305
  • 1
  • 4
  • 11
  • How would you go about printing each word on a separate line to begin with? – X-Istence Apr 16 '13 at 05:22
  • already answerd look here http://stackoverflow.com/questions/53849/how-do-i-tokenize-a-string-in-c – Lars Apr 16 '13 at 05:38
  • Here are some similar questions: http://stackoverflow.com/questions/1894886/parsing-a-comma-delimited-stdstring http://stackoverflow.com/questions/1321137/convert-string-containing-several-numbers-into-integers http://stackoverflow.com/questions/1141741/int-tokenizer http://stackoverflow.com/questions/3162108/a-better-way-to-split-a-string-into-an-array-of-strings-in-c-c-using-whitespac http://stackoverflow.com/questions/1323824/how-to-read-numbers-from-an-ascii-file-c –  Apr 16 '13 at 06:27

6 Answers6

53

It is possible to turn the string into a stream by using the std::stringstream class (its constructor takes a string as parameter). Once it's built, you can use the >> operator on it (like on regular file based streams), which will extract, or tokenize word from it:

#include <iostream>
#include <sstream>

using namespace std;

int main(){
    string line = "test one two three.";
    string arr[4];
    int i = 0;
    stringstream ssin(line);
    while (ssin.good() && i < 4){
        ssin >> arr[i];
        ++i;
    }
    for(i = 0; i < 4; i++){
        cout << arr[i] << endl;
    }
}
Ryan Knutson
  • 108
  • 2
  • 14
didierc
  • 14,572
  • 3
  • 32
  • 52
  • 3
    This answer is very simple, to the point, and more importantly works! Thank you very much! – txp111030 Apr 16 '13 at 05:49
  • It splits the individual characters for me. – Krii Feb 26 '15 at 20:02
  • Hymm, if there is a space at the end of the "line" variable. And you remove the <4 and use push_back to store in a vector, then you get the last element twice. There's something wrong with this code. – Owl Feb 13 '16 at 16:43
  • it's missing a check that the read succeeded. Instead, use `for (int i=0; i<4 && ssin >> arr[i]; ++i);` – Mooing Duck Dec 02 '22 at 08:34
5
#include <iostream>
#include <sstream>
#include <iterator>
#include <string>

using namespace std;

template <size_t N>
void splitString(string (&arr)[N], string str)
{
    int n = 0;
    istringstream iss(str);
    for (auto it = istream_iterator<string>(iss); it != istream_iterator<string>() && n < N; ++it, ++n)
        arr[n] = *it;
}

int main()
{
    string line = "test one two three.";
    string arr[4];

    splitString(arr, line);

    for (int i = 0; i < 4; i++)
       cout << arr[i] << endl;
}
Alexey
  • 51
  • 2
2
#define MAXSPACE 25

string line =  "test one two three.";
string arr[MAXSPACE];
string search = " ";
int spacePos;
int currPos = 0;
int k = 0;
int prevPos = 0;

do
{

    spacePos = line.find(search,currPos);

    if(spacePos >= 0)
    {

        currPos = spacePos;
        arr[k] = line.substr(prevPos, currPos - prevPos);
        currPos++;
        prevPos = currPos;
        k++;
    }


}while( spacePos >= 0);

arr[k] = line.substr(prevPos,line.length());

for(int i = 0; i < k; i++)
{
   cout << arr[i] << endl;
}
Vijendra Singh
  • 628
  • 3
  • 13
  • `string::find` returns `string::npos` if it did not find the string being searched and not 0. – RedX Apr 16 '13 at 07:11
  • std::string::npos is a static member constant value with the greatest possible value for an element of type size_t. This constant is defined with a value of -1, which because size_t is an unsigned integral type, it is the largest possible representable value for this type. – Vijendra Singh Apr 16 '13 at 07:17
0

Here's a suggestion: use two indices into the string, say start and end. start points to the first character of the next string to extract, end points to the character after the last one belonging to the next string to extract. start starts at zero, end gets the position of the first char after start. Then you take the string between [start..end) and add that to your array. You keep going until you hit the end of the string.

Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
0
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;

int main() {

    string s1="split on     whitespace";
    istringstream iss(s1);
    vector<string> result;
    for(string s;iss>>s;)
        result.push_back(s);
    int n=result.size();
    for(int i=0;i<n;i++)
        cout<<result[i]<<endl;
    return 0;
}

Output:-

split
on
whitespace

  • 1
    From Review:  Hi, please don't answer just with source code. Try to provide a nice description about how your solution works. See: [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). Thanks – sɐunıɔןɐqɐp Nov 08 '19 at 18:05
0

I made a header for this and you can use it to split a string into array of strings using a string as a splitter heres how:

  1. create a file with a name "WordSplitter.h" and save it along with the folder of cpp file.

  2. Copy paste this in WordSplitter.h:

#ifndef WORDSPLITTER_H
#undef WORDSPLITTER_H
#include <iostream>
#include <string>
using namespace std;

class Word {
    public:
        string word;
        string list[99];

    Word(string s){
        word = s;
    }
    
    int size(string s){
        int size = 0;
        for(char c : s){
            size ++;
        }
        return size;
    }

    int size(){
        int size = 0;
        for (char c : word){
            size ++;
        }
        return size;
    }

    string slice(int start, int end){
        string result = "";
        for(int i = start ; i <= end ; i ++){
            result += word[i];
        }
        return result;
    }
    
    string sliceThis(string s, int start, int end){
        string result = "";
        for(int i = start ; i <= end ; i ++){
            result += s[i];
        }
        return result;
    }

    int count(string s){
        int count, start = 0;
        for(int end = size(s)-1 ; end < size() ; end ++){
            if(s == slice(start,end)){count ++;}
            start ++;
        }
        return count;
    }
    
    int listSize(){
        int size_ = 0;
        for(string str : list){
            if (size(str) > 0){
                size_ ++;
            }
        }
        return size_;
    }

    void split(string splitter){
        int splitSize = size(splitter) - 1;
        int split_start = 0;
        int split_end, end;
        int index = 0;
        
        if (count(splitter) > 0){
            for(end = splitSize ; end < size() ; end ++){
                int start = end - splitSize;
                if (splitter == slice(start,end)){
                    split_end = start - 1;
                    list[index] = slice(split_start,split_end);
                    split_start = end + 1;
                    end += splitSize;
                    index ++;
                }
            }
            list[index] = slice(split_end + size(splitter) + 1, size());
            //list[index] = slice(end + 1, size());
        }
    }
};

#endif
  1. inside your cpp file:
#include <iostream>
#include <string>
#include "WordSplitter.h"

using namespace std;

int main(){ 
    Word mySentence = Word("I[]got[]a[]jar[]of[]dirt");
    mySentence.split("[]"); //use a splitter

    for(int i = 0 ; i < mySentence.count("[]") + 1 ; i ++){
        cout << mySentence.list[i] << endl;
    }

    return 0;
}

output:

I
got
a
jar
of
dirt
  • Welcome to SO! While your answer does work, since you use a custom-written approach for tokenizing it could be improved if you added some explanation or comments to your algorithm. Also, while it's understandable that you don't use some container like `std::vector` to store words because the question explicitly forbids it, the max word count of 99 seems very arbitrary (in particular, this involves much overhead if there are few words in the line), and could be replaced by e.g. template parameter word limit with checking whether the line exceeds this limit during splitting. – YurkoFlisk Jul 24 '22 at 23:14
  • thank you for you advice, btw I'm just a new to C++ language, and I am just trying to make c++ as easy as python, but the only thing that i dont get in c++ is that i dont know if it is possible to change the size of an array or make a funcion/method that can return an array or at least the memory address of array elements – Rollie Garcia Jul 26 '22 at 04:55