Calling a base function from derived class function? - c++

The class BaseSearch is the base function that I'm trying to call within the derived function (ValueSearch).
The code that I have in question specifically is under ValueSearch, calling BaseSearch::Print(line, title). The compiler errors I'm getting are:
I'm uncertain if I'm using inheritance correctly.
Error 1 error C2275: 'std::string' : illegal use of this type as an expression
BaseSearch.cpp
BaseSearch::BaseSearch()
{
}
BaseSearch::~BaseSearch()
{
}
void Print(string line, string title)
{
char c2 = '_'; //set character to blank value; defines the header row
char c = '_'; //set character to blank value; defines the searched row
int numHeader = 0; //sets the value of character for the header row
int numLine = 0; //sets the value of character for the searched row
c2 = line[numLine];
while (true) //force while loop
{
c = title[numHeader]; numHeader++; //header character is set to the title array defined as the entire header string above
if (c != ',')
{
cout << c; // couts the header until it reaches a ','
}
if (c == ',' || title.size() == numHeader) // if c reaches a ',' it will print the searched row
{
cout << ": ";
while (line.size() != numLine)
{
while (c2 != ',' && line.size() != numLine)
{
cout << line[numLine];
numLine++;
if (line.size() != numLine)
c2 = line[numLine];
else
break;
}
if (line.size() != numLine)
{
numLine++;
c2 = line[numLine];
cout << "\n";
break;
}
}
}
if (title.size() == numHeader) // if c reaches a null value, it breaks until other row is found.
{
cout << endl << endl; break;
}
}
}
BaseSearch.h
#ifndef BASESEARCH_H
#define BASESEARCH_H
#include <string>
class BaseSearch
{
public:
BaseSearch();
virtual ~BaseSearch();
virtual void Print(string, string);
};
Value Search.cpp
ValueSearch::ValueSearch()
{
string input;
}
ValueSearch::~ValueSearch()
{
//dtor
}
double ValueSearch::getInput()
{
cout << endl << "Enter the name of the company you would like to search for: ";
cin >> input;
return input;
}
void ValueSearch::ValueSearchFunc(int c, int x)
{
column = c;
// cout << "Enter the name of the company you would like to search for: ";
// getline(cin, input);
string line;
ifstream fs("Stock Database.csv");
string title;
getline(fs, title);
while (!fs.eof())
{
getline(fs, line);
string companyname = ""; //start as blank, then append
string a;
int commacount = 0; //how many commas have we passed
int ChrCount = 0; //counter for which character in the line we are looking at
while (line != "\0") //while the line does not equal to null value.
{
double price;
price = 0;
a = line[ChrCount]; //convert char c to a string (a) so that we can append
ChrCount++;
if (a == ",")
{
commacount++; //increases the comma count as a encounters a comma each time.
}
else if (commacount == column && (a != "N" && a != "/" && a != "A")) //if comma count is equal to the set column, it will append the string company name.
{
while (a != ",")
{
if (a != ",")
{
companyname.append(a);
a = line[ChrCount];
ChrCount++;
}
}ChrCount--;
price = stod(companyname);
}
else if (commacount > column) // if the comma count is any value larger than the column, breaks out of loop.
{
break;
}
if (input == 0)
{
break;
}
if (x == 1){
if (price >= input && price != 0) // if the appended company name is equal to the search input entered, it will cout the entire row.
BaseSearch::Print(line, title);
}
if (x == 2)
{
if (price <= input && price != 0) // if the appended company name is equal to the search input entered, it will cout the entire row.
BaseSearch::Print(line, title);
}//end if
}
}
}
ValueSearch.h
#ifndef VALUESEARCH_H
#define VALUESEARCH_H
#include <string>
#include "BaseSearch.h"
class ValueSearch : public BaseSearch
{
public:
ValueSearch();
~ValueSearch();
double getInput();
void ValueSearchFunc(int c, int x);
void Print(string,string) {BaseSearch::Print(string,string);}
protected:
private:
double input;
int column;
};
#endif

