list node pointer 'not declared in this scope'? - c++

I've searched high and low trying to debug this, but so far I can't figure it out.
I've got a class declaration in a file named DataList.h, the methods in a file named DataList.cc file, and the main program in a separate .cc file.
DataList.cc has an #include header to include DataList.h.
whenever I run
g++ DataList.cc
in Ubuntu terminal, it spits out
DataList.cc: In function ‘bool TransactOnce(int&, TRANS&, std::string&)’:
DataList.cc:395:2: error: ‘ListNodeT’ was not declared in this scope
DataList.cc:395:13: error: ‘nodeTPtr’ was not declared in this scope
DataList.cc:396:13: error: ‘headTrans’ was not declared in this scope
What's weird is that I declare variables of these type ALL OVER THE PLACE in my other member functions in DataList.cc, but the compiler doesn't give me any other errors besides those above. I'm trying to figure out what it is that g++ doesn't like about those particular declarations in that one function.
'ListNodeT' is a struct within my main class, and the struct includes a pointer to another object that struct type.
'nodeTPtr' is simply a pointer to a 'ListNodeT' object, and
'headTrans' is a pointer (contained privately in the class) that points to an object of type ListNodeT, particularly, the very first node in the linked list.
The class "List" is intended for linked lists.
Here's the "DataList.h" file:
#ifndef DATALIST_H
#define DATALIST_H
#include <iostream>
#include <fstream>
#include <ostream>
#include <iomanip>
using namespace std;
const int MAXDISCIPLINES = 4;
const int MAXBREEDS = 4;
struct HORSE {
int ID;
string name; // maximum 25 alphanumeric characters, spaces included
double height;// in inches?
int age;
char genderCode;//'m', 'f', 'M', or 'F'
int breed;
int disciplineCount;
int discipline[MAXDISCIPLINES];
double lowBid; // minimum selling price
};
struct TRANS {
char transCode; //'A' for add, 'D' for delete or updating disciplines, or 'P' for updating lowBid price
HORSE transHorse;
};
class List {
private:
struct ListNodeT {
TRANS trans;
struct ListNodeT *nextLNT;
};
ListNodeT *headTrans;
struct ListNodeH {
HORSE horse;
struct ListNodeH *nextLNH;
};
ListNodeH *headHorse;
public:
//ListNodeH *headHorse;
//ListNodeT *headTrans;
List();
List(const List &obj);
~List();
bool InsertHorse(HORSE newHorse);
bool InsertTrans(TRANS newTrans);
bool DeleteHorse(int target);
bool DeleteTrans(int target);
bool ViewHorse(int target, HORSE &viewHorse);
bool ViewTrans(int target, TRANS &viewTrans);
int getNumHorses();
void getNumTrans(int &numA, int &numDel, int &numDisc, int &numP);
bool TransactOnce(int &skip, TRANS &thisTrans, string &failString);
bool UpdateDisc(TRANS thisTrans);
bool UpdatePrice(TRANS thisTrans);
void ReportOneTransaction(fstream &strm, TRANS thisTrans);
}; //end List class definition
//methods are in file DataList.cc and compiled separately.
#endif
And below is my "DataList.cc" file. The problematic "TransactOnce()" is towards the bottom.
#include "DataList.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <ostream>
#include <iomanip>
using namespace std;
//constructor
List::List(){
headHorse = NULL;
headTrans = NULL;
}
//copy constructor
List::List(const List &obj){
//copy the linked list of horses
ListNodeH *nodeHPtr;
ListNodeH **newListHPtr;
headHorse = NULL;
newListHPtr = &headHorse; //means &(this->headHorse), not &(obj.headHorse)
nodeHPtr = obj.headHorse;
while (nodeHPtr != NULL) {
*newListHPtr = new ListNodeH;
(*newListHPtr)->horse = nodeHPtr->horse;
(*newListHPtr)->nextLNH = NULL;
newListHPtr = &((*newListHPtr)->nextLNH);
nodeHPtr = nodeHPtr->nextLNH;
}
//copy the linked list of transactions
ListNodeT *nodeTPtr;
ListNodeT **newListTPtr;
headTrans = NULL;
newListTPtr = &headTrans;
nodeTPtr = obj.headTrans;
while (nodeTPtr != NULL) {
*newListTPtr = new ListNodeT;
(*newListTPtr)->trans = nodeTPtr->trans;
(*newListTPtr)->nextLNT = NULL;
newListTPtr = &((*newListTPtr)->nextLNT);
nodeTPtr = nodeTPtr->nextLNT;
}
}//end copy constructor
//destructor
List::~List(){
//destroy the list of horses
ListNodeH *nodeHPtr;
ListNodeH *nextHNode;
nodeHPtr = headHorse;
while(nodeHPtr != NULL){
nextHNode = nodeHPtr->nextLNH;
delete nodeHPtr;
nodeHPtr = nextHNode;
}//end walkthrough
//destroy the list of transactions
ListNodeT *nodeTPtr;
ListNodeT *nextTNode;
nodeTPtr = headTrans;
while(nodeTPtr != NULL){
nextTNode = nodeTPtr->nextLNT;
delete nodeTPtr;
nodeTPtr = nextTNode;
}//end walkthrough
}//end List::~List()
//********************************************************************
// FUNCTION NAME: InsertHorse()
// FUNCTION PURPOSE: inserts a new HORSE struct into our list
// INPUT PARAMETERS:
// 1. HORSE newHorse - the object of type DATA to be inserted into the List.
//RETURN VALUE – bool
//********************************************************************
bool List::InsertHorse(HORSE newHorse){
bool success = false;
ListNodeH *newNodeHPtr;
ListNodeH *nodeHPtr;
ListNodeH *prevNodeHPtr = NULL;
newNodeHPtr = new ListNodeH;
newNodeHPtr->horse = newHorse;
if(!headHorse){ //if head==NULL, our list is empty
headHorse = newNodeHPtr;
newNodeHPtr->nextLNH = NULL;
success = true;
}
else { //perhaps add? Our list is currently not empty.
nodeHPtr = headHorse;
//prevNodePtr; [sic] in my notes. I think it's supposed to be prevNodePtr = NULL;, but this should already be true
while(nodeHPtr != NULL && nodeHPtr->horse.ID < newHorse.ID){ //searches for approriate place
prevNodeHPtr = nodeHPtr;
nodeHPtr = nodeHPtr->nextLNH;
}
if(nodeHPtr != NULL && nodeHPtr->horse.ID == newHorse.ID){ //checks for duplicates
delete newNodeHPtr;
success = false; //note: this is the only way that Insert could return false
}
else { //insert the node
success = true;
newNodeHPtr->nextLNH = nodeHPtr;
if(prevNodeHPtr == NULL) //we're at the beginning of the list
headHorse = newNodeHPtr;
else //not at the beginning of the list
prevNodeHPtr->nextLNH = newNodeHPtr;
}//successful insertion
}
// delete newNodeHPtr;
return success;
}
//end List::InsertHorse()
//********************************************************************
// FUNCTION NAME: InsertTrans()
// FUNCTION PURPOSE: inserts a new TRANS struct into our list.
// if the transaction is trying to delete or update a horse that does not exist,
// returns false, and transaction is not inserted.
// INPUT PARAMETERS:
// 1. TRANS newTrans - the object of type TRANS to be inserted into the List.
//RETURN VALUE – bool
//********************************************************************
bool List::InsertTrans(TRANS newTrans){
bool success = false;
ListNodeT *newNodeTPtr;
ListNodeT *nodeTPtr;
ListNodeT *prevNodeTPtr = NULL;
newNodeTPtr = new ListNodeT;
newNodeTPtr->trans = newTrans;
HORSE dummyHorse; //dummy variable to be passed by reference to ViewHorse()
//we need to ensure a few things
//no duplicate IDs in transactions
//no Del, Disc, or P transactions for which the horse dosn't already exist in inventory
if(!headTrans){ //if head==NULL, our list is empty
headTrans = newNodeTPtr;
newNodeTPtr->nextLNT = NULL;
success = true;
}
else { //perhaps add? Our list is currently not empty.
nodeTPtr = headTrans;
//prevNodePtr; [sic] in my notes. I think it's supposed to be prevNodePtr = NULL;, but this should already be true
while(nodeTPtr != NULL && nodeTPtr->trans.transHorse.ID < newTrans.transHorse.ID){ //searches for approriate place
prevNodeTPtr = nodeTPtr;
nodeTPtr = nodeTPtr->nextLNT;
}
//check for duplicates
if(nodeTPtr != NULL && nodeTPtr->trans.transHorse.ID == newTrans.transHorse.ID){
delete newNodeTPtr;
success = false;
}
//in the case of Delete or Update transactions for which the horse does not already exist in inventory
else if((newTrans.transCode == 'D' || newTrans.transCode == 'P') && !List::ViewHorse(newTrans.transHorse.ID, dummyHorse)){
delete newNodeTPtr;
success = false;
}
else { //insert the transaction node
success = true;
newNodeTPtr->nextLNT = nodeTPtr;
if(prevNodeTPtr == NULL) //we're at the beginning of the list
headTrans = newNodeTPtr;
else //not at the beginning of the list
prevNodeTPtr->nextLNT = newNodeTPtr;
}//successful insertion
}
// delete newNodeTPtr;
return success;
}//end List::InsertTrans()
//********************************************************************
// FUNCTION NAME: DeleteHorse()
// FUNCTION PURPOSE: deletes a HORSE struct from our object of class List.
// INPUT PARAMETERS:
// 1. int target - the ID of the object of type HORSE to be deleted from List
//RETURN VALUE – bool
//********************************************************************
bool List::DeleteHorse(int target){
bool success = false;
ListNodeH *nodeHPtr;
ListNodeH *prevHPtr;
if (!headHorse) //empty list
success = false;
else if (headHorse->horse.ID == target) { //found target at the beginning of list, delete it
nodeHPtr = headHorse->nextLNH;
delete headHorse;
headHorse = nodeHPtr;
success=true;
}
else { // maybe delete?
nodeHPtr = headHorse;
while(nodeHPtr!=NULL && nodeHPtr->horse.ID < target){ //searching...
prevHPtr = nodeHPtr;
nodeHPtr = nodeHPtr->nextLNH;
}
if(nodeHPtr == NULL && nodeHPtr->horse.ID != target) //we're at the end of the list, and if target's not here...
success=false; //deletion failed. This is the only case where Delete() returns false.
else { //we're between the beginning and end, and we found the target
prevHPtr->nextLNH = nodeHPtr->nextLNH;
delete nodeHPtr; //delete target.
success = true;
}
}
return success;
}
//********************************************************************
// FUNCTION NAME: DeleteTrans()
// FUNCTION PURPOSE: deletes a TRANS struct from our object of class List.
// INPUT PARAMETERS:
// 1. int target - the ID of the object of type TRANS to be deleted from List
//RETURN VALUE – bool
//********************************************************************
bool List::DeleteTrans(int target){
bool success = false;
ListNodeT *nodeTPtr;
ListNodeT *prevTPtr;
if (!headTrans) //empty list
success = false;
else if (headTrans->trans.transHorse.ID == target) { //found target at the beginning of list, delete it
nodeTPtr = headTrans->nextLNT;
delete headTrans;
headTrans = nodeTPtr;
success=true;
}
else { // maybe delete?
nodeTPtr = headTrans;
while(nodeTPtr!=NULL && nodeTPtr->trans.transHorse.ID < target){ //searching...
prevTPtr = nodeTPtr;
nodeTPtr = nodeTPtr->nextLNT;
}
if(nodeTPtr == NULL && nodeTPtr->trans.transHorse.ID != target) //we're at the end of the list, and if target's not here...
success=false; //deletion failed. This is the only case where Delete() returns false.
else { //we're between the beginning and end, and we found the target
prevTPtr->nextLNT = nodeTPtr->nextLNT;
delete nodeTPtr; //delete target.
success = true;
}
}
return success;
}
//********************************************************************
// FUNCTION NAME: ViewHorse()
// FUNCTION PURPOSE: finds the HORSE struct whose ID is target, then returns the HORSE by reference.
// INPUT PARAMETERS:
// 1. int target - the ID to be searched for
// 2. HORSE &viewHorse - the object of type HORSE to be found and returned (by reference)
//RETURN VALUE – bool
//********************************************************************
//returns by reference the HORSE in the list with ID == target
//if View() returns false, then the target was not found and &viewHorse was not changed by ViewHorse().
bool List::ViewHorse(int target, HORSE &viewHorse){
bool success = false;
ListNodeH *nodeHPtr;
nodeHPtr = headHorse; //start at the beginning of the list
while(nodeHPtr != NULL && nodeHPtr->horse.ID < target) //search...
nodeHPtr = nodeHPtr->nextLNH;
//which test failed?
if(nodeHPtr == NULL || nodeHPtr->horse.ID != target) //we're at the end of the list, or didn't find the target.
success = false; //Note: this is the ONLY way that ViewHorse() returns false.
else { //nodeHPtr != NULL && nodeHPtr->horse.ID == target, we found the target
success = true;
viewHorse = nodeHPtr->horse; //return by reference the HORSE in the list with ID == target
}
return success;
}//end List::ViewHorse()
//********************************************************************
// FUNCTION NAME: ViewTrans()
// FUNCTION PURPOSE: finds the TRANS struct whose ID is target, then returns the TRANS by reference.
// INPUT PARAMETERS:
// 1. int target - the ID to be searched for
// 2. TRANS &viewTrans - the object of type TRANS to be found and returned (by reference)
//RETURN VALUE – bool
//********************************************************************
//returns by reference the TRANS in the list with ID == target
//if ViewTrans() returns false, then the target was not found and &viewTrans was not changed by ViewTrans().
bool List::ViewTrans(int target, TRANS &viewTrans){
bool success = false;
ListNodeT *nodeTPtr;
nodeTPtr = headTrans; //start at the beginning of the list
while(nodeTPtr != NULL && nodeTPtr->trans.transHorse.ID < target) //search...
nodeTPtr = nodeTPtr->nextLNT;
//which test failed?
if(nodeTPtr == NULL || nodeTPtr->trans.transHorse.ID != target) //we're at the end of the list, or didn't find the target.
success = false; //Note: this is the ONLY way that ViewTrans() returns false.
else { //nodeTPtr != NULL && nodeTPtr->horse.ID == target, we found the target
success = true;
viewTrans = nodeTPtr->trans; //return by reference the TRANS in the list with ID == target
}
return success;
}//end List::ViewTrans
//********************************************************************
// FUNCTION NAME: getNumHorses()
// FUNCTION PURPOSE: returns the number of nodes in our list of horses
// INPUT PARAMETERS: [none]
//RETURN VALUE – int
//********************************************************************
int List::getNumHorses(){
int horseCounter = 0;
ListNodeH *nodeHPtr;
nodeHPtr = headHorse;
while(nodeHPtr != NULL){
nodeHPtr = nodeHPtr->nextLNH;
horseCounter++;
}
return horseCounter;
}//end List::getNumHorses()
//********************************************************************
// FUNCTION NAME: getNumTrans()
// FUNCTION PURPOSE: returns (by reference) the numbers of various types of transactions in our list of transactions
// INPUT PARAMETERS:
// 1.int &numA - number of "Add" transactions
// 2.int &numDel - number of "Delete" transactions
// 3.int &numDisc - number of "update discipline" transactions
// 4.int &numP - number of "update lowBid" transactions
//RETURN VALUE – void
//********************************************************************
void List::getNumTrans(int &numA, int &numDel, int &numDisc, int &numP){
numA = 0;
numDel = 0;
numDisc = 0;
numP = 0;
ListNodeT *nodeTPtr;
nodeTPtr = headTrans;
while(nodeTPtr != NULL){
if(nodeTPtr->trans.transCode == 'A')
numA++;
else if(nodeTPtr->trans.transCode == 'D'){
if (nodeTPtr->trans.transHorse.disciplineCount == 0)
numDel++;
else
numDisc++;
}
else if(nodeTPtr->trans.transCode == 'P'){
numP++;
}
nodeTPtr = nodeTPtr->nextLNT;
}
}//end List::getNumTrans()
//********************************************************************
// FUNCTION NAME: TransactOnce()
// FUNCTION PURPOSE: Performs a single transaction.
// [skip] number of transactions at the beginning of the linked list of trans are skipped.
// The transaction immediately after the skipped transactions is attempted.
// If the transaction fails, skip is incremented and the function returns false.
// In any case, thisTrans is returned by reference as the transaction that was just attempted.
// INPUT PARAMETERS:
// 1. int &skip - the number of transactions to skip
// 2. TRANS &thisTrans - the returned transaction that was just attempted
// 3. string &failString - the ERROR, if any.
//RETURN VALUE – bool
//********************************************************************
bool TransactOnce(int &skip, TRANS &thisTrans, string &failString){
bool success = true;
stringstream failStream;
ListNodeT *nodeTPtr;
nodeTPtr = headTrans;
HORSE dummyHorse; //for ViewHorse()
//if 'A', the ID must not already exist in our list of horses
//if 'D' or 'P', the horse must already exist in our list of horses.
//if 'D' and disciplineCount != 0, then
//the existing horse must already have disciplineCount <4
//transaction's transHorse.discipline[] must not have duplicates in the array
//each of transaction's transHorse.discipline[]s must be valid (1<= discipline <=4)
//find the transaction in question
for (int i=0; i < skip; i++){
nodeTPtr = nodeTPtr->nextLNT;
}
//nodeTPtr is now pointing to the appropriate ListNodeT.
if (nodeTPtr->trans.transCode == 'A' && !List::InsertHorse(nodeTPtr->trans.transHorse)){
failStream << "ERROR for horse transaction" << nodeTPtr->trans.transHorse.ID << " via InsertHorse().";
success = false;
}
else if (nodeTPtr->trans.transCode == 'D'){ //delete or update disciplines
if(nodeTPtr->trans.transHorse.disciplineCount == 0 && !List::DeleteHorse(nodeTPtr->trans.transHorse.ID)){ //for deletion
failStream << "ERROR for horse transaction" << nodeTPtr->trans.transHorse.ID << " via DeleteHorse().";
success = false;
}
else if(nodeTPtr->trans.transHorse.disciplineCount != 0 && !List::UpdateDisc(nodeTPtr->trans)){ //update disciplines
failStream << "ERROR for horse transaction" << nodeTPtr->trans.transHorse.ID << " via UpdateDisc().";
success = false;
}
}
else if (nodeTPtr->trans.transCode == 'P' && !List::UpdatePrice(nodeTPtr->trans)){
failStream << "ERROR for horse transaction" << nodeTPtr->trans.transHorse.ID << " via UpdatePrice().";
success = false;
}
else {
failStream << "ERROR for horse transaction" << nodeTPtr->trans.transHorse.ID << ", not a valid transCode.";
success = false;
}
if (success){ //attempt to delete the transaction
if (!List::DeleteTrans(nodeTPtr->trans.transHorse.ID)){
failStream << "ERROR, could not delete transaction " << nodeTPtr->trans.transHorse.ID << ".";
success = false;
}
else //return true and error free
failStream << "No error to report.";
}
if (!success)
skip++;
failStream << "\n";
failString = failStream.str();
return success;
}//end TransactOnce()
//********************************************************************
// FUNCTION NAME: UpdateDisc()
// FUNCTION PURPOSE: for an "update discipline" transaction, update the disciplines of that horse in inventory.
// INPUT PARAMETERS:
// 1. TRANS thisTrans - the transaction to be executed
//RETURN VALUE – bool
//********************************************************************
bool List::UpdateDisc(TRANS thisTrans){
bool success = true;
ListNodeH *nodeHPtr = headHorse; //no need for a ListNodeT
//obtain a pointer to the horse in question
while (nodeHPtr != NULL && nodeHPtr->horse.ID < thisTrans.transHorse.ID)
nodeHPtr = nodeHPtr->nextLNH;
if(nodeHPtr == NULL) //failed to find the horse
success = false;
//horse found; nodeHPtr->horse.ID == thisTrans.transHorse.ID
else if(thisTrans.transCode != 'D') //this isn't even a "D" transaction...
success = false;
else if(thisTrans.transHorse.disciplineCount == 0) //nothing to do, this is for deletion
success = false;
else if(nodeHPtr->horse.disciplineCount + thisTrans.transHorse.disciplineCount > 4)
success = false; //too many disciplines
else {
//update the disciplines
while(thisTrans.transHorse.disciplineCount !=0){
nodeHPtr->horse.discipline[nodeHPtr->horse.disciplineCount] = thisTrans.transHorse.discipline[thisTrans.transHorse.disciplineCount-1];
nodeHPtr->horse.disciplineCount++;
thisTrans.transHorse.disciplineCount--;
}//disciplines are now updated but perhaps not sorted
//bubble-sort the horse's array of disciplines.
int i, j;
bool swaped = true;
int tempInt;
for(i = 1; (i <= nodeHPtr->horse.disciplineCount)&&swaped; i++){
swaped = false;
for (j=0; j< nodeHPtr->horse.disciplineCount-1; j++){
if(nodeHPtr->horse.discipline[j] > nodeHPtr->horse.discipline[j+1]){
tempInt = nodeHPtr->horse.discipline[j];
nodeHPtr->horse.discipline[j] = nodeHPtr->horse.discipline[j+1];
nodeHPtr->horse.discipline[j+1] = tempInt;
swaped = true;
}
}
}
}//end update and sort horse's disciplines
return success;
}//end List::UpdateDisc()
//********************************************************************
// FUNCTION NAME: UpdatePrice()
// FUNCTION PURPOSE: for an "update lowBid" transaction, update the lowBid of that horse in inventory.
// INPUT PARAMETERS:
// 1. TRANS thisTrans - the transaction to be executed
//RETURN VALUE – bool
//********************************************************************
bool List::UpdatePrice(TRANS thisTrans){
bool success = true;
ListNodeH *nodeHPtr;
nodeHPtr = headHorse;
//obtain a pointer to the horse in question
while (nodeHPtr != NULL && nodeHPtr->horse.ID < thisTrans.transHorse.ID)
nodeHPtr = nodeHPtr->nextLNH;
if(nodeHPtr == NULL) //failed to find the horse
success = false;
//else, horse found; nodeHPtr->horse.ID == thisTrans.transHorse.ID
else if(thisTrans.transCode != 'P') //this isn't even a "P" transaction...
success = false;
else { //update lowBid
nodeHPtr->horse.lowBid = thisTrans.transHorse.lowBid;
}
return success;
}//end List::UpdatePrice()
//********************************************************************
// FUNCTION NAME: ReportOneTransaction()
// FUNCTION PURPOSE: prints to Report.out a single transaction. called by Transact().
// INPUT PARAMETERS:
// 1. fstream &strm - the stream to print to.
// 2. TRANS oneTrans - the transaction being reported.
//RETURN VALUE – void
//********************************************************************
void List::ReportOneTransaction(fstream &strm, TRANS oneTrans){
//some "Ragged Arrays"
string breedDescription[MAXBREEDS+1] = {"Dummy", "Pleasure Saddle Horse", "American Fox Trotter", "Virginia Highlander", "Arabian"};//21
string disciplineDescription[MAXDISCIPLINES+1] = {"Dummy", "Dressage", "Jumper", "Hunter", "Western Pleasure"};//16
if (oneTrans.transCode == 'A')
strm << "Horse ADDED to inventory named '" ;
else
strm << "Horse REMOVED from inventory named '" ;
strm << oneTrans.transHorse.name << "'"<< endl;
strm << "______________________________________________________________________\n";//70
strm <<"ID Height Age M/F LowBid "<< oneTrans.transHorse.disciplineCount << " Discipline(s): Breed\n";
strm << left << setw(3) <<oneTrans.transHorse.ID <<" ";//ID
strm << left << setw(5) <<setprecision(2) <<oneTrans.transHorse.height <<" ";//height (double)
strm << left << setw(3) <<oneTrans.transHorse.age <<" ";//age
strm << left << setw(1) <<oneTrans.transHorse.genderCode; //genderCode (char)
strm << " "<<left<<'$';
strm << right << fixed << setw(8) << setprecision(2) << oneTrans.transHorse.lowBid ;//lowBid (double)
strm << left << " " << setw(16) << disciplineDescription[oneTrans.transHorse.discipline[0]] ;
strm << " " << breedDescription[oneTrans.transHorse.breed] << endl;
for (int j=1; j < oneTrans.transHorse.disciplineCount; j++){
strm << " ";
strm << disciplineDescription[oneTrans.transHorse.discipline[j]] << endl;
}
strm << endl << endl;
}//end ReportOneTransaction()

