I am trying to count the number of each letter grade for a list of students and count how many are male and female and how many students there are total. The problematic section is:

int ItemType::CountItems(int& ACount, int& BCount, int& CCount, int& DCount, int& FCount,
                         int& MaleCount, int& FemaleCount, int& TotalCount, char grd,
                         char sex)
{
  if(!TotalCount > 0)
  {
    ACount = 0;
    BCount = 0;
    CCount = 0;
    DCount = 0;
    FCount = 0;
    MaleCount = 0;
    FemaleCount = 0;
  }

  if(grd == 'A')
  {
    ACount++;
    return ACount;
  }
  if(grd == BGrd)
  {
    BCount++;
    return BCount;
  }
  if(grd == CGrd)
  {
    CCount++;
    return CCount;
  }
  if(grd == DGrd)
  {
    DCount++;
    return DCount;
  }
  else
  {
    FCount++;
    return FCount;
  }

  if(sex == MALE)
  {
    MaleCount++;
    return MaleCount;
  }
  else
  {
    FemaleCount++;
    return FemaleCount;
  }

  TotalCount++;
}

void ItemType::CallCountItems()
{
  CountItems(ACount, BCount, CCount, DCount, FCount, MaleCount, FemaleCount, TotalCount, grd,
             sex);
}

Here's the whole thing (ItemType.h, ItemType.cxx, SortedLinkedList.h, and client code)
ITEMTYPE.H

#include <fstream>
#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

const int MAX_ID = 999;
const int MIN_ID = 111;

const char MALE = 'M';
const char FEMALE = 'F';
const char AGrd = 'A';
const char BGrd = 'B';
const char CGrd = 'C';
const char DGrd = 'D';
const char FGrd = 'F';

enum  RelationType {LESS, EQUAL, GREATER};

class ItemType
{
  public :

    ItemType();
    ItemType(int inid, char ingrd, char insex);
    RelationType ComparedTo(ItemType otheritem) const;
    void GetItemFromFile(ifstream& inFile);
    int CountItems(int& ACount, int& BCount, int& CCount, int& DCount, int& FCount,
                   int& MaleCount, int& FemaleCount, int& TotalCount, char grd,
                   char sex);
    void CallCountItems();
    void GetIdFromFile(ifstream& inFile);
    void WriteIdToFile(ofstream& outFile) const;
    void WriteItemToFile(ofstream& outFile) const;
    void WriteInvalidItemToFile(ofstream& outFile) const;
    void Initialize(int id, char grd, char sex);
    bool ValidItem();
   void PrintStats(ofstream& outFile);

  private :
    int id;
    char grd;
    char sex;

    int ACount;
    int BCount;
    int CCount;
    int DCount;
    int FCount;
    int MaleCount;
    int FemaleCount;
    int TotalCount;

} ;

ITEMTYPE.CXX

#include "ItemType.h"

ItemType::ItemType()
//****************************************************************************************
//Purpose: Sets the default values
//Input: None
//Pre: Initializer variables have been declared
//Output: None
//Post: Default values have been assigned
//Note: None
//****************************************************************************************
{
  id = -100;
  grd = 'H';
  sex = 'x';
}

ItemType::ItemType(int inid, char ingrd, char insex)
//****************************************************************************************
//Purpose: Assign data to inid, ingrd, insex
//Input: inid, ingrd, insex
//Pre: All variables contain data
//Output: None
//Post: inid, ingrd, insex are assigned values
//Note: None
//****************************************************************************************
{
  id = inid;
  grd = ingrd;
  sex = insex;
}

RelationType ItemType::ComparedTo(ItemType otherItem) const
//****************************************************************************************
//Purpose: Compares one item key to another item key and tells less, equal, or more than
//Input: otheritem
//Pre: List has data
//Output: None
//Post: Determined if a key is less, equal, or greater than another item key
//Note: None
//****************************************************************************************
{
  if (id < otherItem.id)
        return  LESS;
  else if (id  > otherItem.id)
             return  GREATER;
       else
             return  EQUAL;
}

void ItemType::GetItemFromFile(ifstream& inFile)
//****************************************************************************************
//Purpose: Inputs a record from file
//Input: inFile
//Pre: File is open an ok
//Output: None
//Post: Record is input from file
//Note: None
//****************************************************************************************
{
  inFile >> id >> grd >> sex;
}

int ItemType::CountItems(int& ACount, int& BCount, int& CCount, int& DCount, int& FCount,
                         int& MaleCount, int& FemaleCount, int& TotalCount, char grd,
                         char sex)
