The class string vs. C-style strings
My previous C++ post illustrated how struct
s worked. The same example -- reading student names and grades from a .csv file into an array of Student structs -- can be used to illustrate the differences between C-style strings -- null-terminated arrays of characters -- and the class string
.
The advantage of using the class string
, so far, seems to be that it saves the work of array length accounting. The global constant NAMELEN is gone. Here's the new version of the code in the previous post:
// An example of using structs: reading data from a list of student
// names and grades, saved as a .csv file, into an array. In this
// example the file is saved as .csv, but the delimiter between
// name and grade is the tab character, '\t'. Also, the first row
// of the .csv file has column names -- "name" and "grade" -- so
// I want to skip it.
//-------------------------------------------------------------------
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int LISTMAX=1000; // maximum number of students
struct Student {
string name;
float grade;
};
void readList(string infilename);
// Arguments:
// file name, passed as a class string.
// Side effects:
// open file stream, function call of fillUp.
void fillUp(ifstream& inList, Student wholeClass[],
int LISTMAX, int& stCount);
// Preconditions: global constant LISTMAX is the dimension of
// the wholeClass[] array of Student structs.
// Postconditions:
// (1) grades[0] through grades[stCount-1] filled with positive
// real numbers read from input file stream open by readList.
// (2) names[0] through names[stCount-1] are class string objects.
//-------------------------------------------------------------------
int main()
{
string infilename="example_list.csv";
readList(infilename);
return 0;
}
//-------------------------------------------------------------------
// open input, file stream call fillStudent to fill array named
// wholeClass[LISTMAX] with Student structs
void readList(string infilename)
{
ifstream inList(infilename.c_str( ));
if (inList.fail()) {
cout << "Input file opening failed.\n";
exit(1);
}
else {
Student wholeClass[LISTMAX]; // initialize array of structs
int stCount=0; // number of valid elements starts at zero
fillUp(inList, wholeClass, LISTMAX, stCount);
cout << "\nGrade Roll Report" << endl;
cout << "There were " << stCount << " students." << endl;
}
inList.close();
}
// fill wholeClass[LISTMAX] using data from infilename.
void fillUp(ifstream& inList, Student wholeClass[],
int LISTMAX, int& stCount)
{
string dummy; // container for garbage.
getline(inList,dummy,'\n'); // toss the entire first row.
for(int i=0; i<LISTMAX; i++) {
while (stCount<LISTMAX &&
getline(inList, wholeClass[i].name,'\t')) {
if(inList >> wholeClass[i].grade) {
getline(inList,dummy,'\n');
cout << "Name: " << wholeClass[i].name
<< " Grade: "<< wholeClass[i].grade << endl;
}
stCount++;
}
}
}
//-------------------------------------------------------------------
So I'm back in school, continuing the course I started last fall. We're using the same textbook, and the quotes at the beginning of the sections are only getting better. Here's the one on testing and debugging your functions: "I beheld the wretch -- the miserable monster whom I had created." Can you tell it's from Frankenstein?