1

Within this function, I am passing multiple files. It was implemented with arrays before, and now I need to convert all of the arrays to vectors. The issue I have is when I read in from the files, it does not stop. Why??

void readIn(ifstream &iFile, vector<string> &itemName, vector<double> &itemPrice, vector<double> &quantity)
{
    int x = 0;
    string str;
    string nTemp;
    double pTemp;
    int qTemp;

    while(!iFile.eof())
    {
        getline(iFile, nTemp);
        iFile.ignore();
        itemName.push_back(nTemp);
        iFile >> pTemp;
        itemPrice.push_back(pTemp);
        iFile >> qTemp;
        quantity.push_back(qTemp);

        cout << itemName.size() << " " << itemPrice.size() << " " << quantity.size() << endl;
    }

    readIn(appIn, appName, appPrice, appquantity);
    readIn(drinkIn, drinkName, drinkPrice, driquantity);
    readIn(entreeIn, entreeName, entreePrice, entquantity);
    readIn(dessertIn, desName, desPrice, dessquantity);

This is the function and calls. Not sure why when outputting the item name, item price and quantity sizes, it just continually reads in values.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
adamp
  • 13
  • 2
  • 2
    It seems to me that the data you read is closely related and should have been a structure or a class instead. Then you would need only a single vector. Also [don't do `while (!iFile.eof())`](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons), it will not work as you expect. Furthermore, that `ignore` call inside the loop is suspicious, why do you need it? – Some programmer dude Sep 28 '19 at 18:30
  • So the first value is a string. With spaces. So the iFile.ignore is ignoring the spaces inside of the input. What would your suggestion be if the While(!iFile.eof()) isnt in there?? – adamp Sep 28 '19 at 18:35
  • But that [`getline`](https://en.cppreference.com/w/cpp/string/basic_string/getline) call reads a whole line, including spaces. It also read the newline, but throws it away. – Some programmer dude Sep 28 '19 at 18:51
  • As for the loop condition, perhaps something like `while (getline(iFile, nTemp) >> pTemp >> qTemp)`? – Some programmer dude Sep 28 '19 at 18:52

1 Answers1

0

Expanding your code to an executable example:

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

using namespace std;

void readIn(ifstream &iFile, vector<string> &itemName, vector<double> &itemPrice, 
        vector<double> &quantity)
{
    int x = 0;
    string str;
    string nTemp;
    double pTemp;
    int qTemp;

    while(!iFile.eof())
    {
        getline(iFile, nTemp);
        iFile.ignore();
        itemName.push_back(nTemp);
        iFile >> pTemp;
        itemPrice.push_back(pTemp);
        iFile >> qTemp;
        quantity.push_back(qTemp);

        cout << itemName.size() << " " << itemPrice.size() << " " << quantity.size() 
            << endl;
    }

}

int main () {
    vector<string> nam;
    vector<double> price,quantity;
    ifstream in;
    in.open("data_adamp.txt");  
    readIn(in,nam,price,quantity);
}

Given ...

$ cat data_adamp.txt
animal a 1 2
beach b 3 4
cart c 4 5
dog d 6 7

... compiling with (GCC version 6.4.0):

$ gcc adamp.cpp -lstdc++ -oadamp

... lets me run:

$ ./adamp

... which does indeed never stop.

One way to solve this problem is to tokenize each line and convert the two rightmost fields to doubles and the rest to the record name, e.g. (using the approach in the highest-ranked answer to How do I iterate over the words of a string?):

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

using namespace std;

// See the highest-scoring answer to https://stackoverflow.com/questions/236129/how-do-i-iterate-over-the-words-of-a-string/236803#236803
template<typename Out>
void split(const std::string &s, char delim, Out result) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        *(result++) = item;
    }
}

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, std::back_inserter(elems));
    return elems;
}

void readIn(ifstream &iFile, vector<string> &itemName, vector<double> &itemPrice, 
        vector<double> &quantity)
{
    string nTemp;
    double pTemp;
    int qTemp;

    string line;
    while(getline(iFile,line))
    {
        char delim = ' ';
        vector<string> s = split(line,delim);

        istringstream ss;
        ss.str(s.back());
        ss >> qTemp;

        s.pop_back();
        ss.str(s.back());
        ss.clear();
        ss >> pTemp;

        s.pop_back();
        nTemp = "";
        for (int i = 0; i < s.size(); i++)
        {
            if (i > 0) nTemp.append(" ");
            nTemp.append(s[i]);
        }
        itemName.push_back(nTemp);
        itemPrice.push_back(pTemp);
        quantity.push_back(qTemp);

        cout << nTemp << "++" << pTemp << "++" << qTemp << endl;
    }

}

int main () {
    vector<string> nam;
    vector<double> price,quantity;
    ifstream in;
    in.open("data_adamp.txt");  
    readIn(in,nam,price,quantity);
}
Simon
  • 10,679
  • 1
  • 30
  • 44