It seems you are a beginner of C++.I will show you an example code which will compile successfully.
BaseSearc.h:
#ifndef BASESEARCH_H
#define BASESEARCH_H
#include <string>
using namespace std;
class BaseSearch
{
public:
BaseSearch();
~BaseSearch();
void Print(string, string);
};
#endif
BaseSearch.cpp:
#include "BaseSearch.h"
#include <iostream>
BaseSearch::BaseSearch()
{
}
BaseSearch::~BaseSearch()
{
}
void BaseSearch::Print(string line, string title)
{
cout << "line:" << line << endl;
cout << "title:" << title << endl;
}
ValueSearch.h:
#ifndef VALUESEARCH_H
#define VALUESEARCH_H
#include <string>
#include "BaseSearch.h"
class ValueSearch : public BaseSearch
{
public:
ValueSearch();
~ValueSearch();
double getInput();
void ValueSearchFunc(int c, int x);
protected:
private:
double input;
int column;
};
#endif
ValueSearch.cpp:
#include "ValueSearch.h"
ValueSearch::ValueSearch()
{
}
ValueSearch::~ValueSearch()
{
}
double ValueSearch::getInput()
{
return input;
}
void ValueSearch::ValueSearchFunc(int c, int x)
{
//where is 'input' from?
//if (x == 1)
//{
// if (price >= input && price != 0)
// BaseSearch::Print(line, title);
//}
//if (x == 2)
//{
// if (price <= input && price != 0)
// BaseSearch::Print(line, title);
//}//end if
}
But I've no idea what ValueSearchFunc wants to do.

There is no realization of BaseSearch constructor/destructor in code. And Print function realization should be
void BaseSearch::Print(string line, string title)
{
//code
}

Related

Why do I get a segmentation fault when fetching this variable?

