简体   繁体   中英

How to convert a string containing multiple numbers to ints and store it in a vector

I am writing a program that reads data from a file.

the .txt file looks like this:

Text, numbers, : 5,3,5

Text, numbers, : 1,3,7,8

I was successful in extracting the "Text" and "Numbers", However when I came across the numbers after the : "5,3,5", I was really stuck.

I need to change these numbers to ints and add them to a vector of int, so I got rid of the commas, then tried using stoi to convert them to ints, however, stoi was only "extracting" the first number, in this case, only 5 and 1, this is what I've tried:

while(getline(file, line)){
   stringstream ss(line);
   getline(ss, text, ',');
   getline (ss, nums, ':');
   getline (ss, numList, ',' );
   replace(numList.begin(), numList.end(), ',' , ' ');
   vec.push_back(stoi(numList));

   randomStruct str = {text, nums, numList};

   randomStructVec.push_back(str);


}

I need the output to look like this when printing the elements of the vector:

5 3 5

1 3 7 8

what I'm getting is :

5

1

and other times I get duplicate numbers as well: 5

1111

or

5555

11

I need a way to make the stoi function convert all the numbers on that one line of string to ints, and store them in a vec of ints.

Any help, would be greatly appreciated.

Check out my solution at How do I tokenize a string that uses the String Toolkit Library

Here is a paired down version for your case:

#include <iostream>
#include <vector>
#include <string>
#include <strtk.hpp>  //String Toolkit Library

const char *whitespace  = " \t\r\n\f";
const char *whitespace_and_punctuation  = " \t\r\n\f;,=";

int main()
{

  // parsing a string into a vector of integers with  separators
  // of spaces and punctuation

       std::string s("3; 4, 4, 8,-1");
       std::vector<int> values;
       if( strtk::parse( s, whitespace_and_punctuation, values ) )
       {
           for(size_t i = 0; i < values.size(); ++i )
            std::cout << values[i] << std::endl;
       }

    return 0;
}

You will notice the conversion of the values into a vector of integers. The library is header only. The library is VERY fast and can handle most anything you need to do with a string and parsing.

Use this function stoi_() in this function, I am converting a string into a number if that string contains the characters in range 0-9 otherwise create a new string and repeat this process until you reach the end of string. To handle negative numbers you have to add one more condition.

vector<int> stoi_(string s){
    vector<int>ans;
    int i = 0;
    int n =s.length();
    while(i<n){
        string temp = ""; // current number 

       if(s[i]=='-' && (i+1<n && (s[i+1]>='0' && s[i+1]<='9'))){ // handle -ve numbers
           temp = temp + s[i];
           i++;
       }
        while(i<n && s[i]>='0' && s[i]<='9'){ // if current character is number append it into cur number
            temp = temp + s[i];
            i++;
        }
        if(temp.length()>0){
            ans.push_back(stoi(temp)); // here using stoi() for simplicity 
        }
        else{
            i++;
        }
    }
    return ans;
}

There is too main problem in your code.


First of all getline (ss, numList, ',' ); will stop on the first value of the list. In fact, when your list is 5,3,5 , getline (ss, numList, ','); will read 5 then , so it will stop. At this point, numValue == "5"

This is quite simple to fix : Just remove the delimiter char, so getline(ss, numList); . Using this, numValue == "5,3,5"


Alright, now you have all your value. You replace ',' by ' ' in order to separate your numbers. Good, numList = "5 3 5" .

And then is your second error : vec.push_back(stoi(numList)); . stoi(numList) return an int and is not able to get through space characters. So it will only convert the first 5 and return it. You will never get the other numbers, as you don't even do a loop.

Here is my solution : convert your string to a stringstream and use >> operator

std::stringstream numStream(numList);
int value;
while(numList >> value)
    vec.push_back(value);

So we end up with your final code (I removed std s, as it seems that you wrote using namespace std somewhere in your code)

struct randomStruct
{
   string txt,
   string nb, 
   vector<int> data
}
// -------
while(getline(file, line)){
   stringstream ss(line);
   getline(ss, text, ',');
   getline (ss, nums, ':');
   getline (ss, numList);
   replace(numList.begin(), numList.end(), ',' , ' ');
   stringstream numStream(numList);
   int value;
   while(numStream >> value)
      vec.push_back(value);

   randomStruct str = {text, nums, vec};

   randomStructVec.push_back(str);
   vec.clear();
}

// Accessing and printing data
for (auto str : randomStructVec)
{
   for (auto i : str.data)
   {
      cout << i << " ";
   }
   cout << endl;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM