0

So I have a .txt file I'm supposed to be reading information in from and displaying in a neat little table. Here's a snippet of the .txt files contents in the format

Farm name, item count, item, price, total price

Collins Farm, 43900 tomatoes 0.67 29413
Bart Smith Farms, 34910 cassavas 0.99 34560.9
Allen Farms, 117 coconuts 0.54 63.18

etc...

It should print out in the console as

Collins Farm (some spaces here) 43900 items contributed totaling $29413.00

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

using namespace std;
int addLine(int);

int main()
{
using std::ifstream;

ifstream myFile;
myFile.open("ASSGN6-B.txt");

string farmName;
int itemCount;
string itemName;
double itemPrice;
double totalPrice;

if (!myFile)
{
    cout << "File open failed!" << endl;
}
else
{
    cout << "\t\t\t=========================================================" << endl;
    cout << "\t\t\t=               FARMER'S MARKET INVENTORY               =" << endl;
    cout << "\t\t\t=========================================================" << endl;

    while (myFile.good())
    {
        getline (myFile, farmName);
        getline (myFile, itemName);
        myFile >> itemName >> itemPrice >> totalPrice;
        cout << farmName << "       " << itemCount << " items contributed totaling $" << totalPrice << endl;

    }
}


myFile.close();
return 0;
}

This is what I've been messing with trying to figure out how this input stuff works. I guess what I really don't get is how it's supposed to know which item is which. I previously thought it just read in a line at a time only but theres's gotta be a way to separate the items even on the same line and print them all separately in the console.

Also, some farm names appear twice in the .txt file and I'm supposed to combine their data into one line if it's a duplicate. Help with this would be appreciated too.

Thanks.

R Sahu
  • 196,807
  • 13
  • 136
  • 247
Cartino
  • 31
  • 1
  • 7
  • I highly recommend searching the internet for "StackOverflow C++ read file csv". This will list many examples for you to study. – Thomas Matthews Mar 19 '18 at 23:18

3 Answers3

2

First piece of advice:

Don't use

while (myFile.good()) { ... }

You need to make sure that the data you expect to read are indeed read successfully.

See Why is iostream::eof inside a loop condition considered wrong? to understand why.

Coming to the other problems...

The line

    getline (myFile, farmName);

will read an entire line to farmName. That's not what you want. You want to read everything up to the comma (,) character. std::getline has such an option. Use

    getline (myFile, farmName, ',');

It's not clear what you were hoping to accomplish by

    getline (myFile, itemName);

That line can be removed.

Looking at the sample data, all you need is

    myFile >> itemCount >> itemName >> itemPrice >> totalPrice;

to read rest of the data.

However, after you read them, make sure to ignore the everything in that line. You can use istream::ignore for that.

Here's my suggestion.

while ( getline(myFile, farmName, ',') &&
       (myFile >> itemCount >> itemName >> itemPrice >> totalPrice) )
{
    cout << farmName << "       " << itemCount << " items contributed totaling $" << totalPrice << endl;

    // Ignore rest of the line
    myFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Make sure to add

#include <limits>

to be able to use std::numeric_limits.

R Sahu
  • 196,807
  • 13
  • 136
  • 247
0

I think you should try to do more research to understand file operations in c++, but I noticed a few things with your code:

getline(myFile, farmName);

This line will take the entire line of the file it's reading and store it into farmName. It basically reads the line until it finds the end of line character. I think your intention was for the line to read until the comma for the farm name, thus you would use:

getline(myFile, farmName, ',');

The third parameter is an optional delimiting character that tells getline what character to look for to stop reading at.

The next lines that I noticed are:

getline(myFile, itemName);
myFile >> itemName >> itemPrice >> totalPrice;

Why are you reading data into itemName twice? I think you meant to read into itemCount first before itemName by the looks of your file format, thus you should eliminate the first line shown above and just have:

myFile >> itemCount >> itemName >> itemPrice >> totalPrice;

In terms of adding to the existing data if the farm name appears more than once, your current code overwrites the data from each line after printing and continuing to the next iteration of the while loop. Thus, you would have to redesign your code to save previous values from farms and check if the farm appears more than once and determine what to do from there.

Sirius
  • 73
  • 1
  • 4
  • Thanks. I updated my code according to suggestions from others in the thread and it's now working as intended. As for redesigning the structure to allow for combining the data, could you lead me in the right direction of how this might look? – Cartino Mar 19 '18 at 22:36
  • @Cartino I'm not sure what your assignment entails, but you could create a class to represent a "farm item" and give it an attribute for farm name, item name, item price, and item count. Then you could create an array or vector to hold a number of farm items and add a new farm item to that array/vector of farm items if it doesn't already exist. Instead of printing each farm item's data right after reading it, you can then wait until you've filled your array/vector and then print everything you collected after you close the file. – Sirius Mar 19 '18 at 23:26
  • @Cartino The reason I didn't say to add an attribute for total price is because it would be a derived value from (item count) * (item price) and thus would be better to just be a method that returns those two values multipled. Thus instead of a variable member for total price, you'd have a method that returns a double called getTotalPrice() that simply does what I stated previously. – Sirius Mar 19 '18 at 23:30
0

Could use regex:

std::string line;
std::regex r{R"(([^,]*), ?([^ ]*) ([^ ]*) ([^ ]*) (\d*.?\d*))"};
std::smatch m;
while(getline(myFile, line)){
    std::regex_match(line, m, r);

    std::string farmName    {          m[1] };
    int itemCount           {std::stoi(m[2])};
    std::string itemName    {          m[3] }; 
    double itemPrice        {std::stod(m[4])};
    double totalPrice       {std::stod(m[5])};

    std::cout << farmName << "       " << itemCount << " items contributed totaling $" << totalPrice << std::endl;
}
wally
  • 9,757
  • 3
  • 34
  • 63