//****************************************************************************************
//Purpose: Counts the number of A,B,C,D, or F and the number of M or F
//Input: grd, sex
//Pre: id has value
//Output: Integer
//Post: A,B,C,D, or F and M or F has been counted
//Note: None
//****************************************************************************************
{
  if(!TotalCount > 0)
  {
    ACount = 0;
    BCount = 0;
    CCount = 0;
    DCount = 0;
    FCount = 0;
    MaleCount = 0;
    FemaleCount = 0;
  }

  if(grd == 'A')
  {
    ACount++;
    return ACount;
  }
  if(grd == BGrd)
  {
    BCount++;
    return BCount;
  }
  if(grd == CGrd)
  {
    CCount++;
    return CCount;
  }
  if(grd == DGrd)
  {
    DCount++;
    return DCount;
  }
  else
  {
    FCount++;
    return FCount;
  }

  if(sex == MALE)
  {
    MaleCount++;
    return MaleCount;
  }
  else
  {
    FemaleCount++;
    return FemaleCount;
  }

  TotalCount++;
}

void ItemType::CallCountItems()
//****************************************************************************************
//Purpose: Calls the function that counts grades and sex
//Input: None
//Pre: None
//Output: None
//Post: The function that counts grades and sex is called
//Note: None
//****************************************************************************************
{
  CountItems(ACount, BCount, CCount, DCount, FCount, MaleCount, FemaleCount, TotalCount, grd,
             sex);
}

void ItemType::GetIdFromFile(ifstream& inFile)
//****************************************************************************************
//Purpose: Inputs a single ID from file
//Input: inFile
//Pre: File is open and ok
//Output: None
//Post: A single ID is input from file
//Note: None
//****************************************************************************************
{
  inFile >> id;
}

void ItemType::WriteIdToFile(ofstream& outFile) const
//****************************************************************************************
//Purpose:
//Input:
//Pre: outFile is open and ok
//Output: outFile
//Post:
//Note: None
//****************************************************************************************
{
  outFile.setf(ios::left);
  outFile << setw(10) << id;
}

void ItemType::WriteItemToFile(ofstream& outFile) const
//****************************************************************************************
//Purpose: Prints valid record to outFile
//Input: None
//Pre: outFile is open and ok
//Output: outFile
//Post: Valid record is printed
//Note: None
//****************************************************************************************
{
  outFile.setf(ios::left);
  outFile << setw(10) << id <<setw(10) << grd << setw(10) << sex << endl;
}

void ItemType::WriteInvalidItemToFile(ofstream& outFile) const
//****************************************************************************************
//Purpose: Prints invalid record to outFile
//Input: None
//Pre: outFile is open and ok
//Output: outFile
//Post: Invalid record is printed
//Note: None
//****************************************************************************************
{
  outFile.setf(ios::left);
  outFile << setw(8) << id << setw(3) << grd << setw(3) << sex << setw(16) << " ~~~Invalid data" << endl;
}

void ItemType::Initialize(int id, char grd, char sex)
//****************************************************************************************
//Purpose: Sets the default values
//Input: None
//Pre: Initializer variables have been declared
//Output: None
//Post: Default values have been assigned
//Note: None
//****************************************************************************************
{
  id = -100;
  grd = 'H';
  sex = 'x';
}

bool ItemType::ValidItem()
//****************************************************************************************
//Purpose: Determines if a record is valid or invalid
//Input: None
//Pre: There is data
//Output: Boolean
//Post: Record determined to be valid or invalid
//Note: None
//****************************************************************************************
{
  return ((id >= MIN_ID)&&
          (id <= MAX_ID)&&
          ((grd == 'A')||(grd == 'B')||(grd == 'C')||(grd == 'D')||(grd == 'F'))&&
          ((sex == MALE)||(sex == FEMALE)));
}

void ItemType::PrintStats(ofstream& outFile)
//****************************************************************************************
//Purpose: Prints the statistics for all valid records
//Input: None
//Pre: There are valid records
//Output: outFile
//Post: Statistics are printed for all valid records
//Note: None
//****************************************************************************************
{
  outFile << ACount << endl;
  outFile << BCount << endl;
  outFile << CCount << endl;
  outFile << DCount << endl;
  outFile << FCount << endl;
  outFile << MaleCount << endl;
  outFile << FemaleCount << endl;
  outFile << endl;

  if(ACount > 0)
    outFile << (ACount/TotalCount) << "%" << " A" << endl;
  if(BCount > 0)
    outFile << (BCount/TotalCount) << "%" << " B" << endl;
  if(CCount > 0)
    outFile << (CCount/TotalCount) << "%" << " C" << endl;
  if(DCount > 0)
    outFile << (DCount/TotalCount) << "%" << " D" << endl;
  if(FCount > 0)
    outFile << (FCount/TotalCount) << "%" << " F" << endl;
  outFile << endl;

  outFile << (MaleCount/TotalCount) << "%" << "Male" << endl;
  outFile << (FemaleCount/TotalCount) << "%" << "Female" << endl;
  outFile << endl;
}

