c++ structs
   

.. what is a struct?

struct
====== 
collection of a fixed number of components, accessed by name
   Components may be of different types – heterogeneous
   Components are called the members of the struct

struct is a reserved word

general syntax of a struct is:
      struct structName
      {
        dataType1  identifier1;
        dataType2  identifier2;
        .
        .
        dataTypen  identifiern;
      };

      Does this allocate storage? NO!

** Simple struct example: SIX data fields struct studentType // struct definition { // NO memory allocation string firstName; string lastName; char courseGrade; int testScore; int programmingScore; double GPA; }; // declare two variables of this type - ALLOCATES MEMORY! studentType student; studentType newStudent; // read in FOUR data items inFile >> student.firstName >> student.lastName >> student.testScore >> student.programmingScore; // Calculate the FIFTH field: GPA student.GPA = (student.testScore + student.programmingScore) / 2.0; // Calculate SIXTH field: Grade if (student.GPA >= 90) student.courseGrade = 'A'; else if (student.GPA >= 80) student.courseGrade = 'B'; else if (student.GPA >= 70) student.courseGrade = 'C'; else if (student.GPA >= 60) student.courseGrade = 'D'; else student.courseGrade = 'F'; // Output all SIX Fields cout << student.firstName << endl << student.lastName << endl << student.testScore << endl << student.programmingScore << endl << student.GPA << endl << student.courseGrade << endl; // Assign ALL fields of struct at once newStudent = student; // legal!! Value of one ENTIRE struct var can be assigned to another struct var (as long as same type...)
Array of structs ================ struct studentType // struct definition { // NO memory allocation string firstName; string lastName; char courseGrade; int testScore; int programmingScore; double GPA; }; // declare ARRAY of structs - ALLOCATES MEMORY for 50 structs! studentType student[ 50 ]; Print ONE student struct (record) from array cout << student[ 0 ].firstName << endl << student[ 0 ].lastName << endl << student[ 0 ].testScore << endl << student[ 0 ].programmingScore << endl << student[ 0 ].GPA << endl << student[ 0 ].courseGrade << endl;
In a loop, print ALL for (int i=0; i<50; i++) { cout << student[ i ].firstName << endl << student[ i ].lastName << endl << student[ i ].testScore << endl << student[ i ].programmingScore << endl << student[ i ].GPA << endl << student[ i ].courseGrade << endl; }

.. code: structs: collections of different data (heterogeneous)

C++ Primer Plus Chapter 4
C++ code examples 11-13


.. structs in multi-file projects

Header Files ( .h )
=================
   A separate file with data definitions that can be shared
   by multiple files in a project.
      Single definition
      Easier to update / maintain


Example: THREE FILE PROGRAM : 2 functions, 1 include file ======= ( CC main.cpp out.cpp -o letter ) // FILE: project.h // define struct in project.h, then each .cpp file can include it struct letterType // globally defined { char letter; int count; }; ------------------------------ // FILE: main.cpp #include <iostream> #include "project.h" // <<==== Syntax!! void out(letterType); using namespace std; int main( ) { letterType aLetter[ 5 ]; cin >> aLetter[ 0 ].letter >> aLetter[ 0 ].count; out( aLetter[ 0 ] ); system( "pause" ); return 0; } ------------------------------ // FILE: out.cpp // function uses struct #include "project.h" void out( letterType let ) { cout << let.letter << let.count; return; }

.. arrays in arrays of structs

 arrays in array of structs
 ==========================

   struct personType  // struct definition
   {                  // NO memory allocation
   char name[ 50 ];
   int height;
   int weight;
   int testScores[ 5 ];
   };

   personType student[ 10 ];
   -------------------------
   student[ 0 ].height = 72;
   student[ 0 ].weight = 185;
   student[ 0 ].testScores[ 0 ] = 99;
   student[ 0 ].testScores[ 1 ] = 90;
   student[ 0 ].testScores[ 2 ] = 76;
   student[ 0 ].testScores[ 3 ] = 81;
   student[ 0 ].testScores[ 4 ] = 100;

   // input struct array
   for ( int i=0; i<10; i++ )
   {
      cin >> student[ i ].name; // can enter entire string
      student[ i ].height = rand( )%120 + 90;
      student[ i ].weight = rand( )%100 + 100;
      for ( int j=0; j<5; j++ )
         student[ i ].testScores[ j ] = rand( )%101;
   }

   // output array of structs
   for ( int i=0; i<10; i++ )
   {
      cout << student[ i ].name; // entire string
      cout << student[ i ].height;
      cout << student[ i ].weight;
      for ( int j=0; j<5; j++ )
         cout << student[ i ].testScores[ j ];
   }

   // output c string by char in array of structs
   for ( int i=0; i<10; i++ )
   {
      int j=0;
      while ( student[ i ].name[ j ] != 0 ) 
         cout << student[ i ].name[ j++ ]; // out one char at a time
      cout << student[ i ].height;
      cout << student[ i ].weight;
      for ( int j=0; j<5; j++ )
         cout << student[ i ].testScores[ j ];
   }

