-1

I am a new programmer (< 1 year) so please forgive if I am making a simple thing complicated.

I'm trying to remove all the white space (the tab and space characters) in a given string and store the data as individual elements in a vector as I go. I also want to account for leading and trailing white space.

I've tried using string methods to move two indexes forward in the string while checking along the way for these characters. I've rewritten the code at least five times so far and I always end up with:

terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::at: __n (which is 7754) >= this->size() (which is 42)
Aborted (core dumped)
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void  makeTokens(string& separate);

int main()
{
    string test = "  u       65.45\t\t   36.12\t     78.25  0.00";

    makeTokens(test);

    return 0;
}

void  makeTokens(string& separate)
{
    vector<string> tokens;
    unsigned short index1, index2 = 0;

    while (separate.at(index1) == ' ' || separate.at(index1) == '\t')
    {
        index1++;
        index2 = index1 + 1;
    }

    while (index2 < separate.length())
    {
        if (separate.at(index2) == ' ' || separate.at(index2) == '\t')
        {
            tokens.push_back(separate.substr(index1, index2 - index1));

            index1 = index2;

            while (separate.at(index1) == ' ' || separate.at(index1) == '\t')
            {
                index1++;
            }

            index2 = index1 + 1;
        }
        else
        {
            index2++;
        }

        if (index2 == separate.length() - 1)
        {
            if (separate.at(index2) == ' ' || separate.at(index2) == '\t')
            {
                tokens.push_back(separate.substr(index1));
            }
        }
    }

    for (unsigned short i = 0; i < tokens.size(); i++)
    {
        cout << tokens[i] << "|" << endl;
    }
}

I want the console to output:

u|
65.45|
36.12|
78.25|
0.00|

If a similar test string were passed, except with white space on the end, I still want the same output.

EDIT: I have changed my index declarations to:

unsigned short index1 = 0;
unsigned short index2 = 0;

Now the console outputs:

u|
65.45|
36.12|
78.25|

The final 0.00 is still missing.

  • Check out this question that seems relevant: https://stackoverflow.com/questions/236129/how-do-i-iterate-over-the-words-of-a-string – Kyle May 29 '19 at 18:26

2 Answers2

2

The first instance of undefined behavior is here:

    unsigned short index1, ...

    while (separate.at(index1) ...
//                     ^^^^^^

index1 is not initialized.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • Sorry, I don't understand. My thoughts were that separate.at(index1) = ' ' –  May 29 '19 at 18:29
  • @nrhale Your code uses a variable, but that variable has no value. You never assigned anything to `index1`. – melpomene May 29 '19 at 18:31
1

This is easily done by using std::istringstream:

#include <string>
#include <sstream>
#include <iostream>
#include <vector>

int main()
{
  std::string test = "  u       65.45\t\t   36.12\t     78.25  0.00";
  std::istringstream strm(test);
  std::string word;
  std::vector<std::string> words;
  while (strm >> word)
      words.push_back(word);
  for (auto& v : words)
    std::cout << v << "|\n";
}

Output:

u|
65.45|
36.12|
78.25|
0.00|

Live Example

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45