My previous C++ post illustrated how structs 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?