You forgot List:: on TransactOnce so it's trying to parse it as a stand-alone function. I did this myself just a couple days ago...

The TransactOnce function should be implemented as it was declared, as a member function of List:
Change this:
bool TransactOnce(int &skip, TRANS &thisTrans, string &failString){
to this:
bool List::TransactOnce(int &skip, TRANS &thisTrans, string &failString){

OP here. I figured it out.
when defining TransactOnce()
bool TransactOnce(.....)
should have been
bool List::TransactOnce(....)

Related

LinkedList sorting a-z

Requirements for this function: If the full name (both the first and last name) is not equal to any full name currently in the list then add it and return true. Elements should be added according to their last name. Elements with the same last name should be added according to
their first names. Otherwise, make no change to the list and return false (indicating that the name is already in the list).
//this function add nodes to the list
//return true if fullname isn't in the list. Else return false if fullname is in the list.
//should be added according to last name.
bool OnlineDating::makeMatch(const std::string& firstName, const std::string& lastName, const OnlineType& value)
{
Node* p = head;
//are these nodes already set to firstName and lastName in this function
Node first;
Node last;
Node* temp = nullptr;
//if the list is empty just insert the fullname and value to the list
if (p == nullptr) {
//add values to the empty list
insertToRear(firstName, lastName, value);
return true;
}
else {
// so this loop is to check if fullname is in the list but first sort in alphebetial order
//sure its added in alphebetical order
//traverse the list after knowing where head is
while (p != nullptr) {
//checking to make sure theres at least another node in the list
if (p->next != nullptr) {
//its not going through ig loop?
//these are used to check and alphebetically selected names
if (p->last > p->next->last) {
insertToRear(p->first, p->last, p->value);
p->next = temp;
return true;
}
else if (p->next->last > p->last) {
insertToRear(p->first, p->last, p->value);
p->next = temp;
return true;
}
//check if full name is already in the list
if (p->last == p->next->last) {
insertToRear(p->first, p->last, p->value);
p->next = temp;
return true;
}
else if (p->first > p->next->first) {
insertToRear(p->first, p->last, p->value);
p->next = temp;
return true;
}
else {
//returns false if it passes through these checks
return false;
}
}
p = p->next;
}
}
}
Here is my main.cpp
int main()
{
OnlineDating clippersGonnaClip;
clippersGonnaClip.makeMatch("Kawhi", "Leonard", 2);
clippersGonnaClip.makeMatch("Paul", "George", 13);
clippersGonnaClip.makeMatch("Ivica", "Zubac", 40);
clippersGonnaClip.makeMatch("Reggie", "Jackson", 1);
clippersGonnaClip.makeMatch("Patrick", "Beverley", 21);
for (int n = 0; n < clippersGonnaClip.howManyMatches(); n++) {
string first;
string last;
int val;
clippersGonnaClip.confirmMatch(n, first, last, val);
cout << first << " " << last << " " << val << endl;
}
return 0;
}
honestly, I just want to create a ptr that will point to each node. Check as long as that node isn't pointing to nullptr, and sort the LinkedList in alphabetical order. finally link the nodes together using my *temp. Why won't it let me go through the if statements every time I compile I get a negative number? Every other function works for this program except this makeMatch(...).
Nothing in the requirements says anything about the data types you need to use. In this case using std::set makes most sense.
By providing a comparison operation on persons and a set you can guarantee uniqueness. Like this :
#include <set>
#include <string>
struct person_t
{
std::string name;
std::string last_name;
unsigned int age;
};
bool operator<(const person_t& lhs, const person_t& rhs)
{
if (lhs.last_name == rhs.last_name)
return lhs.name < rhs.name;
return lhs.last_name < rhs.last_name;
}
int main()
{
// set will ensure all persons are unique
std::set<person_t> persons;
persons.insert({ "Kawhi", "Leonard", 2 });
persons.insert({ "Paul", "George", 13 });
persons.insert({ "Ivica", "Zubac", 40 });
persons.insert({ "Reggie", "Jackson", 1 });
persons.insert({ "Patrick", "Beverley", 21 });
}

Rapidxml next_sibling not return the next sibling

I want to select the "actual" xml node by attribute.
When I try to iterate trough the nodes, it only return the first one,
but strangely, when I ask the last node, it will return it without any problem. Also, if I search it with name like "actualroot->first_node("roodnode1")" it will found it.
edit:
I checked it just in case and the "actualroot" have parent
Rapidxml version: 1.13
(I tried different version too(1.1), and it had the same result)
The saved xml:
<rootnode Game="gamename">
<rootnode0 table="a" cluster="b" item="c"/>
<rootnode1 table="atest" cluster="btest" item="ctest"/>
<rootnode2 table="1" cluster="2" item="3"/>
</rootnode>
The simplified verion of the code I use:
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
using namespace std;
using namespace rapidxml;
bool listloaded;
bool actualcontainerloaded;
int rootcounter;
xml_document<> *actuallist;
xml_node<>* actualroot;
xml_node<>* actualcontainer;
std::unordered_map<std::string, xml_document<>*> xmllistmap;
main()
{
listloaded = false;
actualcontainerloaded = false;
rootcounter = 0;
create("tastx")
addcontainer("a","b","c")
addcontainer("atest","btest","ctest")
addcontainer("1","2","3")
setactualcontainer("atest","btest","ctest")
}
bool create(string name)
{
if (isalreadyexist(name)) return false;
//RPXdata oneRPX;
xml_document<> *newlist = new xml_document<>();
xml_node<>* root = newlist->allocate_node(node_element, newlist->allocate_string("rootnode"));
root->append_attribute(newlist->allocate_attribute("Game", newlist->allocate_string("gamename")));
newlist->append_node(root);
newlist->name(name.c_str());
xmllistmap[name] = newlist;
actuallist = newlist;
actualroot = newlist->first_node();
listloaded = true;
return true;
}
bool addcontainer(string table, string cluster, string item)
{
if (listloaded)
{
for (xml_node<> *child = actualroot->first_node(); child; child = actualroot->next_sibling())
{
if (child->first_attribute("table") == NULL) continue;
string tableattr = child->first_attribute("table")->value();
if (tableattr != table) continue;
if (child->first_attribute("cluster") == NULL) continue;
string clusterattr = child->first_attribute("cluster")->value();
if (clusterattr != cluster) continue;
if (child->first_attribute("item") == NULL) continue;
string itemattr = child->first_attribute("item")->value();
if (itemattr == item) continue;
return false;
}
string rootname = "rootnode"+functions.converttostring(rootcounter);
xml_node<>* root = actuallist->allocate_node(node_element, actuallist->allocate_string(rootname.c_str()));
root->append_attribute(actuallist->allocate_attribute("table", actuallist->allocate_string(table.c_str())));
root->append_attribute(actuallist->allocate_attribute("cluster", actuallist->allocate_string(cluster.c_str())));
root->append_attribute(actuallist->allocate_attribute("item", actuallist->allocate_string(item.c_str())));
actualroot->append_node(root);
functions.log("container added:" + table);
rootcounter++;
}
return false;
}
bool setactualcontainer(string table, string cluster, string item)
{
if (listloaded)
{
for (xml_node<> *child = actualroot->first_node(); child; child = actualroot->next_sibling())
{
xml_node<> *lastchild = actualroot->last_node();
string lcname = lastchild->name();
functions.log("last name: " + lcname);
string cname = child->name();
functions.log("cname: " + cname);
functions.log("for step called");
if (child->first_attribute("table") == NULL) continue;
string tableattr = child->first_attribute("table")->value();
string clusterattr = child->first_attribute("cluster")->value();
string itemattr = child->first_attribute("item")->value();
functions.log("actual tableattr:" + tableattr);
if (tableattr == table && clusterattr == cluster && itemattr == item)
{
functions.log("actual continer settd:"+ table);
actualcontainer = child;
actualcontainerloaded = true;
return true;
}
}
}
return false;
}
The result:
23:11:17: container added:a
23:11:17: container added:atest
23:11:17: container added:1
23:11:17: last name: rootnode2
23:11:17: cname: rootnode0
23:11:17: for step called
23:11:17: actual tableattr:a
Just a simple inattention:
The for loop
for (xml_node<> *child = actualroot->first_node(); child; child = actualroot->next_sibling())
actually should looks like this:
for (xml_node<> *child = actualroot->first_node(); child; child = child->next_sibling())

C++ binary search tree creates segmentation fault

I'm trying to make a program that identifies AVR assembly instructions by opcode, since those are just a list of 1's and 0's I thought it would be a good project to make a binary search tree for.
Sadly I keep getting segmentation faults when trying to search through the tree. As I understand it a seg fault is usually the result of trying to do stuff with a pointer that doesn't point to anything, but since I have a Boolean that I check first that should never happen.
I'm pretty sure it has something to do with the way I use pointers, as I'm not very experienced with those. But I can't seem to figure out what's going wrong.
Below is the code involved (SearchTree is only a global variable in this minimal example, not in the real program.):
The code:
#include <iostream>
void ADD(short &code) {std::cout << code << "\n";}
void LDI(short &code) {std::cout << code << "\n";}
void SBRC(short &code){std::cout << code << "\n";}
struct node
{
void(* instruct)(short &code);
bool hasInst = false;
struct node *zero;
bool hasZero = false;
struct node *one;
bool hasOne = false;
};
node SearchTree;
auto parseOpcode(short code, node *currentRoot)
{
std::cout << "Looking for a: " << ((code >> 15) & 0b01 == 1) << std::endl;
std::cout << "Current node 1: " << (*currentRoot).hasOne << std::endl;
std::cout << "Current node 0: " << (*currentRoot).hasZero << std::endl;
// Return instruction if we've found it.
if ((*currentRoot).hasInst) return (*currentRoot).instruct;
// Case current bit == 1.
else if ((code >> 15) & 0b01 == 1)
{
if ((*currentRoot).hasOne) return parseOpcode((code << 1), (*currentRoot).one);
else throw "this instruction does not exist";
}
// Case current bit == 0.
else {
if ((*currentRoot).hasZero) return parseOpcode((code << 1), (*currentRoot).zero);
else throw "this instruction does not exist";
}
}
void addopcode(void(& instruct)(short &code), int opcode, int codeLength)
{
node *latest;
latest = &SearchTree;
for (int i = 0; i <= codeLength; i++)
{
// Add function pointer to struct if we hit the bottom.
if (i == codeLength)
{
if ((*latest).hasInst == false)
{
(*latest).instruct = &instruct;
(*latest).hasInst = true;
}
}
// Case 1
else if (opcode >> (codeLength - 1 - i) & 0b01)
{
if ((*latest).hasOne)
{
latest = (*latest).one;
}
else{
node newNode;
(*latest).one = &newNode;
(*latest).hasOne = true;
latest = &newNode;
}
}
// Case 0
else {
if ((*latest).hasZero)
{
latest = (*latest).zero;
}
else{
node newNode;
(*latest).zero = &newNode;
(*latest).hasZero = true;
latest = &newNode;
}
}
}
}
int main()
{
addopcode(ADD, 0b000011, 6);
addopcode(LDI, 0b1110, 4);
addopcode(SBRC, 0b1111110, 7);
short firstOpcode = 0b1110000000010011;
void(* instruction)(short &code) = parseOpcode(firstOpcode, &SearchTree);
instruction(firstOpcode);
return 0;
}
EDIT: I still had some #includes at the top of my file that linked to code I didn't put on StackOverflow.
The error happened because I forgot to use the new keyword and was therefor populating my search tree with local variables (which were obviously now longer around by the time I started searching through the tree).
Fixed by using:
node *newNode = new node();
(*latest).one = newNode;
(*latest).hasOne = true;
latest = newNode;
Instead of:
node newNode;
(*latest).one = &newNode;
(*latest).hasOne = true;
latest = &newNode;

Why does my recursion not return to previous pointer?

I am working on an assignment in which we must create a 20-questions type game from a binary search tree. We read the tree in from a text file that is formatted like this:
Does it walk on 4 legs?
Does it fly?
*centipede?
Is it an insect?
*bird?
*butterfly?
Does it purr?
Does it howl?
*mouse?
*dog?
*cat?
Later, I am going to allow the user to add to this list. At the moment, however, I am unable to accurately read the list into a binary search tree. I have set it up so that (I think) it will use recursion and return to the previous "current" node pointer when it ends a loop of the function. Currently, however, the current node pointer remains the same.
The below function is passed a vector of the strings from the text file.
string line;
string guess;
bool start = true;
void buildTree(vector<string> gameData, Node* current, int &counter)
{
//fill node with question or answer
//recursive:
// add to the left until we encounter an asterisk
// add to the right
line = gameData[counter];
//if a question
if (line[0] != '*')
{
if (current->getData().empty())
{
current->setData(line);
cout << current->getData() << endl;
}
if (!start)
{
//if noChild is empty AND current isn't a guess, go to noChild
if ((current->getNo()->getData().empty())
&& (current->isGuess() == false))
{
current = current->getNo();
}
//otherwise, go to yes
else {
current = current->getYes();
}
}
while (counter < gameData.size())
{
if (!start) { counter++; }
start = false;
buildTree(gameData, current, counter);
}
}
//if a guess
else
{
//if data is full, go to no
if (current->getData().empty() == false)
{
current = current->getNo();
}
//otherwise, go to yes
else
{
//current = current->getYes();
for (int i = 1; i < line.size(); i++)
{
guess.push_back(line[i]);
}
current->setData(guess);
guess.clear();
cout << current->getData() << endl;
counter++;
current->setGuess(true);
}
}
}

Program Terminates unexpectedly C++

The goal of the program is to simulate a medical complex with 6 "Doctor Queues". I tried keeping it close enough to the Java version I've completed (must do this in 3 languages). At this point when I run the DequeuePatients and ListPatients method, the program terminates unexpectedly with no errors. I've tried the debugger but eclipse is ignoring all my breakpoints.Why is it terminating?
The ListPatients method is all follows in Driver class:
void ListPatients() {
int x, QueueChoice = 0;
bool exit = false;``
while (!exit) {
for (x = 1; x <= MAX; x++) {
cout << x << ": " << Doctor[x - 1] << "\n";
} // end-for
cout << "Choose a Queue to List From";
cin >> QueueChoice;
if (OpenFlag[QueueChoice - 1] == true) { //open flag for each queue
int i = Complex[QueueChoice - 1]->GetSize();//Global array of queues
//cout <<i<<endl;
Terminates in this loop if function is called
for (x = 1; x <= i; x++) {
Patient This = Complex[QueueChoice-1]->GetInfo(x); //Program Terminates here
cout << x<< ": " << endl;//This.ID_Number;
//<<Complex[QueueChoice - 1]->GetInfo(x + 1).PrintMe()
} // end-for
} // end-if
cout << "Press 1 to List Another Queue, press 2 to exit";
cin >> x;
switch (x) {
case 1:
break;
case 2:
exit = true;
break;
}//switch
} // end-while
} // List Patients`
Queue Class GetInfo and toArray():
/*Return Patient info from each Node*/
Patient Queue::GetInfo(int Pos) {
Node* ComplexArray= new Node[Length];
ComplexArray = this->toArray();
return ComplexArray[Pos - 1].Info;
}
// The toArray method
Node* Queue::toArray() {
// Copy the information in each node to an array and return the array.
int x = Length;
Node ComplexArray[Length] ={} ;
Node* Current = new Node();
Current = Rear;`
for (x = 0; x<Length;x++) {
ComplexArray[x] = Node();
ComplexArray[x].Modify(Current);
Current = Current->Next;
}
return ComplexArray;
} // End of toArray method
Modify Method in Node:
void Node :: Modify(Node* ThisNode)
{
Info = ThisNode->Info;
Next = ThisNode->Next;
}
If this is base-zero why are you subtracting 1 from x
for (x = 0; x<Length;x++) {
ComplexArray[x-1] = Node();
ComplexArray[x - 1].Modify(Current);
Current = Current->Next;
}
Subscript errors are hard crashes in C/C++.
The problem was sort of basic, it was way I was declaring my pointers, as well as changing the toArray function to return a Patient pointer(That can be treated as an array?) as apposed to Node, and not just to the first element of the array.
this caused toArray to return one Node pointer, with that instances Next pointer continuously pointing to itself.
Queue Complex[6] = Queue(); //in driver class
Patient* ComplexArray[Length] = new Patient();//Queue Class GetInfo & toArray
I needed:
Queue* Complex = new Queue[MAX];
Patient* ComplexArray = new Patient[Length];
and changed these functions:
Patient Queue::GetInfo(int Pos) {
Patient* ComplexArray = new Patient[Length];
ComplexArray= toArray();
return ComplexArray[Pos - 1];
}
// Now returns Patient pointer of Node->Info to GetInfo
Patient* Queue::toArray() {
Node* Current;
int x;
Patient* ComplexArray = new Patient[Length];
Current = Rear;
for (x = 1; x <= Length; x++) {
ComplexArray[x-1] = Patient();
ComplexArray[x - 1].Modify(Current->Info);
Current = Current->Next;
}
return ComplexArray;
} // End of toArray method