SORTEDLINKEDLIST.H

#include "ItemType.h"

struct NodeType
{
  ItemType info;
  NodeType* next;
};

// SortedType.h
class SortedType
{
 public:
  SortedType();
  ~SortedType();
  SortedType(const SortedType& otherList);
  bool IsFull() const;
  int  LengthIs() const;
  void MakeEmpty();
  void RetrieveItem(ItemType& item, bool& found);
  void InsertItem(ItemType item);
  void DeleteItem(ItemType item);
  void ResetList();
  void GetNextItem(ItemType& item);
  void Print(ofstream& outFile);

 private:
  NodeType* listData;
  int length;
  NodeType* currentPos;
};

// SortedType.cxx
SortedType::SortedType()  // Class constructor
//****************************************************************************************
//Purpose: Constructor
//Input: None
//Pre: None
//Output: None
//Post: Empty list is created
//Note: None
//****************************************************************************************
{
  length = 0;
  listData = NULL;
}

SortedType::~SortedType()
//****************************************************************************************
//Purpose: Destructor
//Input: None
//Pre: List has been created
//Output: None
//Post: List is destroyed
//Note: None
//****************************************************************************************
{
  MakeEmpty();
}

SortedType::SortedType(const SortedType& otherList)
//****************************************************************************************
//Purpose: Copy-constructor
//Input: None
//Pre: List has been created
//Output: None
//Post: List is created as duplicate of otherList
//Note: None
//****************************************************************************************
{
    NodeType* fromPtr;  // Pointer into list being copied from
    NodeType* toPtr;    // Pointer into new list being built
    if(otherList.listData == NULL)
    {
        listData = NULL;
        return;
    }
    // Copy first node
    fromPtr = otherList.listData;
    listData = new NodeType;
    listData->info = fromPtr->info;

    // Copy remaining nodes

    toPtr = listData;
    fromPtr = fromPtr->next;
    while (fromPtr != NULL)
    {
        toPtr->next = new NodeType;
        toPtr = toPtr->next;
        toPtr->info = fromPtr->info;
        fromPtr = fromPtr->next;
    }
    toPtr->next = NULL;
}

bool SortedType::IsFull() const
//****************************************************************************************
//Purpose: Determines whether list is full
//Input: None
//Pre: List has been created
//Output: Boolean
//Post: Function value = (list is full)
//Note: None
//****************************************************************************************
{
  NodeType* ptr;

  ptr = new NodeType;
  if (ptr == NULL)
    return true;
  else
  {
    delete ptr;
    return false;
  }
}

int SortedType::LengthIs() const
//****************************************************************************************
//Purpose: Determines the number of elements in list
//Input: None
//Pre: List has been created
//Output: Integer
//Post: Function value = number of elements in list
//Note: None
//****************************************************************************************
{
  return length;
}

void SortedType::MakeEmpty()
//****************************************************************************************
//Purpose: Initializes list to empty state
//Input: None
//Pre: List has been created
//Output: None
//Post: List is empty
//Note: None
//****************************************************************************************
{
  NodeType* tempPtr;
  while (listData != NULL) // traverse list, deallocating each node in turn
  {
    tempPtr = listData;
    listData = listData->next;
    delete tempPtr;
  }
  length = 0;
}

void SortedType::DeleteItem(ItemType item)
//****************************************************************************************
//Purpose: Deletes the element whose key matches item's key
//Input: item
//Pre: Key member of item is intialized; Only one element in list has key matching item's
//Output: None
//Post: No element in list has key matching item's key
//Note: None
//****************************************************************************************
{
  NodeType* location = listData;
  NodeType* tempLocation;

  // Locate node to be deleted.
  if (item.ComparedTo(listData->info)== EQUAL)
  {
    tempLocation = location;
    listData = listData->next;          // Delete first node.
  }
  else
  {
    while (!((item.ComparedTo((location->next)->info))== EQUAL))
      location = location->next;

    tempLocation = location->next;
    location->next = (location->next)->next;
  }
  delete tempLocation;
  length--;
}

void SortedType::ResetList()
//****************************************************************************************
//Purpose: Initializes current position to end of list for iteration through list
//Input: None
//Pre: List has been created
//Output: None
//Post: Current position is at end of list
//Note: None
//****************************************************************************************
{
  currentPos = NULL;
}

void SortedType::RetrieveItem(ItemType& item, bool& found)
//****************************************************************************************
//Purpose: Retrieves list element whose key matches item's key (if present)
//Input: item
//Pre: Key menmber of item is initialized
//Output: None
//Post: If there is an eleemnt someItem whose key matches item's key, then found = true
// and item is a copy of someItem; otherwise, found = false and item is unchanged. List is
// unchanged
//Note: None
//****************************************************************************************
{
  bool moreToSearch;
  NodeType* location;

  location = listData;
  found = false;
  moreToSearch = (location != NULL);

  while (moreToSearch && !found)
  {
    switch(item.ComparedTo(location->info))
    {
      case GREATER:
        location = location->next;
        moreToSearch = (location != NULL);
        break;

      case EQUAL:
        found = true;
        item = location->info;
        break;

      case LESS:
        moreToSearch = false;
        break;
    }
  }
}

