1

For my university class in programming we have been working on Object Oriented Programming (OOP) and are currently working on a group project. The project is to create a cash register that holds items with their names, amounts, and prices. As well as have a way to track the coins given by the user then determine the coin denomination. These are supposed to be done in different classes and involve objects.

My question is regarding the inventory manager that I am coding. The inventory manager is supposed to take the "data.txt" file and read it into the appropriate vectors. Currently I have a vector for the item name, price, amount, and then the itemList vector which holds a string of all 3 to print to the user for readability.

Here is a snippet from the data file:

20 1.99 Potato Chips
10 5.99 Ibuprofen
4 1.42 Candy
55 3.10 Coffee
12 3.25 Hummus
12 4.55 Guacamole 
7 0.80 Baklava
45 1.50 Chocolate Chip Cookies

My question is, how do I split the line up so that I can pass the amount (first number) to the appropriate vector, pass the price to the appropriate vector, then pass the name to the appropriate vector. Essentially splitting each line into 3 parts. The part that is the most difficult to me is how the names of the items can be 1 word, 2 words, or even 3 words. Making it difficult to predict how many spaces the name will have, which caused a lot of my attempts to not work.

I found a working solution though I'm worried it's incorrect or inefficient and I'm curious in knowing the best way to do this. Thank you so much ahead of time and I will post the class definition and the method I'm working in down below.

< The stream object is inFile>

class inventoryManager
{
    private:
        double total, change, choice;
        vector <int> amount;
        vector <string> name;
        vector <double> price;
        vector <string> itemList;
    public:
        void fileOpen(fstream& inFile);
        void fillInventory(fstream& inFile);
        void printInventory(fstream& inFile);
};
void inventoryManager::fillInventory(fstream& inFile)
{
    string temp;
    string a, b;
    
    while (!inFile.eof())
    {
        inFile >> a >> b;
        amount.push_back(stoi(a));
        price.push_back(stod(b));
        getline(inFile, temp);
        name.push_back(temp);
        itemList.push_back(temp);
    }
}

Attempted: I tried using the find() function to find each space then use the index to print the estimated indices to each side of the white space to the vectors. Though it was extremely messy and wouldn't work if a different data file was inputted. The idea of the program is to be able to work if a different file is put in, similar format but the amount could be 100, and prices could be more digits. I also tried editing the file directly by adding new lines for each space but ran into the item names with multiple spaces and ultimately didn't work.

Yeonari
  • 61
  • 8
  • 1
    Trick: Don't have a structure of many `vector`s, have a single `vector` of a structure that represents one record of data. You'll find the book-keeping is much simpler. – user4581301 Oct 30 '22 at 05:19
  • `while (!inFile.eof())` is a a common bug. See [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/q/5605125/4581301) for details. – user4581301 Oct 30 '22 at 05:20
  • What you have written, get the int, get the double get the rest of the line is so close to correct it's not funny. All you should need to do is better protect the error cases. If you take the first suggestion you can `record data; while (inFile >> data.amount >>data.price && getline(InFile, data.name) { datavector.push_back(data); itemList.push_back(data.name); }` Now isf anything goes wrong, including hitting the end of the file, the reading stops and you can process what you got or clean up and try to continue ([use option 2 here in that case](https://stackoverflow.com/a/7868998/4581301). – user4581301 Oct 30 '22 at 05:30

1 Answers1

0

You are trying to do too many new things at once. Break the problem into pieces and solve them separately, then combine them. To break the string into pieces you can use find and substr, you just have to be careful and debug until you're sure it's working perfectly:

string s = "45 1.50 Chocolate Chip Cookies";
cout << "s: " << s << endl; // for debugging

size_t first = s.find(' ');
cout << first << endl; // for debugging

string amountString = s.substr(0, first);
cout << amountString << "X" <<  endl; // for debugging

size_t second = s.find(' ', first+1);
cout << second << endl; // for debugging

string priceString = s.substr(first+1,second-first-1);
cout << priceString << "X" << endl; // for debugging

string nameString = s.substr(second+1);
cout << nameString << "X" << endl; // for debugging

The purpose of those X's is to be certain that the substring has no trailing space.

Once you have tackled the problem this way (and handed the result in for a grade), you can advance to tools like stringstream, and you won't have to deal with this grubby index arithmetic any more.

Beta
  • 96,650
  • 16
  • 149
  • 150
  • 1
    Those `#` are Python comments. – Jason Oct 30 '22 at 05:43
  • This is a fine answer, but you also should really address the design issues the question has, like storing 3 parallel vectors of data that should be within one object – dwcanillas Oct 30 '22 at 05:44
  • @dwcanillas Could you elaborate on how I would move the vectors into one object? – Yeonari Oct 30 '22 at 06:16
  • 1
    @JasonLiam: Good catch, very careless of me, thank you. – Beta Oct 30 '22 at 15:39
  • @dwcanillas: As I said, the OP must focus on one (minimal) problem at a time. – Beta Oct 30 '22 at 15:47
  • @Yeonari: The idea is not to move the *vectors* into one object; the idea is to move the three *variables* into a class, and then have a vector of objects of that class, rather than having three vectors (one for each variable). It's worth the time to work this out with pencil and paper, and make sure you understand the difference. Then try writing a class called `Item` (that's a bad name, but I can't think of a better one now), with members `int amount`, `double price` and `string name`. Then you can read one record into one `Item`, and keep all of the `Item`s in a `vector`. – Beta Oct 30 '22 at 16:01
  • @Yeonari Beta said exactly what I was getting at. In addition to a solution like that being able to remove your `amount`, `name`, and `price` vectors, you could also add functions to that `Item` object like `Print()` or `ToString()` which would allow you to get rid of your `itemList` vector - you could recreate the original string from the stored members inside the new object. – dwcanillas Oct 30 '22 at 23:53
  • @dwcanillas Thanks for the help everyone. I'll go over this with my group members tomorrow in class and return with any other questions if we have trouble with it, as long as you're still following the thread. Cheers! – Yeonari Oct 31 '22 at 04:42