0

I am unable to read the contents of a 30 row .csv file into the following struct:

class Entry {
public:
    std::string GID;
    std::string DName;
    std::string Phone;
    std::string POC;
    std::string Item;
    std::string Category;
    double amount;
};

I want to be able to create a function that can read the csv file dubbed "Donations.csv" and remove the commas because I would like to create a vector possibly like this: std::vector<Entry> entries; so that I can sort the multiple items based on whatever element in the vector. So for example say I would want to sort by DName, the code would look something like this:

// sort by DName
std::sort(entries.begin(), entries.end(), [](const Entry& a, const Entry& b) {
    return a.DName.compare(b.DName) < 0;
});

I was told not to use multiple vectors as this not safe and efficient however if it may help someone, this is how to read a csv file into multiple vectors:
FAIR WARNING, USING THE EOF CONTROLLER IS WRONG, REFER HERE
Albeit, this code will work just ok, I have personally tested it - numerous times on .csv files.

int main()
{
ifstream inFile;                    // Input file handler
ofstream outFile;                   // Output file handler

vector<string> GID;                 // Vector holding Gift ID
vector<string> DName;               // Vector holding Donor Name
vector<string> Phone;               // Vector holding Phone Number
vector<string> POC;                 // Vector holding point of contact
vector<string> Item;                // Vector holding item donated 
vector<string> Category;            // Vector holding type of item donated
vector<double> amount;              // Vector holding amount of donated items

int Input;                          // User selection choice from menu

// opening data file
inFile.open("Donations.csv");
if (!inFile)                        // If statement to check for file erroe
{
    cout << "Input file did not open. Program will exit." << endl;      // Does not compute!
    exit(0);
}

// reading contents
string str;                         // temp string to hold parse comma
double temp;                        // temp double to hold null spaces for atoi function/strtod

getline(inFile, str, ',');          // read first GID string outside of loop so that we
                                    // won't accidentally reach the end of the file in the MIDDLE of the loop

while (!inFile.eof())               // end of file not reached
{
    GID.push_back(str);
    getline(inFile, str, ',');      // get the contents of the line until a comma is encountered and push it into the necessary vector
    DName.push_back(str);
    getline(inFile, str, ',');
    Phone.push_back(str);
    getline(inFile, str, ',');
    POC.push_back(str);
    getline(inFile, str, ',');
    Item.push_back(str);
    getline(inFile, str, ',');
    Category.push_back(str);
    getline(inFile, str, '\n');     // get until the end of the line but split for parsing

    // convert string to double using strtod and c_str
    temp = strtod(str.c_str(), NULL);
    // now push double onto vector
    amount.push_back(temp);
    getline(inFile, str, ',');      // read in GID here instead of the top.  If we are at the end
                                    // of the file, it won't work and end-of-file flag will be set which is what we want.
}
inFile.close();
}
Community
  • 1
  • 1
  • 1
    "I am having trouble" is not a useful problem description. From a casual examination of the code, there are several obvious problem areas -- from `while (!inFile.eof())` being an obvious bug (see http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) to fragile, error-prone parsing using `getline()` -- but without a specific question, no specific answer is possible. – Sam Varshavchik Dec 24 '16 at 03:44
  • @SamVarshavchik Thank you sir, I have rephrase the question. Thank you for the `while (!inFile.eof())` heads up. I will update the post to reflect this. –  Dec 24 '16 at 03:49
  • @SamVarshavchik I would just to know how to read a csv file to a struct and also remove the commas from the input file –  Dec 24 '16 at 03:51
  • Start by using the sample code in http://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c to read one line at a time, and split each line into individual fields, separated by commas, into a `std::vector`. Once you have that, converting the values into a `struct` should be trivial. – Sam Varshavchik Dec 24 '16 at 04:17
  • @SamVarshavchik thank you sir! –  Dec 24 '16 at 05:06

1 Answers1

-1

Add this method:

friend std::istream& operator>>(std::istream& input, Entry& e);

to your Entry structure.

Add this to your source code:

std::istream&
operator>>(std::istream& input, Entry& e)
{
    input >> e.GID;
    input >> e.Dname;
    //.. input other members
    return input;
}

Change your containers to:

std::vector<Entry> database;

Your input loop will look something like this:

Entry e;
while (my_data_file >> e)
{
  database.push_back(e);
}

You may also want to search the internet for "stackoverflow c++ read file struct" for more examples.

In summary, create a struct or class to model the record.
Overload operator >> to read in a record.
Use std::vector of your struct, not a vector of each data member.
If you are serious about a database, then use one; don't rewrite your own.

Edit 1: Sorting
To make sorting easier, overload the > operator:

struct Entry
{
  //...
  bool operator<(const Entry& other) const
  {
    // add comparison functionality, example:
    return GID < other.GID;
  }
}

Now, you can sort the database by using:

std::sort(database.begin(), database.end());

Edit 2: Other sorting
To order the container using different criteria, you can create ordering functions and pass them to the std::sort function:

bool Order_By_Dname(const Entry& e1, const Entry& e2)
{
  return e1.Dname < e2.Dname;
}

Your sort becomes:

std::sort(database.begin(), database.end(), Order_By_Dname);
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • Thank you sir, I may not understand all of this but, I am hard at work implementing this code. Again, thank you! –  Dec 24 '16 at 05:04
  • ` database.push_back(e);` didn't parse the commas for csv file. That's what I suppose, I already took care of it. Since I'm new my upvote doesn't count. Thanks for your help though. It works! –  Dec 25 '16 at 07:48
  • The `push_back` does not parse the data from the file. Parsing of the file is in the overloaded `operator>>`. – Thomas Matthews Dec 25 '16 at 17:50