void SortedType::InsertItem(ItemType item)
//****************************************************************************************
//Purpose: Adds item to list
//Input: item
//Pre: List is not full; item is not in list
//Output: None
//Post: Item is in list (added); list order is preserved
//Note: None
//****************************************************************************************
{
  NodeType* newNode;  // pointer to node being inserted
  NodeType* predLoc;  // trailing pointer
  NodeType* location; // traveling pointer
  bool moreToSearch;

  location = listData;
  predLoc = NULL;
  moreToSearch = (location != NULL);

  // Find insertion point.
  while (moreToSearch)
  {
    if(item.ComparedTo(location->info) == GREATER)
    {
      predLoc = location;
      location = location->next;
      moreToSearch = (location != NULL);
    }
    else
      moreToSearch = false;
  }

  // Prepare node for insertion
  newNode = new NodeType;
  newNode->info = item;

  // Insert node into list.
  if (predLoc == NULL)         // Insert as first
  {
    newNode->next = listData;
    listData = newNode;
  }
  else
  {
    newNode->next = location;
    predLoc->next = newNode;
  }
  length++;
}

void SortedType::GetNextItem(ItemType& item)
//****************************************************************************************
//Purpose: Gets the next element in list
//Input: item
//Pre: List has been created and has data
//Output: None
//Post: If current position is at end, currentPos points to head of list, else item is
// copy of element at current position. Advance current position.
//Note: None
//****************************************************************************************
{
  if (currentPos == NULL) //Wrap at end of list
    currentPos = listData;

  item = currentPos->info;
  currentPos = currentPos->next;
}

void SortedType::Print(ofstream& outFile)
//****************************************************************************************
//Purpose: Prints valid data to outFile
//Input: None
//Pre: There is valid data to be printed
//Output: outFile
//Post: Valid data is printed to outFile
//Note: None
//****************************************************************************************
{
   currentPos = listData;

   while(currentPos != NULL)
   {
       currentPos ->info.WriteItemToFile(outFile);
       currentPos = currentPos->next;
   }
}

I think you forgot to state what the problem was, all you did was post the problematic code and a whole lot more code...

Chris

The problem is that the counters within the first section of code (the problematic code) are not working. Here's an example of the problem (ignore the 958, 959, etc., they are line numbers):

Input:
A 999 A F
A 122 B M
A 756 C F
P
A 598 B M
A 742 C F
P

Output:
958 <* Grade Report *>
959
960
961 STUD ID GRADE SEX
962 ------- ----- ---
963 122 B M
964 756 C F
965 999 A F
966
967 7
968 1073847661
969 1073843105
970 1073845404
971 1074017075
972 -1073744724
973 1073778547
974
975 0% A
976 0% B
977 0% C
978 0% D
979 1% F
980
981 0%Male
982 0%Female
983
984
985
986 STUD ID GRADE SEX
987 ------- ----- ---
988 122 B M
989 598 B M
990 742 C F
991 756 C F
992 999 A F
993
994 7
995 1073847662
996 1073843106
997 1073845404
998 1074017075
999 -1073744724
1000 1073778547
1001
1002 0% A
1003 0% B
1004 0% C
1005 0% D
1006 1% F
1007
1008 0%Male
1009 0%Female
1010
1011
1012 <~ end ~>


In lines 994-1000 all of the mumbo jumbo is my function PrintStats printing ACount, BCount, CCount, DCount, FCount, MaleCount, FemaleCount. These counters appear to be printing a memory location instead of counting and printing how many A's, B's, etc. there are. I cannot figure out how to code the counters so they count the grade and the sex of each student.

I only looked at the code briefly, so there may well be other errors and I may have overlooked sections that address areas discussed below.

1) I don't see where totalCount is initialized to zero. Based on quick review of code it looks like this should probably be done in the constructor.

2) There is no reason to pass or return the variables ACount, BCount, etc to coutnItems() as they are member variables and member functions of the ItemType class.

I just added TotalCount so that it is initialized to 0.

if(!TotalCount > 0)
  {
    ACount = 0;
    BCount = 0;
    CCount = 0;
    DCount = 0;
    FCount = 0;
    MaleCount = 0;
    FemaleCount = 0;
    TotalCount = 0;
  }

That won't work. You need to initialize TotalCount to a valid value before you use int in the conditional of the if statement. Again, I recommend doing it in the constructor.

This article has been dead for over six months. Start a new discussion instead.