4

I participated in different coding contests and therefore cant use python cause it's too slow on execution time, but i really like the input.split() thing, so i tried to implement my own split. Here is what i came up with:

#include <iostream>
#include <vector>
#include <stack>

using namespace std;

vector<string> splt(string s){
    vector<string> ans={};
    for(int i=0;i<s.size();i++){
        string str="";
        while(s[i]!=' '){
            str+=s[i];
            i++;
        }
        ans.push_back(str);
    }
    return ans;
}

int main(){
    string s;
    getline(cin, s);
    vector<string> ans=splt(s);
    for(auto i:ans)
        cout<<i<<", ";
}

But the vector returned by the function often(but no always) has some junk at the end. Would appreciate any help with correcting my code, as well as some other impementation of splitting a string into an array.

P.S. Sorry if my English is bad, im from Russia and haven't even finished school :)

Cut7er
  • 1,209
  • 9
  • 24
LukaSsS
  • 100
  • 5
  • 2
    What's python tag doing here? – Sheldore Sep 19 '18 at 12:17
  • 1
    There's a tool on your computer called a "debugger". Using this tool you can run your program one line at a time and examine the values of all variables. This debugger will tell you exactly why your function returns garbage. The reason is quite obvious, but the real answer to your question is: learn how to use a debugger. This is what it's there for. Knowing how to use a debugger is a required skill for every C++ developer, no exceptions. – Sam Varshavchik Sep 19 '18 at 12:19
  • 2
    Your inner loop while(s[i]!=' ') ... does not check for the end of the string. Try while(s[i]!=' '&&i – One Man Monkey Squad Sep 19 '18 at 12:20
  • That won't work unless your input string ends with a space, which isn't very likely. – molbdnilo Sep 19 '18 at 12:22
  • consider using subranges defined by iterator pairs to work on substrings. Its seems a bit backwards to use c++ instead of python for performance and then do all this uneccesary stuff (copying, creating a vector, creating several strings etc) – 463035818_is_not_an_ai Sep 19 '18 at 12:23
  • 2
    One question per question, please. Your second question is a duplicate of https://stackoverflow.com/q/236129/3002139. Please consider removing it. – Baum mit Augen Sep 19 '18 at 12:26

4 Answers4

8

In this loop:

    while(s[i]!=' '){
        str+=s[i];
        i++;
    }

You never check whether i is outside the bounds of s and as long as there isn't a ' ' there, i will be incremented beyond the boundary, and the string will be accessed outside of bounds. The behaviour of accessing the string outside of bounds is undefined.

eerorika
  • 232,697
  • 12
  • 197
  • 326
2

Your inner loop doesn't stop at the end of the string, only when it encounters a space character.
Thus, if your input doesn't end with a space, you're going to index outside the string and have undefined behaviour.
(And when it works, contiguous space characters will result in empty strings, which you probably don't want.)

The most straightforward way to split on whitespace is to use a stream:

#include <sstream>

vector<string> split(string s){
    vector<string> ans;
    istringstream ss(s);
    string word;
    while (ss >> word)
        ans.push_back(word);
    return ans;
}

or

#include <algorithm>
#include <iterator>
#include <sstream>

vector<string> split(string s){
    vector<string> ans;
    istringstream ss(s);
    copy(istream_iterator<string>(ss), istream_iterator<string>(), back_inserter(ans));
    return ans;
}
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
2
while(s[i]!=' '){
        str+=s[i];
        i++;
}

The above code part doesn't check for the boundary of s. While doing i++ you might go over the boundary of the string. So check if i == s.size() and break from the loop.

Destructor
  • 523
  • 1
  • 3
  • 13
0

Your while loop does not check for the end of the string, so if you reach the last space in your string, it will not stop at the last character.

while(s[i]!=' ' && i<s.size()){

It is probably smarter to use the solution using streams from the other answer, or use the find method of the string class and the substring method. Example:

vector<string> splt(string s){
    vector<string> ans={};
    size_t found = s.find_first_of(' ');
    size_t last = 0;
    while(found!=string::npos){
        ans.push_back(s.substr(last,found));
        last = found+1;
        found = s.find_first_of(' ',found+1);
    }
    ans.push_back(s.substr(last,s.size()));
    return ans;
}
Ketzu
  • 660
  • 1
  • 7
  • 12