C strings ( character arrays ) =========================== C strings are character sequences stored as one-dimensional character arrays and terminated with a null character ('\0', called NUL in ASCII). For compatibility with "older" code, it is sometimes necessary to convert a string object into a character array ("C-style string"). char name[ 10 ] = "Bill B"; |B|i|l|l| |B|\0| | | | 0 1 2 3 4 5 6 7 8 9 c_str() function ================ Converts a string object into a c-string. For example, to open a file stream with a user-specified file name: // filenames provided to open function must be zero-termintaed c-string string filename; ofstream outfile; cout << "Enter file name: "; cin >> filename; outfile.open( filename.c_str() );

.. code: arrays of structs

Programming Example
===================
• Six salespeople go on road trips to sell the company’s product
• End of each month
   total sales for each salesperson,
   salesperson’s ID,
   the month,
   are recorded in a file
• End of each year, the manager of the company asks for a report

Output Format ============= ----------- Annual Sales Report ------------- ID QT1 QT2 QT3 QT4 Total _______________________________________________________________ 12345 1892.00 0.00 494.00 322.00 2708.00 32214 343.00 892.00 9023.00 0.00 10258.00 23422 1395.00 1901.00 0.00 0.00 3296.00 57373 893.00 892.00 8834.00 0.00 10619.00 35864 2882.00 1221.00 0.00 1223.00 5326.00 54654 893.00 0.00 392.00 3420.00 4705.00 Total 8298.00 4906.00 18743.00 4965.00 Max Sale by SalesPerson: ID = 57373, Amount = $10619.00 Max Sale by Quarter: Quarter = 3, Amount = $18743.00 QT1 stands for quarter 1 (months 1 to 3), QT2 for quarter 2 (months 4 to 6), QT3 for quarter 3 (months 7 to 9) and QT4 for quarter 4 (months 10 to 12)
Programming Analysis ==================== Salespeople IDs stored in one file; sales data are stored in another file Sales data is in the following form: salesPersonID month saleAmount Sales data are not ordered Input/Output • Input: file containing each salesperson’s ID, file containing the sales data • Output: file containing annual sales report in above format Problem Analysis • Main components for each sales person: - ID - Quarterly sales amount - Total annual sales amount (need struct, different types) • There are six people, so an array of 6 components is used • Program requires company’s total sales for each quarter - need an array of four components to store the data • Read salespeople IDs into the array salesPersonList • Init quarterly sales and total sales for each salesperson to 0 • For each entry in the file containing the sales data - Read ID, month, sale amount for month - Search salesPersonList to locate component corresponding to salesperson - Determine the quarter corresponding to the month - Update the sales for the quarter by adding sale amount for the month • Once the sales data file is processed - Calculate the total sale by salesman - Calculate the total sale by quarter - Print the report
Algorithm Design ================ - Initialize the array sales - Process the sales data - Calculate the total sale by salesman - Calculate the total sale by quarter - Print the report - Calculate and print maximum sale by salesman - Calculate and print maximum sale by quarter ------------------------------------------------------------------------- Main Algorithm • Prompt user to enter name of file containing the salesperson’s ID data • Read the name of the input file and Open the input file • If input file does not exist exit • Initialize the array salesPersonList by calling the function initialize • Close input file containing salesperson’s ID • Prompt user to enter name of file containing sales data • Read the name of the input file and Open the input file • If input file does not exist exit • Prompt user to enter name of output file • Read the name of the output file and Open the output file • Output data to two decimal places • Process sales data function getData • Calculate the total sale by quarter function saleByQuarter • Calculate the total sale by salesman function totalSaleByPerson • Print the report in the tabular form function printReport • Find and print the salesperson who produces the maximum sales for the year function maxSaleByPerson • Find and print the quarter producing the maximum sale for the year function maxSaleByQuarter • Close files
CODE ==== //Program: Sales data analysis #include <iostream> #include <fstream> #include <iomanip> #include <string> using namespace std; const int noOfSalesPerson = 6; struct salesPersonRec { string ID; double saleByQuarter[ 4 ]; double totalSale; }; void initialize( ifstream& indata, salesPersonRec list[],int listSize ); void getData( ifstream& infile, salesPersonRec list[], int listSize ); void saleByQuarter( salesPersonRec list[], int listSize, double totalByQuarter[] ); void totalSaleByPerson( salesPersonRec list[], int listSize ); void printReport( ofstream& outfile, salesPersonRec list[], int listSize, double saleByQuarter[] ); void maxSaleByPerson( ofstream& outData, salesPersonRec list[], int listSize ); void maxSaleByQuarter( ofstream& outData, double saleByQuarter[] ); int main( ) { ifstream infile; ofstream outfile; string inputFile; string outputFile; double totalSaleByQuarter[ 4 ]; // sale by quarter salesPersonRec salesPersonList[ noOfSalesPerson ]; //salesperson's data // get salespeople file info cout << "Enter the salesPerson ID file name: "; cin >> inputFile; cout << endl; infile.open( inputFile.c_str() ); if ( !infile ) { cout << "Cannot open the input file." << endl; return 1; } // process salespeople file initialize( infile, salesPersonList, noOfSalesPerson ); infile.close(); //reclaim the input file stream variable; infile.clear(); //clear the input stream cout << "Enter the sales data file name: "; cin >> inputFile; infile.open( inputFile.c_str() ); if ( !infile ) { cout << "Cannot open the input file." << endl; return 1; } // setup output cout << "Enter the output file name: "; cin >> outputFile; outfile.open( outputFile.c_str() ); outfile << fixed << showpoint << setprecision(2); // get info about sales and process getData( infile, salesPersonList, noOfSalesPerson ); saleByQuarter( salesPersonList, noOfSalesPerson, totalSaleByQuarter ); totalSaleByPerson( salesPersonList, noOfSalesPerson ); printReport( outfile, salesPersonList, noOfSalesPerson, totalSaleByQuarter ); maxSaleByPerson( outfile, salesPersonList, noOfSalesPerson ); maxSaleByQuarter( outfile, totalSaleByQuarter ); // finish up infile.close( ); outfile.close( ); return 0; } //--------------------------------------------------------------------- // void initialize( ifstream& indata, salesPersonRec list[], int listSize ) { int index; int quarter; for ( index = 0; index < listSize; index++ ) { indata >> list[index].ID; //get salesperson's ID for ( quarter = 0; quarter < 4; quarter++ ) list[ index ].saleByQuarter[ quarter ] = 0.0; list[ index ].totalSale = 0.0; } return; } //--------------------------------------------------------------------- // void getData( ifstream& infile, salesPersonRec list[], int listSize ) { int index, quarter, month; string sID; double amount; infile >> sID; //get salesperson's ID while ( infile ) { infile >> month >> amount; //get the sale month and the sale amount for ( index = 0; index < listSize; index++ ) if ( sID == list[index].ID ) break; if ( 1 <= month && month <= 3 ) quarter = 0; else if (4 <= month && month <= 6) quarter = 1; else if (7 <= month && month <= 9) quarter = 2; else quarter = 3; if (index < listSize) list[index].saleByQuarter[quarter] += amount; else cout << "Invalid salesperson's ID." << endl; infile >> sID; }//end while return; } //--------------------------------------------------------------------- // void saleByQuarter(salesPersonRec list[], int listSize, double totalByQuarter[]) { int quarter; int index; for (quarter = 0; quarter < 4; quarter++) totalByQuarter[quarter] = 0.0; for (quarter = 0; quarter < 4; quarter++) for (index = 0; index < listSize; index++) totalByQuarter[quarter] += list[index].saleByQuarter[quarter]; return; } //--------------------------------------------------------------------- // void totalSaleByPerson(salesPersonRec list[], int listSize) { int index, quarter; for (index = 0; index < listSize; index++) for (quarter = 0; quarter < 4; quarter++) list[index].totalSale += list[index].saleByQuarter[quarter]; return; } //--------------------------------------------------------------------- // void printReport(ofstream& outfile, salesPersonRec list[], int listSize, double saleByQuarter[]) { int index, quarter; outfile << "----------- Annual Sales Report -------------" << endl; outfile << endl; outfile << " ID QT1 QT2 QT3 " << "QT4 Total" << endl; outfile << "________________________________________________" << "_______________" << endl; for (index = 0; index < listSize; index++) { outfile << list[index].ID << " "; for (quarter = 0; quarter < 4; quarter++) outfile << setw(10) << list[index].saleByQuarter[quarter]; outfile << setw(10) << list[index].totalSale << endl; } outfile << "Total "; for (quarter = 0; quarter < 4; quarter++) outfile << setw(10) << saleByQuarter[quarter]; outfile << endl << endl; return; } //--------------------------------------------------------------------- // void maxSaleByPerson(ofstream& outData, salesPersonRec list[], int listSize) { int maxIndex = 0, index; for (index = 1; index < listSize; index++) if (list[maxIndex].totalSale < list[index].totalSale) maxIndex = index; outData << "Max Sale by SalesPerson: ID = “ << list[maxIndex].ID << ", Amount = $" << list[maxIndex].totalSale << endl; return; } //--------------------------------------------------------------------- // void maxSaleByQuarter(ofstream& outData, double saleByQuarter[]) { int quarter, maxIndex = 0; for (quarter = 0; quarter < 4; quarter++) if (saleByQuarter[maxIndex] < saleByQuarter[quarter]) maxIndex = quarter; outData << "Max Sale by Quarter: Quarter = " << maxIndex + 1 << ", Amount = $" << saleByQuarter[maxIndex] << endl; return; }