I am pulling names as strings from a file, create a Person *p object, and put it into an array.
Then to search the array for a name but when I try to fetch the name I get a segmentation fault.
Why is this segmentation fault happening, and what can I do to fix it?
#include <iostream>
#include <string>
using namespace std;
class Person {
private:
string firstName;
string lastName;
string phoneNumber;
public:
Person();
Person(string f, string l, string n);
~Person(void);
void setName()
{
}
string getFirstName()
{
return firstName;
}
string getLastName()
{
return lastName;
}
string getNumber() { return phoneNumber; }
void print();
};
Array creation.
{
ifstream file;
file.open("phonebook.txt");
if (!file.is_open()) //Check for File Error.
{
cerr << "Failed to open file" << endl;
exit(1);
}
//Get Array Size
string line;
while (getline(file, line))
{
count++;
}
file.close();
//Create an array
Person *arrList[count];
buildArray(arrList, count);
if (uInput == "a" || uInput == "A") //To add
{
int x = addPerson();
if (x == 1)
{
count++;
}
delete[] arrList;
}
void buildArray(Person *arr[], int size)
{
string f, l, n;
ifstream file;
file.open("phonebook.txt");
for (int i = 0; i < size; i++)
{
file >> f >> l >> n;
Person *p = new Person(f, l, n);
arr[i] = p;
delete p;
}
}
The search, This is the part that has the trouble. I have tried a few different things including creating 2 Persons, and comparing their parts but whenever it goes into the .h it can not return the name.
if (uInput == "s" || uInput == "S")
{ //To Search
string f, l;
cout << "Find Who (Firstname Lastname) " << endl;
cin >> f >> l;
Person *n = new Person(f, l, "");
int i = 0;
bool found = false;
while (i <= count && found == false)
{
Person *p = new Person("", "", "");
p = arrList[i];
if (p->getFirstName() == n->getFirstName() && p->getLastName() == n->getLastName())
{
arrList[i]->print();
found = true;
delete p;
delete n;
}
i++;
}
while (i == count && found == false)
{
cout << "No results found. " << endl;
found = true;
}
}

Invalid static_cast from struct to char*

I am trying to do a uni assignment (first year), where the task is to read in a file filled with records (in this case fake student records), insert them into a struct array in the code, write that struct array to a .dat file, and then read the file back in and verify it.
I keep getting an error about converting my struct to a char* (line 155)
Please don't be too technical with the answer, as I have only been coding for a few months ahah
/*
* File: lab3.cpp
* Author: tom
*
* Created on August 19, 2015, 12:02 AM
*/
#include<iostream>
#include<cstring>
#include<fstream>
using namespace std;
//Structure declaration area
struct marks // A structure for user data
{
int studentnumber;
float ass1;
float ass2;
float ass3;
float ass4;
int labs;
float exam;
float total;
};
//Function Prototyping
void structinsert(ifstream&);
void binarywrite(ofstream&);
int binaryread(ifstream& , marks);
//Global Array for student marks
marks students [100];
int main(int argc, char* argv[])
{
ifstream fin;
ofstream fout;
int recordsread = 0;
fin.open(argv[1]); //Input file opened from cmdline args
fout.open(argv[2]); // Output file opened from cmdline args
if (fin.fail())
{
cerr << "Input file not found. Terminating..." << endl;
}
else if (fout.fail())
{
cerr << "Output file not found. Terminating..." << endl;
}
else
{
structinsert(fin);//Function which places data into the global "student" array
binarywrite(fout);
fin.close();
fout.close();
fin.open(argv[2]);
int cnt = 0;
while((!fin.eof()) && (cnt < 100))
{
fin.read(static_cast<char *>(&students[cnt]), sizeof(marks));
cnt++;
}
cout << "Records Read: " << recordsread << endl;
}
return 0;
}
void structinsert(ifstream& input)
{
float temp;
float value;
// Ignore first line of headings
input.ignore(150, '\n');
for (int x = 0; x < 100; x++)
{
input >> students[x].studentnumber;
input.ignore (1);
temp = input.peek();
if (temp == '\t')
{
input.ignore(1,'\t');
students[x].ass1 = 0;
}
else
{
input >> students[x].ass1;
input.ignore(1,'\t');
}
temp = input.peek();
if (temp == '\t')
{
input.ignore(1,'\t');
students[x].ass2 = 0;
}
else
{
input >> students[x].ass2;
input.ignore(1,'\t');
}
temp = input.peek();
if (temp == '\t')
{
input.ignore(1,'\t');
students[x].ass3 = 0;
}
else
{
input >> students[x].ass3;
input.ignore(1,'\t');
}
temp = input.peek();
if (temp == '\t')
{
input.ignore(1,'\t');
students[x].ass4= 0;
}
else
{
input >> students[x].ass4;
input.ignore(1,'\t');
}
input >> students[x].labs;
input.ignore(1,'\t');
temp = input.peek();
if (temp == '\n')
{
input.ignore(1,'\t');
students[x].exam = 0;
}
else
{
input >> students[x].exam;
input.ignore(1,'\t');
}
}
}
void binarywrite(ofstream& output)
{
output.write(reinterpret_cast<char*>(&students),100*sizeof(marks));
}

How to create an array of different size as a private class variable?

I'm trying to create a program that takes a polynomial function from the user, counts the number of terms it has, creates an array large enough to store all of the terms, and then stores the terms there. The problem is that I'm not quite sure how to add a private class variable (or more specifically, a string array) AFTER the program determines how the large the function is. I need this string array to be a private class variable because I want to be able to access its contents through other class methods to do things like, for example, cout each of the function terms.
main.cpp:
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
int main()
{
Function func1;
func1.coutFuncTerms();
func1.coutFunc();
return 0;
}
Function.h:
#ifndef FUNCTION_H
#define FUNCTION_H
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
class Function
{
public:
Function();
~Function();
void removePlus(string*);
void removeWhitespace(string*);
void setFuncTerms();
void splitTerms();
void coutFuncTerms();
void coutFunc();
void coutTerms(string);
protected:
private:
string func;
int funcTerms;
};
#endif
Function.cpp:
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
// Function Constructor
//
// Stores a function inputted by the user
// Adds a null character ('\0') to the end of a string
// Erases a redundant '+' sign at the beginning of a string if there's one there
// Erases any whitespace characters in a string
// Stores the number of terms in the function
Function::Function()
{
getline(cin, func);
setFuncTerms();
//splitTerms();
}
Function::~Function()
{
}
// removePlus Function
//
// Erases a redundant '+' sign at the beginning of a string if there's one there
void Function::removePlus(string* func)
{
if(func->at(0) == '+')
{
func->erase(0, 1);
}
}
// removeWhitespace Function
//
// Erases any whitespace characters in a string
void Function::removeWhitespace(string* func)
{
for(int x = 0; unsigned(x) < func->length() - 1; x++)
{
while(func->at(x) == ' ' || func->at(x) == '\t')
{
func->erase(x, 1);
}
}
}
// setFuncLength Function
//
// Finds the number of terms in a Function object's 'func' variable
// Assigns this number to the object's 'funcLength' variable
void Function::setFuncTerms()
{
funcTerms = 0;
for(int funcTerm = 0; unsigned(funcTerm) < func.length(); funcTerm += 1)
{
bool isAPotentialTerm = false;
bool isATrueTerm = false;
if(func.at(funcTerm) == '+' || func.at(funcTerm) == '-')
{
isAPotentialTerm = true;
}
if(isAPotentialTerm == true)
{
for(int newFuncTerm = funcTerm + 1; unsigned(newFuncTerm) < func.length(); newFuncTerm += 1)
{
if(func.at(newFuncTerm) == '+' || func.at(newFuncTerm) == '-')
{
break;
}
if(func.at(newFuncTerm) != ' ' && func.at(newFuncTerm) != '\t')
{
isATrueTerm = true;
break;
}
}
}
if(isATrueTerm)
{
funcTerms++;
}
}
}
// splitTerms Function
//
// Calls the splitTerm function for each term in 'func' according to the function array 'funcArray'
void Function::splitTerms()
{
string funcArray[funcTerms];
int tempFuncLength = 0;
for(int funcTerm = 0; unsigned(funcTerm) < func.length(); funcTerm += 1)
{
bool isAPotentialTerm = false;
bool isATrueTerm = false;
if(func.at(funcTerm) == '+' || func.at(funcTerm) == '-')
{
isAPotentialTerm = true;
}
if(isAPotentialTerm == true)
{
for(int newFuncTerm = funcTerm + 1; unsigned(newFuncTerm) < func.length(); newFuncTerm += 1)
{
if(func.at(newFuncTerm) == '+' || func.at(newFuncTerm) == '-')
{
break;
}
if(func.at(newFuncTerm) != ' ' && func.at(newFuncTerm) != '\t')
{
isATrueTerm = true;
break;
}
}
}
if(isATrueTerm)
{
string temp;
for(; unsigned(funcTerm) < func.length() && func.at(funcTerm) != '+' && func.at(funcTerm) != '-'; funcTerm += 1)
{
funcArray[tempFuncLength].append(1, func.at(funcTerm));
}
tempFuncLength++;
}
}
for(int x = 0; x < funcTerms; x++)
{
cout << "Term " << x + 1 << " is: " << funcArray[x] << endl;
}
}
void Function::coutFuncTerms()
{
cout << "Terms: " << funcTerms << endl;
}
void Function::coutFunc()
{
cout << "Function: " << func << endl;
}
void Function::coutTerms(string funcArrayTerm)
{
/*for(int x = 0; x < funcLength; x++)
{
cout << "Term " << x << " is: " << funcArray[x] << endl;
}*/
//cout << funcArray[0] << endl;
}
I highly recommend you change your design.
A function is a container of terms. So let's define a term:
A term minimally has a coefficient and an exponent:
struct Fundamental_Term
{
double coefficient;
int exponent;
};
If your function is only in terms of one variable, all you need is the Fundamental_Term. Otherwise, you need to have the base variable name:
struct Term_With_Base
: public Fundamental_Term
{
std::string variable_name;
};
Note: if you can't use inheritance, copy the member variables of Fundamental_Term into Term_With_Base.
Remember a function is a collection or container of terms. Assuming a function with multiple bases, we can declare:
struct Function
{
std::vector<Term_With_Base> terms;
};
Evaluation of Terms
To evaluate a function, f(x), all terms must be evaluated and their results summed.
This decomposes into two requirements: 1) Terms must have an evaluation method; 2) The function class must have an evaluation method that sums the terms.
So, we add an evaluation function to the base class:
struct Fundamental_Term
{
double coefficient;
int exponent;
double evaluate(double value)
{
return coefficient * pow(value, exponent);
}
};
struct Function
{
std::vector<Term_With_Base> terms;
double evauate(double value)
{
const unsigned int quantity = terms.size();
double result = 0.0;
for (unsigned int i = 0; i < quantity; ++i)
{
result = result + terms[i].evaluate(value);
}
return result;
}
};
When creating a function from a string, a preference is to create a constructor of Fundamental_Term that takes a string parameter. The term object should read its coefficient, variable name and exponent, not the Function container.
For more examples, search StackOverflow for "c++ parse term evaluation".
Edit 1: Inserting terms
One method to insert terms, is to have a method in the term data structure that loads a term from a string:
bool
Fundamental_Term ::
load_from string(const std::string& input,
unsigned int & start_position)
{
bool term_is_valid = false;
// Parse the string and load appropriate fields.
// Set the start position to the first position after the valid term.
// Set term_is_valid to true if the term has valid syntax.
return term_is_valid;
}
The Function object would have a member to load terms from a string.
bool
Function ::
load_terms_from_string(const std::string& input)
{
Term_With_Base term;
unsigned int position_in_string = 0;
bool term_is_valid = true;
while (term_is_valid && (position_in_string < input.size()))
{
term_is_valid = term.load_from_string(input, position_in_string);
if (term_is_valid)
{
terms.push_back(term);
}
}
}
The std::vector used to contain the terms will expand as necessary with each additional term that is parsed. The loop will terminate when the string is parsed or there is an invalid term.

