0

I want to read a string with integers and whitespaces into an array. For example I have a string looks like 1 2 3 4 5, and I want to convert it into an integer array arr[5]={1, 2, 3, 4, 5}. How should I do that?

I tried to delete the whitespaces, but that just assign the whole 12345 into every array element. If I don't everything element will all assigned 1.

for (int i = 0; i < str.length(); i++){
            if (str[i] == ' ')
                str.erase(i, 1);
        }

for (int j = 0; j < size; j++){   // size is given

            arr[j] = atoi(str.c_str());

        }
Ace_J
  • 87
  • 7
  • possible duplicate of [What exactly does stringstream do?](http://stackoverflow.com/questions/20594520/what-exactly-does-stringstream-do) – user657267 Sep 30 '15 at 02:59
  • 1
    Why not use `vector`? – jtbandes Sep 30 '15 at 03:02
  • @user657267 yes, but a bit oblique. Ace, `stringstream input("1 2 3 4 5");` then `while (input >> arr[i] && i < MAX_I);`better still, `while(input >> temp) vec.push_back(temp);` – user4581301 Sep 30 '15 at 03:23

3 Answers3

2

A couple of notes:

  • Use a std::vector. You will most likely never know the size of an input at compile time. If you do, use a std::array.
  • If you have C++11 available to you, maybe think about stoi or stol, as they will throw upon failed conversion
  • You could accomplish your task with a std::stringstream which will allow you to treat a std::string as a std::istream like std::cin. I recommend this way
  • alternatively, you could go the hard route and attempt to tokenize your std::string based on ' ' as a delimiter, which is what it appears you are trying to do.
  • Finally, why reinvent the wheel if you go the tokenization route? Use Boost's split function.

Stringstream approach

std::vector<int> ReadInputFromStream(const std::string& _input, int _num_vals)
{
    std::vector<int> toReturn;
    toReturn.reserve(_num_vals);
    std::istringstream fin(_input);
    for(int i=0, nextInt=0; i < _num_vals && fin >> nextInt; ++i)
    {
        toReturn.emplace_back(nextInt);
    }

    // assert (toReturn.size() == _num_vals, "Error, stream did not contain enough input")
    return toReturn;
}

Tokenization approach

std::vector<int> ReadInputFromTokenizedString(const std::string& _input, int _num_vals)
{
    std::vector<int> toReturn;
    toReturn.reserve(_num_vals);
    char tok = ' '; // whitespace delimiter
    size_t beg = 0;
    size_t end = 0;
    for(beg = _input.find_first_not_of(tok, end); toReturn.size() < static_cast<size_t>(_num_vals) &&
    beg != std::string::npos; beg = _input.find_first_not_of(tok, end))
    {
        end = beg+1;
        while(_input[end] == tok && end < _input.size())
            ++end;
        toReturn.push_back(std::stoi(_input.substr(beg, end-beg)));
    }
    // assert (toReturn.size() == _num_vals, "Error, string did not contain enough input")
    return toReturn;
}

Live Demo

AndyG
  • 39,700
  • 8
  • 109
  • 143
  • Is there any way to use an array if the size is known at compile time? – Ace_J Sep 30 '15 at 12:52
  • @Ace_J, absolutely. Assume `toReturn` is a `std::array` in my above example. You would instead perform assignment instead of `push_back`. That is, `toReturn[index] = stoi(...)` – AndyG Sep 30 '15 at 15:39
  • @Ace_J: [Here's the same example using std::array instead](http://coliru.stacked-crooked.com/a/1dfbf1c342065c76) – AndyG Sep 30 '15 at 15:51
0

Your code arr[j] = atoi(str.c_str()); is fault. The str is a string, not a char. When you used atoi(const char *), you should give the &char param. So the correct code is arr[j] = atoi(&str[j]). By the way, if you want to change the string to int, you could use the function arr[j] = std::stoul(str). I hope this can help you.

cwfighter
  • 502
  • 1
  • 5
  • 20
0

You have modified/parsing the string in one loop, but copying to integer array in another loop. without setting any marks, where all the embedded integers in strings start/end. So we have to do both the actions in single loop. This code is not perfect, but to give you some idea; followed the same process you followed, but used vectors.

string str = "12 13 14";
vector<int> integers;
int start=0,i = 0;
for (; i < str.length(); i++){
        if (str[i] == ' ')
        {
            integers.push_back(atoi(str.substr(start,i).c_str()));
            start = i;
        }
    }
integers.push_back(atoi(str.substr(start,i).c_str()));
bala sreekanth
  • 464
  • 2
  • 6