splitting a string into an array in C++ without using vector
Asked Answered
K

6

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.

Keratose answered 16/4, 2013 at 5:19 Comment(3)
How would you go about printing each word on a separate line to begin with?Elegancy
already answerd look here #54349Authorship
Here are some similar questions: #1895386 #1321637 https://mcmap.net/q/503529/-int-tokenizer #3162608 #1324324Gawen
W
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;
    }
}
Wiggins answered 16/4, 2013 at 5:41 Comment(4)
This answer is very simple, to the point, and more importantly works! Thank you very much!Keratose
It splits the individual characters for me.Carrell
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.Dryclean
it's missing a check that the read succeeded. Instead, use for (int i=0; i<4 && ssin >> arr[i]; ++i);Earthquake
G
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;
}
Gangboard answered 16/4, 2013 at 6:53 Comment(0)
C
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;
}
Corticosteroid answered 16/4, 2013 at 6:9 Comment(2)
string::find returns string::npos if it did not find the string being searched and not 0.Fernandofernas
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.Corticosteroid
A
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.

Astronaut answered 16/4, 2013 at 5:24 Comment(0)
C
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
Ciliolate answered 23/7, 2022 at 9:14 Comment(2)
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.Firmin
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 elementsCiliolate
M
-1
#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

Mcphail answered 8/11, 2019 at 17:48 Comment(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?. ThanksPlanar

© 2022 - 2024 — McMap. All rights reserved.