Unable to access members of a class; SegFault

I have a program where I am setting up a closed hash table. In each Element of the Hash table, there is a Student class which holds varies members (name, id, year, etc.). I am simply trying to print out what has been added to my array, but I keep getting a SegFault, and I don't know why. It is only in my print function, though. I have copied the line of code to my other functions or put them in different classes, and they work there, but not when I try to print from my print function. I am at the end of my rope, trying to figure out why I can access the memory location of each member, but not it's actual value.
Here is my program:
main.cpp:
using namespace std;
#include <cstdlib>
#include "hash.h"
int main()
{
string temp1;
string temp2;
string temp3;
string temp4;
string temp5;
string temp6;
Hash h;
do{
cout << "set> ";
cin >> temp1;
//Checking for quit command.
if(temp1.compare("quit") == 0)
{
return 0;
}
//checking for add command.
else if(temp1.compare("add") == 0)
{
cin >> temp2;
cin >> temp3;
cin >> temp4;
cin >> temp5;
cin >> temp6;
Student *s1 = new Student(temp2, temp3, temp4, temp5, temp6);
Element e1(s1);
h.add(e1);
}
//checking for remove command.
else if(temp1.compare("remove") == 0)
{
int r;
cin >> r;
h.remove(r);
}
//checking for print command.
else if(temp1.compare("print") == 0)
{
h.print();
}
//Anything else must be an error.
else
{
cout << endl;
cout << "Error! "<< endl;
}
}while(temp1.compare("quit") != 0);
}
hash.h:
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
// Student Class
class Student{
private:
string firstName;
string lastName;
string id;
string year;
string major;
public:
//Constructor
Student(string a, string b, string c, string d, string e);
friend class Element;
friend class Hash;
};
//Element class
class Element{
private:
Student *data;
public:
int getKey();
Student* getData();
void printStudent();
//Constructor
Element(Student *e)
{
data = e;
};
friend class Hash;
};
class Hash{
private:
Element **array;
public:
void add(Element);
void print();
void remove(int);
//Constructor
Hash()
{
array = new Element *[10];
};
friend class Student;
};
hash.cpp:
#include "hash.h"
//The Constructor for Student
Student::Student(string a, string b, string c, string d, string e)
{
firstName = a;
lastName = b;
id = c;
year = d;
major = e;
}
//getKey function for Element Class
int Element::getKey()
{
int key = atoi(getData()->id.c_str());
return key;
}
Student* Element::getData()
{
return data;
}
void Element::printStudent()
{
string c = data->firstName;
cout<< "(" << c << ")";
}
//The add command
void Hash::add(Element e1)
{
int x = e1.getKey()%10;
int i = 0;
if(array[x] == NULL || array[x]->getData() == NULL)
{
array[x] = &e1;
}
else
{while(array[x] != NULL || array[x]->getData() != NULL)
{
x=(x+(i*i))%10;
if(array[x] == NULL || array[x]->getData() == NULL)
{
array[x] = &e1;
break;
}
else
{
i++;
}
}}
}
//The remove command
void Hash::remove(int n)
{
Element e2(NULL);
for(int j = 0; j<10; j++)
{
if(n == array[j]->getKey())
{
array[j] = &e2;
cout << "true" << endl;
break;
}
}
cout << "false" << endl;
}
//The Print command
void Hash::print()
{ int k = 0;
while(k<10)
{
if(array[k] == NULL)
{
cout << "(NULL)";
}
else if(array[k]->getData() == NULL)
{
cout << "(DEL)";
}
else
{
cout << "(" << array[k]->getData()->firstName << ")";
}
k++;
}
cout << endl;
}
Thank you for your help.
You have dangling pointers.
This function gets a temporary copy of an Element, calling it e1.
//The add command
void Hash::add(Element e1)
{
It then stores the address of this local variable.
array[x] = &e1;
And when Hash::add leaves scope, e1 no longer exists.
}
array[x] now points to memory that is no longer Element e1.
The general problem you are facing is that you have designed a Hash class that maintains pointers to objects, but has little control or knowledge regarding when those objects get destroyed.
You will need to personally ensure that objects added to your Hash last at least as long as the Hash does.
Simplest solution for your problem could be to store Element instances in Hash by value not by pointers. So:
class Hash{
private:
Element *array;
public:
void add(Element);
void print();
void remove(int);
//Constructor
Hash()
{
array = new Element[10];
};
friend class Student;
};
Now when you store new element or remove existing you copy them:
array[x] = e1; // not &e1 anymore
This is not very good practice, but at least could change your program in some workable state with minimal changes.

