store elements of a string into different vectors/

2019-10-03 09:00发布

问题:

Greetings all im pretty new to c++ but enjoying it alot (i come from doing c) this is a third program part of a system im building and im looking for example code to just help with a function so i have a small question, ive been going through alot of examples and cant find exactly what i want, this may be obvious but im just having a brain fart with it. I want to read a .txt file with a layout of: category, item, price, itemnumber

main,steak bernaise,15,101
pudding,banoffee,3.99,102
starter,prawn cocktail,2.89,103
drink,gin & tonic,3.50,104

i then want to detect ',' and put the different elements into seperate vectors, ive tried a few things such as getline, ispunct (the full stops in price make this non viable) same with isspace, i did wonder about using an 'ignore' with these but think thats bad practise to list so much unless i can define i only want isspunt to check ','. feel free to modify my examples or provide your own.

class Food {
private:
string category;
string item;
string price;
string itemnum;
public:
string tostring();
Food(string cat, string it, string pr, string itno)
    : category(cat), item(it), price(pr), itemnum(itno) {  }

void display(ostream& output) const{
    output << category << " " << item << " " << price << " " << itemnum << endl;
}
};

ostream& operator<<(ostream& output, Food const& f){
f.display(output);
return output;
}

This above is the class im using, ive attached the overloader with this.

void filein::intake() {
string tempnum;
ifstream fin("bill.txt");
if(fin) {
    while(!fin.eof()) {
        string itemnum;
        string category;
        string item;
        string price;
        getline(fin, category, ',');
        getline(fin, item, ',');
        getline(fin, price, ',');
        getline(fin, itemnum);
        _items.push_back(Food(category, item, price, itemnum));
            }
    }
    for (size_t i = 0; i < _items.size(); ++i){
        cout << _items[i];
    }
}

this is only storing into 1 though, if any of my examples can be modified id be grateful.

vector<string> split(const string& s)
{
vector<string> _totals;
vector<string> _items;
typedef string::size_type string_size;
string_size i = 0;

    // invariant: we have processed characters [original value of i, i) 
    while (i != s.size()) {
    // ignore leading blanks
    // invariant: characters in range [original i, current i) are all spaces
    while (i != s.size() && ispunct(s[i]))
     ++i;

    // find end of next word
     string_size j = i;
     // invariant: none of the characters in range [original j, current j)is a space
    while (j != s.size() && !ispunct(s[j]))
     j++;

     // if we found some nonpunctuation characters 
     if (i != j) {
     _totals.push_back(s.substr(i, j - i));


     i = j;
  }
 }
return _totals;
}

this doesnt work either this was the ispunct thing i was sying about, i tried it as i wondered if somwhere in the while loops i could add lines to parse the different elements of the string into seperate vectors.

so to reiterate my question: I want to read the file line by line take each element from that line and store in a vector, layout is always the same in the .txt but the words are different sizes they are always seperated by a ',' though.

Thanks for any help you can provide.

回答1:

A simple way of doing this is probably using a std::stringstream in combination with getline like this:

std::string str;
while (std::getline(fin, str)) // fin is the input stream
{
    std::istringstream iss(str);
    std::string token;
    while (std::getline(iss, token, ',')) // get the token as a std::string
    {
         // process it here, can use `stoi` to convert to int
    }
}


回答2:

Here's another way to do it - this function split() splits a comma-separated string into a vector of strings.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

vector<string> split(const string& s)
{
    vector<string> v;
    size_t current = 0;
    while (current != string::npos) {
        auto next = s.find_first_of(',', current);
        if (next == string::npos) {
            v.push_back(s.substr(current));
            current = string::npos;
        }
        else {
            v.push_back(s.substr(current, next - current));
            current = next + 1;
        }
    }
    return v;
}

// test the function
int main()
{
    ifstream infile("bill.txt");
    while(!infile.eof()) {
        string s;
        getline(infile, s);
        auto words = split(s);
        if (words.size() == 4) {
            cout << words[0] << "|" << words[1] << "|" << words[2]<< "|" << words[3] << endl;
        }
    }

   return 0;
}