Having a divide by zero in my code - c++

Hes my code and I can't figure out where I'm getting the divide by zero problem.
mreviewApp.cpp
const int SIZE = 80;
const char DELIMIT = '|';
void parseLine(const char line[], string& title, int& rating);
void stringTrim(char st[]);
void printMrList(std::vector <Mreview> mrList);
Mreview searchTitle(std::vector <Mreview> &mrList, string title);
int main()
{
ifstream fin;
fin.open("rating_list.txt");
if (fin.fail()) {
cerr << "Input file opening error.\n";
exit(1);
}
char line[SIZE];
string title;
int rating;
int lineCount = 0;
std::vector <Mreview> mrList;
/* Process one line at a time */
// Read the first line
fin.getline(line, SIZE);
stringTrim(line);
// Process loop
while (strlen(line) != 0) {
parseLine(line, title, rating);
lineCount++;
Mreview review = searchTitle(mrList, title);
review.addScore(rating);
// Read the next line
fin.getline(line, SIZE);
stringTrim(line);
}
cout << "** PROCESS DONE. There were " << mrList.size() << " movie titles. **\n\n";
printMrList(mrList);
// Close the input file before exit.
fin.close();
system("Pause");
return 0;
}
void parseLine(const char line[], string& title, int& rating)
{
char s[SIZE], r[SIZE];
const char *ptr, *temp1;
char *temp2;
ptr = strchr(line, DELIMIT);
if (ptr != NULL) {
// First grab the title string (until '|').
temp1 = line;
temp2 = s;
while (temp1 != ptr)
*temp2++ = *temp1++;
*temp2 = '\0';
stringTrim(s);
title = s;
// Second grab the rating number
temp1 = ptr+1;
temp2 = r;
while (*temp1 != '\0')
*temp2++ = *temp1++;
*temp2 = '\0';
stringTrim(r);
rating = atoi(r);
}
else {
title = "";
rating = 0;
}
}
void stringTrim(char st[])
{
char* ptr;
for (ptr = st; *ptr; ptr++) ;
for (ptr--; *ptr == ' ' && ptr >= st; ptr--) ;
ptr++;
*ptr = '\0';
for (ptr = st; *ptr && *ptr == ' '; ptr++) ;
if (*ptr && ptr != st) {
char* ptr2;
for (ptr2 = st; *ptr; *ptr2++ = *ptr++) ;
*ptr2 = '\0';
}
}
void printMrList(std::vector <Mreview> mrList)
{
std::vector<Mreview>::iterator itr;
for(itr = mrList.begin(); itr != mrList.end(); itr++) {
Mreview review = *(itr);
cout << review.getTitle() << "\t\t" << review.getTotalScore() << "\t\t" << review.aveRating() << endl;
}
}
Mreview searchTitle(std::vector <Mreview> &mrList, string title)
{
Mreview review (title);
std::vector<Mreview>::iterator itr;
for(itr = mrList.begin(); itr != mrList.end(); itr++) {
Mreview r2d2 = *(itr);
if(review.getTitle() == r2d2.getTitle())
return r2d2;
}
mrList.push_back(review);
return review;
}
mreview.cpp
Mreview::Mreview(string ttl)
: title(ttl), totalScore(0), numRatings(0) {}
Mreview::Mreview(string ttl, int score)
: title(ttl), totalScore(score), numRatings(1) {}
void Mreview::addScore(int score)
{
this->totalScore += score;
this->numRatings += 1;
}
double Mreview::aveRating() const
{
double rating = totalScore/numRatings;
return rating;
}
mreview.h
#ifndef MREVIEW_H
#define MREVIEW_H
#include <string>
using namespace std;
class Mreview
{
public:
Mreview(string ttl = "N/A");
Mreview(string ttl, int firstScore);
string getTitle() const { return title; }
int getTotalScore() const { return totalScore; }
int getNumRatings() const { return numRatings; }
void addScore(int score);
double aveRating() const;
private:
string title;
int totalScore;
int numRatings;
};
#endif
My problem is that I am unable to figure out what I have to do to fix the problem. I have read the comments and I am still confused.