C++ Palindrome program

I find myself oddly perplexed on this homework assignment. The idea is to create a Palindrome program, using a specific header the professor wants us to use, but for some reason, when I run it, right after I enter the phrase the program crashes on me.
Here is the program
#include <iostream>
#include <ctime>
#include "STACK.h"
using namespace std;
int main(void)
{
// Declare variables
time_t a;
STACK<char, 80> s;
STACK<char, 80> LR;
STACK<char, 80> RL;
char c;
char c1;
char c2;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
// Prompts the user to enter the string
cout << "Enter a phrase: ";
while(cin.get(c) && (c != '\n'))
{
if(isalpha(c))
{
c = toupper(c);
LR.PushStack(c);
s.PushStack(c);
}
}
// Copies s into RL in reverse order
while(!(s.EmptyStack() ) )
{
c = s.PopStack();
RL.PushStack(c);
}
// Checks for Palindrome
while(!(LR.EmptyStack() ) )
{
c1 = LR.PopStack();
c2 = RL.PopStack();
if( c1 != c2)
{
break;
}
}
// Displays the result
if(LR.EmptyStack() )
{
cout << "Palindrome";
}
else
{
cout << "Not a Palindrome";
}
return 0;
}
And here is the header (I am not allowed to change this)
#ifndef STACK_H
#define STACK_H
template <class T, int n>
class STACK
{ private: T a[n];
int counter;
public:
void MakeStack() { counter = 0; }
bool FullStack()
{ return (counter == n) ? true : false ; }
bool EmptyStack()
{ return (counter == 0) ? true : false ; }
void PushStack(T x)
{ a[counter] = x; counter++; }
T PopStack()
{ counter--; return a[counter]; }
};
#endif
You are not calling MakeStack, which will set STACK initial size (0).