You're allocating (and copying!) a vector of Mreview objects, all of which are being constructed with the default ctor, so numRatings defaults to 0, and you are doing nothing to ensure that aveRating() is never called on unmodified objects or at the very least protects itself from numRatings being 0.
Edit: Easiest fix:
double Mreview::aveRating() const {
if (numRatings == 0)
return 0.;
else
return static_cast<double>(totalScore)/numRatings;
}
A further fix, IMO, would be to store Mreview pointers (ideally shared_ptr) in the vector and newing them when the first score is to be added rather than earlier.

Not the divide by zero error, but...
double Mreview::aveRating() const
{
double rating = totalScore/numRatings;
return rating;
}
You are taking two integer values and storing it in a double without typecasting... you have to cast either totalScore or numRatings to a double like:
double Mreview::aveRating() const
{
double rating = (double)totalScore/numRatings;
return rating;
}

When looking for divide by zero problems, look for / and % operators. I see only one / in your code.

I only see one actual division operation...
double Mreview::aveRating() const {
double rating = totalScore/numRatings;
return rating;
}
...so is it there?

Can you run it in a debugger and let it tell you where the trap occurred?

It looks like if the length of the line is 0 after trimming, then printMrList() can be called without review.addScore() being called first. In that case, printMrList() calls review.aveRating() which tries to divide totalScore by numRatings. Both of these values are 0, so a divide by zero error occurs.

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;
}
}

Copying Array - Crashes After Doubling Array

I'm having some trouble with this program, I'm aware I can use a vector but I'm trying to do it only using arrays. Once the program gets to the initial array size of 1000, it should double the array (in this case to 2000) after copying the data. So for example if I had a list of 3000 names, it'd double once at 1000, then again at 2000 - making the total list 4000. I'm not entirely sure why it crashes after I double the array size. Can someone help me with this?
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
struct Information {
char functionality;
string SSN;
string name;
};
Information* person;
int numPeople = 1000;
int numRetrieved = 0;
int numArray = 0;
int numInserted = 0;
int numDeleted = 0;
void doubleArray(Information *person){
numPeople = numPeople * 2;
Information* temp = new Information[numPeople];
memcpy(temp, person, numPeople/2);
delete[] person;
person = temp;
cout << "Person 1: " << person[0].name << " " << person[0].SSN << endl;
}
//Currently not using this until I figure out the double...
void halfArray(Information *person){
numPeople = numPeople / 2;
}
void deleteInfo(Information *person, string SSN){
for(int i = 0; i < numArray; i++){
if(person[i].SSN == SSN){
for(int k = i; k < numArray-1; k++){
person[k].SSN = person[k+1].SSN;
person[k].name = person[k+1].name;
}
numArray--;
numDeleted++;
if((numArray+1) < (numPeople / 4)){
//halfArray(person);
}
}
}
}
void retrieve(Information *person, string findSSN, int lastPerson){
for(int i = 0; i < lastPerson; i++){
if(person[i].SSN == findSSN){
numRetrieved++;
}
}
}
void insert(Information *person, string SSN, string name){
if(numArray == (numPeople - 1)){
doubleArray(person);
}
bool dontInsert = false;
for(int i = 0; i <= numArray; i++){
if(person[i].SSN == SSN){
dontInsert = true;
}
}
if(dontInsert){
dontInsert = false;
}else{
person[numArray].SSN = SSN;
person[numArray].name = name;
numArray++;
numInserted++;
}
}
int main(int argc, char* argv[]) {
person = new Information[numPeople];
char firstLetter;
string SSN, firstName, lastName, name;
fstream input(argv[1]);
for(int i = 0; !input.eof(); i++){
input >> firstLetter >> SSN >> firstName >> lastName;
name = firstName + " " + lastName;
switch(firstLetter){
case 'd':{
deleteInfo(person, SSN);
break;
}
case 'i':{
insert(person, SSN, name);
break;
}
case 'r':{
retrieve(person, SSN, numArray);
break;
}
}
}
input.close();
}
You delete the memory that the Information* points at, but you have a copy of that pointer, and assigning it to your temp variable has no effect outside of doubleArray.
Let's say that the value of person passed in is 0xC001C001;
void doubleArray(Information *person){
numPeople = numPeople * 2;
Information* temp = new Information[numPeople];
memcpy(temp, person, numPeople/2);
delete[] person;
person = temp;
cout << "Person 1: " << person[0].name << " " << person[0].SSN << endl;
}
You create a new pointer temp which has a value of 0xBAD1BAD1. You delete person (0xC001C001), then assign 0xBAD1BAD1 to person. Execution then continues in the insert function ...
void insert(Information *person, string SSN, string name){
if(numArray == (numPeople - 1)){
doubleArray(person);
}
bool dontInsert = false;
for(int i = 0; i <= numArray; i++){
if(person[i].SSN == SSN){
dontInsert = true;
}
}
The person variable here still has the value 0xC001C001, which has been deallocated. Your program blows up when you deference person with person[i].SSN.
When you want to change a pointer, the classic pattern is to pass a pointer pointer. (Two star programming)
void redo(P** p)
{
P* temp = new P();
delete *p;
*p = temp;
}

Palindrome finder: non-alphanumeric character deletion problems

So I'm having a substantial amount of trouble with this one bit of code. I've included the whole program for context, but my issue lies in the cleanUp function, wherein I (attempt to) remove all characters that are not 'A' through 'Z'.
Any tips?
#include <iostream>
#include <cstdlib>
#include <string>
#include <stdio.h>
#include <ctype.h>
using namespace std;
bool again(string title); // Checks if you want to run again.
void makeUpper(char word[]);
void getReverse(char word[], char reversed[]);
char * find(char *str, char what);
bool equal(char word[], char reversed[]);
int size(char word[]);
char * cleanUp(char *str);
int main()
{
char word[256] = "Hello?? There!", reversedWord[256];
do
{
cout<<"Please enter the string to check: ";
makeUpper(word);
cout << word;
cleanUp(word);
getReverse(word,reversedWord);
if(equal(word, reversedWord))
cout<<"You have a palindrome!"<<endl;
else
cout<<"You do not have a palindrome!"<<endl;
} while(again("Do you want to do this again? "));
return 0;
}
bool again(string title)
{
string answer;
cout<<endl<<title;
getline(cin,answer);
return toupper(answer[0]) == 'Y';
}
void makeUpper(char word[])
{
char *ptr = word;
while (*ptr) {
*ptr = toupper(*ptr);
ptr++;
}
cout << "In uppercase:: " << word << endl;
}
char * cleanUp(char * astrid)
{
char *new_astrid;
for (*astrid; *astrid != '\0'; astrid++)
{
cout << "First loop";
if (isalpha(*astrid))
{
*new_astrid = *astrid;
new_astrid = ++new_astrid;
cout << "Here!";
}
}
cout << *new_astrid;
return *new_astrid;
}
void getReverse(char word[], char reversed[])
{
char *ptr_ind = find(word, '\0'), *ptr_ind_2 = reversed;
while(ptr_ind != word-1)
{
*ptr_ind_2 = *ptr_ind;
ptr_ind--;
ptr_ind_2++;
}
*ptr_ind_2 = '\0';
}
char * find(char *str, char what)
{
char *ptr = str;
while(*ptr != what && *ptr != '\0')
ptr++;
return *ptr == what ? ptr : NULL;
}
bool equal(char word[], char reverse[])
{
int total;
char * ptr;
ptr = word;
if((total = size(word)) != size(reverse))
return false;
for(char * ptr2 = reverse; *ptr != '\0' && *ptr == *ptr2; ptr++, ptr2++);
return *ptr == '\0';
}
int size(char word[])
{
int total = 0;
char * ptr = word;
while(*ptr != '\0') //while(!ptr)
{
ptr++;
total++;
}
return total;
}
There are several errors in your code.
new_astrid is not initialized and when you call *new_astrid = *astrid you try to copy a character to uninitialized memory, which will crash the program.
You also return the dereferenced pointer to new_astrid but the function prototype of cleanUp says that you return a pointer to char.
You should initialize new_astrid with new char[strlen(astrid)]. But then your code will result in memory leaks, since you increase the pointer (new_astid = ++new_astrid). So you should store the pointer first, so you can delete it later.
Instead of using raw pointers, i would suggest you use std::strings.
My suggestion for a palindrome tester would be:
#include <iostream>
#include <string>
#include <locale>
bool isPalindrome(std::string word)
{
std::locale loc;
for (std::string::size_type i = 0; i < word.length() / 2 + 1; ++i)
{
if (std::toupper(word[i],loc) != std::toupper(word[word.length() - i - 1],loc))
{
return false;
}
}
return true;
}
int main(int , char **)
{
std::string str = "Abba";
//Remove all non alpha values from string
str.erase(std::remove_if(str.begin(), str.end(), [](char const c){return !std::isalpha(c);}), str.end());
if (isPalindrome(str) == false)
{
std::cout << str << " is no palindrome" << std::endl;
}
else
{
std::cout << str << " is a palindrome" << std::endl;
}
return 0;
}
The erasion of non alpha values in the string is from this question.

Why is my data member empty even after construction?

I have included both my definition of the Question class and its implementation, the first is a header file and the second a cpp file.
I put comments in to show where the problem is. For some reason under the constructor I can cout the questionText just fine but when I try to do this under the getQuestionText function it just outputs an empty string? Any help would be most appreciated!! Thanks!
#include <string>
#include <vector>
#include <iostream>
using namespace std;
#ifndef QUESTION_H
#define QUESTION_H
class Question{
public:
Question(int thePointValue, int theChapterNumber, \
string theQuestionText);
int getPointValue() const;
int getChapterNumber() const;
string getQuestionText() const;
virtual void writeQuestion(ostream& outfile) const;
virtual void writeKey(ostream& outfile) const;
private:
int pointValue;
int chapterNumber;
string questionText;
void writePointValue(ostream& outfile) const;
};
#endif
#include "Question.h"
Question::Question(int thePointValue, int theChapterNumber, \
string theQuestionText)
{
pointValue = thePointValue;
chapterNumber = theChapterNumber;
questionText = theQuestionText;
//HERE THIS WORKS PERFECTLY
cout << questionText << endl;
}
int Question::getPointValue() const
{
return pointValue;
}
int Question::getChapterNumber() const
{
return chapterNumber;
}
string Question::getQuestionText() const
{
//THIS IS THE PROBLEM. HERE IT OUPUTS AN EMPTY STRING NO MATTER WHAT!
cout << questionText << endl;
return questionText;
}
void Question::writeQuestion(ostream& outfile) const
{
writePointValue(outfile);
outfile << questionText << endl;
}
void Question::writeKey(ostream& outfile) const
{
writePointValue(outfile);
outfile << endl;
}
void Question::writePointValue(ostream& outfile) const
{
string pt_noun;
if (pointValue == 1)
pt_noun = "point";
else
pt_noun = "points";
outfile << "(" << pointValue << " " << pt_noun << ") ";
}
vector<Question *> QuestionsList(string filename, int min, int max)
{
vector<Question *> QuestionList;
string line;
vector<string> text;
ifstream in_file;
in_file.open(filename.c_str());
while (getline(in_file, line))
{
text.push_back(line);
}
string type;
for(int i = 0; i < text.size(); i ++)
{
int num = text[i].find('#');
type = text[i].substr(0, num);
if (type == "multiple")
{
MultipleChoiceQuestion myq = matchup(text[i]);
MultipleChoiceQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "short")
{
ShortAnswerQuestion myq = SAmatchup(text[i]);
ShortAnswerQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "long")
{
LongAnswerQuestion myq = LAmatchup(text[i]);
LongAnswerQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "code")
{
CodeQuestion myq = CODEmatchup(text[i]);
CodeQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
cout << QuestionList[QuestionList.size()-1]->getQuestionText() << endl;
}
for (int i = 0; i < QuestionList.size(); i ++)
{
int numm = QuestionList.size();
cout << QuestionList[numm-1]->getQuestionText() << endl;
}
return QuestionList;
}
then when i call this in main the code breaks
vector<Question *> list = QuestionsList(pool_filename, min_chapter, max_chapter);
cout << list[0]->getQuestionText() << endl;
You are declaring, multiple times in your code, local objects and storing their pointer into the QuestionList vector (returned by the function) which, at the end of the function block, will contains dangling pointers.
MultipleChoiceQuestion myq = matchup(text[i]); // < local object
MultipleChoiceQuestion* myptr = &myq; // < pointer to local object
QuestionList.push_back(myptr); // < push back into vector
At this point you can either use dynamic memory allocation (I suggest you not to do that unless you are absolutely forced, and even in that case use one of the smart pointers provided by the standard library) or store the objects directly inside the vector.

Corruption Of Heap

In my program i got "corruption of heap" error
"Windows has triggered a breakpoint in Project_Name.exe.
This may be due to a corruption of the heap, which indicates a bug in JPS.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while Project_Name.exe has focus.
The output window may have more diagnostic information."
Here are the codes:
Header.h
#pragma once
#include <math.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <string>
#include <stdio.h>
#include <stack>
#include <vector>
#include <ctime>
#include <cassert>
#include <cmath>
using namespace std;
class ClientInfo
{
public:
int dayM;
string monthM;
int dayL;
string monthL;
string fName, lName;
double itmAmt;
ClientInfo* next;
};
class Record
{
private:
int numOfClients;
public:
int returnNumOfClients();
ClientInfo* head;
Record();
Record* InitializeRecord();
char* CalculateMaturity();
string ViewClient();
Record* FindName(string nn, ClientInfo *xxx);
void SaveRecord(ClientInfo* h);
double ComputeBalance(double amount, string mnthL, int dyL, string mnthM, int dyM);
ClientInfo* AddClient(string fn,string ln,string xMonthL, int xDayL, string
xMonthM, int xDayM ,double xItemAmt);
ClientInfo* SearchClient(string n);
void RemoveItem(ClientInfo* h, ClientInfo* rc, string remfname);
bool CheckExistence(ClientInfo* hx, string fnx, string lnx);
template <typename T>
string numToStr ( T num )
{
stringstream ss;
ss << num;
return ss.str();
}
};
Record::Record():numOfClients(0),head(NULL)
{
}
Record* Record::FindName(string nn, ClientInfo * xxx)
{
ClientInfo* newci = new ClientInfo();
Record* newrec = new Record();
ClientInfo* node= xxx;
do{
if(node->lName==nn)
{
newrec->head=newrec->AddClient(node->fName,
node->lName,
node->monthL,
node->dayL,
node->monthM,
node->dayM,node->itmAmt);
}
node=node->next;
}while(node!=NULL);
return newrec;
}
int Record::returnNumOfClients()
{
return numOfClients;
}
void Record::SaveRecord(ClientInfo* h)
{
Record *rec = new Record();
ClientInfo* saveRec = h;
string str;
vector<string> v;
ofstream outF;
outF.open("Record.txt");
if(saveRec!=NULL)
{
do
{
str = saveRec->fName+'-'+saveRec->lName+'-'+
rec->numToStr(saveRec->monthL)+'-'+
rec->numToStr(saveRec->dayL)+'-'+
rec->numToStr(saveRec->monthM)+'-'+
rec->numToStr(saveRec->dayM)+'-'+
rec->numToStr(saveRec->itmAmt);
saveRec = saveRec->next;
v.push_back(str);
}
while(saveRec != NULL);
for(vector<string>::iterator it = v.begin(); it != v.end(); ++it)
{
if( it != v.begin())
outF<<'\n';
outF<< *it;
}
}
else
numOfClients=0;
outF.close();
}
char* Record::CalculateMaturity()
{
try
{
ClientInfo* saveRec = new ClientInfo();
Record* rec = new Record();
string str;
stack<string> month;
month.push("December");
month.push("November");
month.push("October");
month.push("September");
month.push("August");
month.push("July");
month.push("June");
month.push("May");
month.push("April");
month.push("March");
month.push("February");
month.push("January");
month.push("December");
month.push("November");
month.push("October");
month.push("September");
month.push("August");
month.push("July");
month.push("June");
month.push("May");
month.push("April");
month.push("March");
month.push("February");
month.push("January");
stack<string> mnth;
mnth.push("December");
mnth.push("November");
mnth.push("October");
mnth.push("September");
mnth.push("August");
mnth.push("July");
mnth.push("June");
mnth.push("May");
mnth.push("April");
mnth.push("March");
mnth.push("February");
mnth.push("January");
mnth.push("December");
mnth.push("November");
mnth.push("October");
mnth.push("September");
mnth.push("August");
mnth.push("July");
mnth.push("June");
mnth.push("May");
mnth.push("April");
mnth.push("March");
mnth.push("February");
mnth.push("January");
const char *delimeter="-";
char* date=new char;
time_t now = time(0);
struct tm tstruct;
char buf[80];
tstruct = *localtime(&now);
strftime(buf, sizeof(buf), "%m-%d", &tstruct);
date = buf;
char* token= new char;
vector<string> dt;
token=strtok(date,delimeter);
while(token!=NULL)
{
dt.push_back(token);
token=strtok(NULL,delimeter);
}
string monthL,monthM;
int dayL;
int monthnum;
istringstream(dt[0])>>monthnum;
for(int x=1;x!=monthnum;x++)
mnth.pop();
monthL=mnth.top();
istringstream (dt[1])>>dayL;
do{month.pop();}while(monthL!=month.top());
month.pop();
month.pop();
month.pop();
monthM=month.top();
str=monthL+'-'+
rec->numToStr(dayL)+'-'+
monthM+'-'+
rec->numToStr(dayL);
int strsize = str.size();
char* chr = new char;
for(int x=0;x<strsize;x++)
{
chr[x]=str[x];
}
return chr;
}
catch(char* ex){system("pause");}
}
ClientInfo* Record::AddClient(string fn, string ln,string xMonthL, int xDayL, string
xMonthM, int xDayM, double xItemAmt)
{
ClientInfo* newInfo = new ClientInfo();
Record* newRecord = new Record();
newInfo->fName = fn;
newInfo->lName = ln;
newInfo->dayM = xDayM;
newInfo->monthM = xMonthM;
newInfo->dayL = xDayL;
newInfo->monthL = xMonthL;
newInfo->itmAmt = xItemAmt;
if(newInfo->next!=NULL)
{
newInfo->next = head;
numOfClients++;
head = newInfo;
}
else
{
newInfo->next=NULL;
}
return head;
}
Record* Record::InitializeRecord()
{
Record* initRec = new Record();
ClientInfo* initClient = new ClientInfo();
ifstream inF;
inF.open("Record.txt");
char* rec;
char* token;
vector<string> v;
int dayL, dayM;
string monthL, monthM;
double itmAmt;
if(inF.good())
{
do
{
rec = new char;
token = new char;
inF>>rec;
token = strtok(rec,"-");
while(token!=NULL)
{
v.push_back(token);
token = strtok(NULL,"-");
}
istringstream(v[2])>>monthL;
istringstream(v[3])>>dayL;
istringstream(v[4])>>monthM;
istringstream(v[5])>>dayM;
istringstream(v[6])>>itmAmt;
initRec->AddClient(v[0],v[1],monthL,dayL,monthM,dayM,itmAmt);
v.erase(v.begin(),v.end());
}while(!inF.eof());
}
inF.close();
return initRec;
}
void Record::RemoveItem(ClientInfo* h, ClientInfo* rc, string remfname)
{
ClientInfo* head = h;
ClientInfo* temp = rc->next;
if(temp!=NULL)
{
rc->fName = rc->next->fName;
rc->lName = rc->next->lName;
rc->monthL = rc->next->monthL;
rc->dayL = rc->next->dayL;
rc->monthM = rc->next->monthM;
rc->dayM = rc->next->dayM;
rc->itmAmt = rc->next->itmAmt;
rc->next = temp->next;
numOfClients--;
free(temp);
}
else
{
head = NULL;
free(temp);
}
SaveRecord(head);
}
ClientInfo* Record::SearchClient(string n)
{
ClientInfo* current = head;
for(int x=numOfClients-1;current!=NULL;x--)
{
if(current->lName == n)
return current;
else
current = current->next;
}
return current;
}
string Record::ViewClient()
{
string s;
ClientInfo* itr;
itr = head;
if(numOfClients!=0)
{
for(int i = 0; i<returnNumOfClients();i++)
{
string empty = "";
int y = i+1;
s+="\n\n***************\nName: "+itr->fName+" "+itr->lName+"\n-----
----------\n"+
"Loan Origination Date: "+numToStr(itr->monthL)+"
"+numToStr(itr->dayL)+
"\n---------------\n"+"Date Of Maturity: "+numToStr(itr-
>monthM)+" "+numToStr(itr->dayM)+"\n---------------\n"+
"Balance: "+numToStr(itr->itmAmt);
itr = itr->next;
}
s.append("\n***************\n\n");
}
else
s ="There is no recorded client yet.\n\n";
return s;
}
double Record::ComputeBalance(double amount, string mnthL, int dyL, string mnthM, int
dyM)
{
try
{
double INTEREST = 0.04;
double PENALTY = 0.02;
stack<string> monthl;
monthl.push("December");
monthl.push("November");
monthl.push("October");
monthl.push("September");
monthl.push("August");
monthl.push("July");
monthl.push("June");
monthl.push("May");
monthl.push("April");
monthl.push("March");
monthl.push("February");
monthl.push("January");
monthl.push("December");
monthl.push("November");
monthl.push("October");
monthl.push("September");
monthl.push("August");
monthl.push("July");
monthl.push("June");
monthl.push("May");
monthl.push("April");
monthl.push("March");
monthl.push("February");
monthl.push("January");
stack<string> monthm;
monthm.push("December");
monthm.push("November");
monthm.push("October");
monthm.push("September");
monthm.push("August");
monthm.push("July");
monthm.push("June");
monthm.push("May");
monthm.push("April");
monthm.push("March");
monthm.push("February");
monthm.push("January");
monthm.push("December");
monthm.push("November");
monthm.push("October");
monthm.push("September");
monthm.push("August");
monthm.push("July");
monthm.push("June");
monthm.push("May");
monthm.push("April");
monthm.push("March");
monthm.push("February");
monthm.push("January");
int ml=0;
int mm=0;
do{
monthl.pop();
mm++;
}while(mnthL!=monthl.top());
do
{
monthm.pop();
ml++;
}while(mnthM!=monthm.top());
int diff=abs(mm-ml);
double balance=diff*(amount*(INTEREST+
(INTEREST/(pow(INTEREST+1,diff)-1))));
return balance;
}
catch(double ex){system("pause");}
}
bool Record::CheckExistence(ClientInfo* hx, string fnx, string lnx)
{
ClientInfo *hh;
hh = head;
int t=0;
for(int x=numOfClients; hh!=NULL && x!=0; x--)
{
if(hh->fName == fnx && hh->lName==lnx)
t++;
else
hh=hh->next;
}
if(t!=0)
return true;
else
return false;
}
Main.cpp
#include "Header.h"
int main()
{
Record* rec = new Record();
ClientInfo* info;
Record* samelastrec = new Record();
double amt;
double balance;
int number;
int choose;
char ch;
double principal;
string iLName,iFName;
string nn;
int iDayL,iDayM;
string iMonthL,iMonthM;
string delfname;
rec=rec->InitializeRecord();
again:
system("cls");
cout<<"WELCOME TO JEWELRY PAWNING SYSTEM."<<endl;
cout<<"\n(1)Add Client\n(2)Remove Client\n(3)Search Client\n\n->";
cin>>choose;
Record *find = new Record();
ClientInfo* found;
system("cls");
int search;
char* datelm;
char* token;
vector<string> date;
string nnx;
switch(choose)
{
case 1:
system("cls");
if(rec->returnNumOfClients()!=0 || rec->returnNumOfClients()!=NULL)
{
cout<<"First Name: ";
cin>>iFName;
cout<<"Last name: ";
cin>>iLName;
if(!rec->CheckExistence(rec->head,iFName,iLName))
{
cout<<"Amount: ";
cin>>amt;
datelm=rec->CalculateMaturity();
token=strtok(datelm, "-");
while(token!=NULL)
{
date.push_back(token);
token=strtok(NULL, "-");
}
istringstream(date[0])>>iMonthL;
istringstream(date[1])>>iDayL;
istringstream(date[2])>>iMonthM;
istringstream(date[3])>>iDayM;
balance=rec->ComputeBalance(amt,iMonthL,iDayL,iMonthM,iDayM);
istringstream(rec->numToStr(balance));
rec->head=rec>AddClient(iFName,iLName,iMonthL,iDayL,iMonthM,iDayM,balance);
system("pause");
}
else
{
cout<<"Member already exist!"<<endl;
system("pause");
}
}
else
{
cout<<"First Name: ";
cin>>iFName;
cout<<"Last name: ";
cin>>iLName;
cout<<"Amount: ";
cin>>amt;
datelm=rec->CalculateMaturity();
token=strtok(datelm, "-");
while(token!=NULL)
{
date.push_back(token);
token=strtok(NULL, "-");
}
istringstream(date[0])>>iMonthL;
istringstream(date[1])>>iDayL;
istringstream(date[2])>>iMonthM;
istringstream(date[3])>>iDayM;
balance=rec->ComputeBalance(amt,iMonthL,iDayL,iMonthM,iDayM);
istringstream(rec->numToStr(balance));
rec->head=rec>AddClient(iFName,iLName,iMonthL,iDayL,iMonthM,iDayM,balance);
system("pause");
}
rec->SaveRecord(rec->head);
goto again;
break;
case 2:
system("cls");
find->head = rec->head;
cout<<"Enter Last Name: ";
cin>>iLName;
samelastrec=new Record();
samelastrec=samelastrec->FindName(iLName, rec->head);
if(find->SearchClient(iLName) == NULL)
{
cout<<"Client not found.\n";
system("pause");
}
else
{
found = find->SearchClient(iLName);
if(samelastrec->returnNumOfClients()>1)
{
cout<<samelastrec->ViewClient()<<endl<<endl;
cout<<"There are "<<samelastrec->numToStr(samelastrec->returnNumOfClients())
<<" Clients with "<<samelastrec->head->lName<<" last name";
cout<<endl<<"Enter the first name of the client you want to
remove: ";
cin>>delfname;
system("cls");
if(samelastrec->CheckExistence(samelastrec->head,delfname,
iLName))
{
cout<<endl<<"Do you want to remove "<<delfname<<"
<<samelastrec->head->lName<<" ?(Y/N)";
cin>>ch;
if(ch=='Y' || ch=='y')
{
rec->RemoveItem(rec->head,found,delfname);
cout<<"Client Removed."<<endl;
system("cls");
}
else if(ch=='N' || ch=='n')
goto again;
}
else
{
cout<<"The member with "<<delfname<<" does not
exist."<<endl;
system("pause");
goto again;
}
system("pause");
}
else
{
cout<<endl<<samelastrec->ViewClient()<<endl;
cout<<"Remove Client? [Y/N]: ";
cin>>ch;
if(ch=='Y' || ch=='y')
{
system("cls");
rec->RemoveItem(rec->head,found,found->fName);
cout<<"Client Removed."<<endl;
system("pause");
}
else if(ch=='N' || ch=='n')
goto again;
}
}
goto again;
break;
case 3:
system("cls");
cout<<"Enter Last Name : ";
cin>>nnx;
samelastrec=new Record();
samelastrec=samelastrec->FindName(nnx, rec->head);
cout<<samelastrec->ViewClient()<<endl;
system("pause");
break;
case 4:
system("cls");
cout<<rec->ViewClient();
system("pause");
goto again;
break;
case 5:
cout<<"Number of clients: "<<rec->numToStr(rec->returnNumOfClients())
<<endl;
system("pause");
break;
default:
if(choose!=0)
{
cout<<"\n\nInvalid Entry.\n\n";
system("pause");
goto again;
}
else
{
cout<<"\n\nTHANK YOU FOR USING THE JEWELRY PAWNING SYSTEM!\n\n";
system("pause");
exit(1);
}
}
goto again;
system("pause");
return 0;
}
I can't figure out why I'm getting these errors.
Please help me debug this error.
Thanks!
Throughout your code you have sections like this that trash memory you do not own:
int strsize = str.size();
char* chr = new char;
for(int x=0;x<strsize;x++)
{
chr[x]=str[x];
}
return chr;
It looks like you don't quite understand how pointers and new work. new char; allocates enough memory for just one character - typically one byte; so when x is larger than 0 in the subsequent loop you're overwriting memory you do not own, leading eventually to a crash. You have a number of sections of code like this. Either allocate the correct amount of memory for the operation (e.g. new char[strsize]), or (preferably) use C++ strings instead of character arrays.
(I also note you do not appear to ever free any of the memory you allocate, this will eventually cause problems as you perform more allocations during a run of the program. In general, every use of new should be matched by a corresponding use of delete).