Size of dynamic array does not match the value submitted - c++

I'm learning dynamic memory and something isn't quite going right. I have a function that accepts a number as input and is supposed to make an array of that size.
class Doctor {
public:
Doctor();
void fillOut();
void listPatients();
void patientReset();
~Doctor();
private:
string name;
int numPatients;
string *patientList;
};
Doctor::Doctor() {
name = "";
numPatients = 0;
patientList = new string[numPatients];
}
(Most relevant code in the 3rd code block).
void Doctor::fillOut()
{
string buffer = "";
string buffer2 = "";
size_t found;
bool valid = false;
int numP = 0;
int tester = 0;
bool validNum = false;
while(!valid)
{
cout << "Enter doctor name: ";
getline(cin, buffer);
found = buffer.find_first_of("1234567890!##$%^&*()-=_+/<>?;':][");
if(string::npos == found)
{
name = buffer;
valid = true;
}
}
while (!validNum)
{
cout << "\nEnter number of patients: ";
buffer = "";
getline(cin, buffer);
buffer2 = buffer;
stringstream ss(buffer);
if(ss >> tester)
{
stringstream ss2(buffer2);
ss2 >> numP;
validNum = true;
}
else
{
cout << "Not a number. Please try again." << endl;
}
}
patientList = new string[numP];
cout << patientList->size() << endl;
for(int i = 0; i < (numP + 0); i++)
{
valid = false;
while(!valid)
{
cout << "\nEnter patient " << (i + 1) << ": ";
getline(cin,buffer);
found = buffer.find_first_of("1234567890!##$%^&*()-=_+,./<>?;':][");
if(string::npos == found)
{
*(patientList + i - 0) = buffer;
//patientList[i-1] = buffer;
valid = true;
}
else
{
valid = false;
}
}
}
}
I then try to display the contents of the list.
void Doctor::listPatients()
{
cout << "size: " << patientList->size() << endl;
cout << "\nDoctor: " << name << endl;
for(int i = 0; i < (patientList->size() - 1); i++)
{
cout << "Patient " << (i+1) << ": " << patientList[i] << endl;
}
cout << "end patients" << endl;
}
But for some reason the number I submit as the size isn't the size of the array. For example, in fillOut() I have the function output the size. It outputs the size as 0 every time. Then in listPatients(), I have something that prints the size again, to verify I'm doing it right. If I initially input 3, it has outputs 5 in this function.
I'm completely mystified.

The line patientList->size() is equivalent to patientList[0].size(), the length of the initial string in your patientList array. At the point where you have just allocated your array, the result is always zero; in other instances, it is the length of the first string.
A preferred way of making containers in C++ is std::vector or std::array. In your case using std::vector is more appropriate, because your code allocates the patientList dynamically.

Ok, I found your problem. You are declaring an array of strings. But a raw array is really just a pointer to the contents of the array. When you call ->size, it dereferences that pointer, which points to the first string in the array and tells you the size of that string.
If you want an array that actually knows its size, use std::array.

OK so you declare patientList as a string* but when you call size() on this you are actually calling it on the first item in the array you have created. The only reason your code compiled is because string has a size() function and as this is the type contained in your array you got away with it because patientList actually points to the item at the start of the array (a string). In general an array does not have a size() function.
One other problem you will have though is here in your loop
for(int i = 0; i < (patientList->size() - 1); i++) {
^
^
cout << "Patient " << (i+1) << ": " << patientList[i] << endl;
}
this will cause your loop to terminate one before the end of patientList. You should use
for(int i = 0; i < patientList->size(); i++) {
cout << "Patient " << (i+1) << ": " << patientList[i] << endl;
}
You would be better off using a std::vector here to put your strings in. Also be careful here
if(string::npos == found) {
*(patientList + i - 0) = buffer;
//patientList[i-1] = buffer;
valid = true;
}
else {
valid = false;
}
because you would only be assigning to your array on the occasions when your if statement is true - the indices in the array when it is false are left uninitialised. I would honestly start again from scratch and use a vector of strings.

Related

Get only similar data within a c++ vector

I'm trying to get all the data from a .txt file that have a similar last value, as in the image.
for example, I go through and create a vector where I save in a file only the lines that have the same last value "1565514F" then when I find a different final value "1678721F" I create another file and so on infinitely, the first file would have the name "1565514F.txt" and would save in the same, or in another vector, data like
1001;2021-03-01;False;0;0;1565514F
1001;2021-03-02;False;0;0;1565514F
1002;2021-03-03;False;0;0;1565514F
1002;2021-03-04;False;0;0;1565514F
1003;2021-03-05;False;0;0;1565514F
1003;2021-03-06;False;0;0;1565514F
1004;2021-03-07;False;0;0;1565514F
another file would be called "1678721F.txt" and would have data like this
1006;2021-03-03;False;0;0;1678721F
1006;2021-03-04;False;0;0;1678721F
1001;2021-03-05;False;0;0;1678721F
1001;2021-03-06;False;0;0;1678721F
1004;2021-03-07;False;0;0;1678721F
1004;2021-03-08;False;0;0;1678721F
1003;2021-03-09;False;0;0;1678721F
the code that I have done is the following
// read file
ifstream archivoPlanificacion;
archivoPlanificacion.open("entrada/Planificacion.txt");
string linea;
vector<string> planificacionVector;
while(getline(archivoPlanificacion, linea))
{
planificacionVector.push_back(linea);
}
archivoPlanificacion.close();
for (int i = 0; i < planificacionVector.size(); i++) {
vector<string> planificacionSplitted = splits(planificacionVector[i], ';');
string planificacionFecha = planificacionSplitted[1];
string planificacionRut = planificacionSplitted[5];
cout << "Planificacion Rut: " << planificacionRut << endl;
if (planificacionRut == planificacionSplitted[5]){
vector<string> soloRutMismoUser;
soloRutMismoUser.push_back(planificacionSplitted[5]);
//imprimir vector soloRutMismoUser
for (int i = 0; i < soloRutMismoUser.size(); i++) {
cout << "soloRutMismoUser: " << soloRutMismoUser[i] << endl;
}
} else {
cout << "nuevo rut" << endl;
string aux = planificacionRut;
//crear archivo de salida
}
cout << "Planificacion Fechas: " << planificacionFecha << endl;
}
I don't know if there is a better way, but I asked because I was nesting many for, I would appreciate any help, I still can't separate the data with the "if", thanks
Modifying your loop
string currentCol5; // current 'rut'
vector<string> sameCol5; // collection of same 'rut' col5
for (int i = 0; i < planificacionVector.size(); i++) {
vector<string> planificacionSplitted = splits(planificacionVector[i], ';');
string planificacionFecha = planificacionSplitted[1];
string planificacionRut = planificacionSplitted[5];
cout << "Planificacion Rut: " << planificacionRut << endl;
if (currentCol5 == planificacionSplitted[5] || currentCol5.length() == 0){
sameCol5.push_back(planificacionSplitted[5]);
} else {
// write file here
for (int i = 0; i < sameCol5.size(); i++) {
cout << "soloRutMismoUser: " << sameCol5[i] << endl;
}
// start next set
currentCol5 = planificacionSplitted[5];
sameCol5.clear();
}
cout << "Planificacion Fechas: " << planificacionFecha << endl;
}
I have not tested any of this because I don't have the data structures or the file.

Why does it give me an error no "operator=="?

This line is an error and I don't know why. The compiler is telling me that the string array can't be converted to a string variable. The search is a string variable the user types in to look for names. And the names[count] is checking through an array of names.
string search;
string names[5]={};
for(int count=0; count<5; count++)
{
cout<<"Enter a name"<<endl;
cin>>names[count];
}
cout<<"Names entered"<<endl;
for(int count=0; count<5; count++)
{
cout<<names[count]<<endl;
cout<<"What name would you like to search for"<<endl;
cin>>search;
for(int count=0; count<5; count++)
{
if(names[count]=search)
{
cout<<search<<"is on array "<<count<<endl;
}
else
{
cout<<search<<"is not on the list"<<endl;
}
}
Is giving you this error because you are using the = assignment operator instead of the == comparison operator. Only use the former when assigning values to variables and the second for comparing variables in a condition.
I hope this helps:
https://www.geeksforgeeks.org/what-is-the-difference-between-assignment-and-equal-to-operators/
Have a good one and happy hacking!
Your question title mentions operator==, but there is no use of operator== anywhere in the code you have shown.
Your search logic is all wrong, though. First off, it is in the wrong place, it should not be inside the 2nd for loop at all, it needs to be moved up 1 level. And second, it is using the assignment operator= when it should be using the comparison operator== instead. And third, it is handling its output incorrectly.
Try something more like this instead:
string search;
string names[5];
for(int count = 0; count < 5; ++count)
{
cout << "Enter a name" << endl;
cin >> names[count];
}
cout << "Names entered" << endl;
for(int count = 0; count < 5; ++count)
{
cout << names[count] << endl;
}
cout << "What name would you like to search for" << endl;
cin >> search;
int found = -1;
for(int count = 0; count < 5; ++count)
{
if (names[count] == search)
{
found = count;
break;
}
}
if (found != -1)
{
cout << search << " is on array " << found << endl;
}
else
{
cout << search << " is not on the list" << endl;
}
/* alternatively:
#include <algorithm>
#include <iterator>
string *namesEnd = &names[5];
if (std::find(names, namesEnd, search) != namesEnd)
{
cout << search << " is on array " << std::distance(names, found) << endl;
}
else
{
cout << search << " is not on the list" << endl;
}
*/

Finding non-whitespace characters in C++

For my assignment, I have to call a function that takes the user input and spits out the number of non-whitespace characters. Inside the program, I have this code:
int GetNumOfNonWSCharacters(const string givenText) {
int counter;
for (int i = 0; i < givenText.length(); i++) {
if (givenText.at(i) != ' ') {
counter++;
}
}
return counter;
}
When I return the counter integer, this is how I output it with the string sampleText being the input:
if (menuInput == 'c' || menuInput == 'C') {
cout << "Number of whitespaces: " << GetNumOfNonWSCharacters(sampleText) << endl;
}
It returns an answer like 1231341235 or something along those lines. Now, when I type this code into a different file, pretty sure it's identical, I get the correct result every time:
int NumNonWhitespaces(const string userInput) {
int counter;
for (int i = 0; i < userInput.length(); i++) {
if (userInput.at(i) != ' ') {
counter++;
}
}
return counter;
}
int main() {
string userString;
cout << "Enter some text" << endl;
getline(cin, userString);
cout << "You entered: " << userString << endl;
cout << NumNonWhitespaces(userString);
return 0;
}
Does anyone have a solution to the problem ?
There is even more simple way to count the number of non white spaces by using the STL count algorithm:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string userString;
cout << "Enter some text" << endl;
getline(cin, userString);
cout << "You entered: " << userString << endl;
//count the number of white spaces
int numberOfWhiteSpace = count(userString.begin(), userString.end(), ' ');
//substruct that number from the total length of your string
cout << "number of non-whitespace: " << userString.length() - numberOfWhiteSpace;
return 0;
}
But in your solution you have to initialize the variable counter to 0
If you use counter without initializing it first, you'll get whatever junk memory existed at its memory address before your program started using it (C++ does not automatically zero-out the memory when you declare a variable). The fact it works when you copy it into a new file is purely coincidental.
The fix is simply to initialize counter to 0 before using it:
int counter = 0;
In some programming languages if a variable is allocated but not assigned, it is said to have a "garbage value" , that is, some information that was being held any random piece of the computer's memory. So initialize the counter variable to 0
You have to initialise the counter variable otherwise it will contain any old value.
int counter=0;

Segfault with String array C++

Had this program in C and was trying to convert some to C++ as I learn the language. Basically char arrays to strings and some of the input/output. Only issue is I get a segfault when attempting to put the input string into the string array (test2 prints. test3 does not).
Any ideas? Any bad coding habits I should be aware of as I learn c++?
int main() {
int nstr=0, nchar=0, nint=0, nfloat=0;
string input;
int i, z=0;
float inputFloat;
string *strList = (string*)malloc(sizeof(string) * nstr);
char *charList = (char*)malloc(sizeof(char) * nchar);
int *intList = (int*)malloc(sizeof(int) * nint);
float *floatList = (float*)malloc(sizeof(float) * nfloat);
while (z != -42) {
cout << "Input: ";
cin >> input;
cin.ignore();
inputFloat = strtof(input.c_str(), NULL);
if (inputFloat) {
if (fmod(inputFloat, 1.0)) {
nfloat++;
floatList = (float*)realloc(floatList, sizeof(float) * nfloat);
floatList[nfloat-1] = inputFloat;
}
else {
nint++;
intList = (int*)realloc(intList, sizeof(int) * nint);
intList[nint-1] = (int)inputFloat;
}
}
else {
if (input.length() == 1) {
nchar++;
charList = (char*)realloc(charList, sizeof(char) * nchar);
if (input.at(0) == 10)
input = " ";
charList[nchar-1] = input.at(0);
}
else {
nstr++;
cout << "test1" << endl;
strList = (string*)realloc(strList, sizeof(string) * nstr);
cout << "test2" << endl;
strList[nstr-1] = input;
cout << "test3" << endl;
}
}
cout << "Integers: ";
for (i=0; i<nint; i++)
cout << intList[i] << " ";
cout << endl << " Floats: ";
for (i=0; i<nfloat; i++)
cout << floatList[i] << " ";
cout << endl << " Chars: ";
for (i=0; i<nchar; i++)
cout << charList[i] << " ";
cout << endl << " Strings: ";
for (i=0; i<nstr; i++)
cout << strList[i] << " ";
cout << endl << endl;
}
}
As a rule you don't use malloc,calloc,realloc etc. in c++ at all, even though you can.
It less meaningful for simple items like: int, char etc. but when using on objects (like std::string) it cause this kind of problems:
When this line runs:
string *strList = (string*)malloc(sizeof(string) * nstr);
You allocate storage to array of strings, but you didn't called any constructor, therefor all the storage you've allocated is still useless.
In c++ you must use new like this:
string *strList = new string[nstr];
it is shorter, easier and call the constructor of each allocated object.
In the end you dealocate it with delete [] like this:
delete [] strList;
Even better is to use:
vector<string> strList;
and add elements by using:
strList.push_back("something"); or strList.push_back(some_string);
vectors are take care for the memory allocation and free, and are freed automatically as regular object at end of life, so it won't needed to be deleted at all.
realloc reassigns a larger array than the previous one. The new element at the end of the array, you fill it as a integer, float, char , which are basic C types. For C++ objects like strings, the last element in your array is not a new string, one of the possibilities is to create arrays of string pointers.
at the start of your code
string **strList = (string**)malloc(sizeof(string *) * nstr);
and by the end of your code, allocate a new string object at the end of the array.
nstr++;
strList = (string**)realloc(strList, sizeof(string *) * nstr);
strList[nstr-1] = new string(input);
at the end of the program you must delete everything you created through new operator and thru malloc/realloc.
while (nstr--)
{
delete strList[nstr];
}
free(strList);

C++ - pointer being freed was not allocated error

malloc: *** error for object 0x10ee008c0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
Or I get this when I try and print everything
Segmentation fault: 11
I'm doing some homework for an OOP class and I've been stuck for a good hour now. I'm getting this error once I've used keyboard input enough. I am not someone who gets frustrated at all, and here I am getting very frustrated with this. Here are the files:
This is the book class. I'm pretty sure this is very solid. But just for reference:
//--------------- BOOK.CPP ---------------
// The class definition for Book.
//
#include <iostream>
#include "book.h"
using namespace std;
Book::Book()
//
{
strcpy(title, " ");
strcpy(author, " ");
type = FICTION;
price = 0;
}
void Book::Set(const char* t, const char* a, Genre g, double p)
{
strcpy(title, t);
strcpy(author, a);
type = g;
price = p;
}
const char* Book::GetTitle() const
{
return title;
}
const char* Book::GetAuthor() const
{
return author;
}
double Book::GetPrice() const
{
return price;
}
Genre Book::GetGenre() const
{
return type;
}
void Book::Display() const
{
int i;
cout << GetTitle();
for (i = strlen(title) + 1; i < 32; i++)
cout << (' ');
cout << GetAuthor();
for (i = strlen(author) + 1; i < 22; i++)
cout << (' ');
switch (GetGenre())
{
case FICTION:
cout << "Fiction ";
break;
case MYSTERY:
cout << "Mystery ";
break;
case SCIFI:
cout << "SciFi ";
break;
case COMPUTER:
cout << "Computer ";
break;
}
cout << "$";
if (GetPrice() < 1000)
cout << " ";
if (GetPrice() < 100)
cout << " ";
if (GetPrice() < 10)
cout << " ";
/* printf("%.2f", GetPrice());*/
cout << '\n';
}
This is the store class that deals with the array and dynamic allocation. This was working well without input commands, but just using its functions it was working like a champ.
//--------------- STORE.CPP ---------------
// The class definition for Store.
//
#include <iostream>
#include <cstring> // for strcmp
#include "store.h"
using namespace std;
Store::Store()
{
maxSize = 5;
currentSize = 0;
bookList = new Book[maxSize];
}
Store::~Store()
// This destructor function for class Store
// deallocates the Store's list of Books
{
delete [] bookList;
}
void Store::Insert(const char* t, const char* a, Genre g, double p)
// Insert a new entry into the direrctory.
{
if (currentSize == maxSize)// If the directory is full, grow it.
Grow();
bookList[currentSize++].Set(t, a, g, p);
}
void Store::Sell(const char* t)
// Sell a book from the store.
{
char name[31];
strcpy(name, t);
int thisEntry = FindBook(name);// Locate the name in the directory.
if (thisEntry == -1)
cout << *name << " not found in directory";
else
{
cashRegister = cashRegister + bookList[thisEntry].GetPrice();
// Shift each succeding element "down" one position in the
// Entry array, thereby deleting the desired entry.
for (int j = thisEntry + 1; j < currentSize; j++)
bookList[j - 1] = bookList[j];
currentSize--;// Decrement the current number of entries.
cout << "Entry removed.\n";
if (currentSize < maxSize - 5)// If the directory is too big, shrink it.
Shrink();
}
}
void Store::Find(const char* x) const
// Display the Store's matches for a title or author.
{
// Prompt the user for a name to be looked up
char name[31];
strcpy(name, x);
int thisBook = FindBook(name);
if (thisBook != -1)
bookList[thisBook].Display();
int thisAuthor = FindAuthor(name, true);
if ((thisBook == -1) && (thisAuthor == -1))
cout << name << " not found in current directory\n";
}
void Store::DisplayGenre(const Genre g) const
{
double genrePrice = 0;
int genreCount = 0;
for (int i = 0; i < currentSize; i++)// Look at each entry.
{
if (bookList[i].GetGenre() == g)
{
bookList[i].Display();
genrePrice = genrePrice + bookList[i].GetPrice();
genreCount++;
}
}
cout << "Number of books in this genre: " << genreCount
<< " " << "Total: $";
if (genrePrice < 1000)
cout << " ";
if (genrePrice < 100)
cout << " ";
if (genrePrice < 10)
cout << " ";
printf("%.2f", genrePrice);
}
void Store::DisplayStore() const
{
if (currentSize >= 1)
{
cout << "**Title**\t\t"
<< "**Author**\t"
<< "**Genre**\t"
<< "**Price**\n\n";
for (int i = 0; i < currentSize; i++)
bookList[i].Display();
}
else
cout << "No books currently in inventory\n\n";
cout << "Total Books = " << currentSize
<< "\nMoney in the register = $";
if (cashRegister < 1000)
cout << " ";
if (cashRegister < 100)
cout << " ";
if (cashRegister < 10)
cout << " ";
printf("%.2f", cashRegister);
cout << '\n';
}
void Store::Sort(char type)
{
Book temp;
for(int i = 0; i <= currentSize; i++)
{
for (int j = i+1; j < currentSize; j++)
{
if (type == 'A')
{
if (strcmp(bookList[i].GetTitle(), bookList[j].GetTitle()) > 0)
{
temp = bookList[i];
bookList[i] = bookList[j];
bookList[j] = temp;
}
}
if (type == 'T')
{
if (strcmp(bookList[i].GetAuthor(), bookList[j].GetAuthor()) > 0)
{
temp = bookList[i];
bookList[i] = bookList[j];
bookList[j] = temp;
}
}
}
}
}
void Store::SetCashRegister(double x)
// Set value of cash register
{
cashRegister = x;
}
void Store::Grow()
// Double the size of the Store's bookList
// by creating a new, larger array of books
// and changing the store's pointer to refer to
// this new array.
{
maxSize = currentSize + 5;// Determine a new size.
cout << "** Array being resized to " << maxSize
<< " allocated slots" << '\n';
Book* newList = new Book[maxSize];// Allocate a new array.
for (int i = 0; i < currentSize; i++)// Copy each entry into
newList[i] = bookList[i];// the new array.
delete [] bookList;// Remove the old array
bookList = newList;// Point old name to new array.
}
void Store::Shrink()
// Divide the size of the Store's bookList in
// half by creating a new, smaller array of books
// and changing the store's pointer to refer to
// this new array.
{
maxSize = maxSize - 5;// Determine a new size.
cout << "** Array being resized to " << maxSize
<< " allocated slots" << '\n';
Book* newList = new Book[maxSize];// Allocate a new array.
for (int i = 0; i < currentSize; i++)// Copy each entry into
newList[i] = bookList[i];// the new array.
delete [] bookList;// Remove the old array
bookList = newList;// Point old name to new array.
}
int Store::FindBook(char* name) const
// Locate a name in the directory. Returns the
// position of the entry list as an integer if found.
// and returns -1 if the entry is not found in the directory.
{
for (int i = 0; i < currentSize; i++)// Look at each entry.
if (strcmp(bookList[i].GetTitle(), name) == 0)
return i;// If found, return position and exit.
return -1;// Return -1 if never found.
}
int Store::FindAuthor(char* name, const bool print) const
// Locate a name in the directory. Returns the
// position of the entry list as an integer if found.
// and returns -1 if the entry is not found in the directory.
{
int returnValue;
for (int i = 0; i < currentSize; i++)// Look at each entry.
if (strcmp(bookList[i].GetAuthor(), name) == 0)
{
if (print == true)
bookList[i].Display();
returnValue = i;// If found, return position and exit.
}
else
returnValue = -1;// Return -1 if never found.
return returnValue;
}
Now this is the guy who needs some work. There may be some stuff blank so ignore that. This one controls all the input, which is the problem I believe.
#include <iostream>
#include "store.h"
using namespace std;
void ShowMenu()
// Display the main program menu.
{
cout << "\n\t\t*** BOOKSTORE MENU ***";
cout << "\n\tA \tAdd a Book to Inventory";
cout << "\n\tF \tFind a book from Inventory";
cout << "\n\tS \tSell a book";
cout << "\n\tD \tDisplay the inventory list";
cout << "\n\tG \tGenre summary";
cout << "\n\tO \tSort inventory list";
cout << "\n\tM \tShow this Menu";
cout << "\n\tX \teXit Program";
}
char GetAChar(const char* promptString)
// Prompt the user and get a single character,
// discarding the Return character.
// Used in GetCommand.
{
char response;// the char to be returned
cout << promptString;// Prompt the user
cin >> response;// Get a char,
response = toupper(response);// and convert it to uppercase
cin.get();// Discard newline char from input.
return response;
}
char Legal(char c)
// Determine if a particular character, c, corresponds
// to a legal menu command. Returns 1 if legal, 0 if not.
// Used in GetCommand.
{
return((c == 'A') || (c == 'F') || (c == 'S') ||
(c == 'D') || (c == 'G') || (c == 'O') ||
(c == 'M') || (c == 'X'));
}
char GetCommand()
// Prompts the user for a menu command until a legal
// command character is entered. Return the command character.
// Calls GetAChar, Legal, ShowMenu.
{
char cmd = GetAChar("\n\n>");// Get a command character.
while (!Legal(cmd))// As long as it's not a legal command,
{// display menu and try again.
cout << "\nIllegal command, please try again . . .";
ShowMenu();
cmd = GetAChar("\n\n>");
}
return cmd;
}
void Add(Store s)
{
char aTitle[31];
char aAuthor[21];
Genre aGenre = FICTION;
double aPrice = 10.00;
cout << "Enter title: ";
cin.getline(aTitle, 30);
cout << "Enter author: ";
cin.getline(aAuthor, 20);
/*
cout << aTitle << " " << aAuthor << "\n";
cout << aGenre << " " << aPrice << '\n';
*/
s.Insert(aTitle, aAuthor, aGenre, aPrice);
}
void Find()
{
}
void Sell()
{
}
void ViewGenre(Store s)
{
char c;
Genre result;
do
c = GetAChar("Enter Genre - (F)iction, (M)ystery, (S)ci-Fi, or (C)omputer: ");
while ((c != 'F') && (c != 'M') && (c != 'S') && (c != 'C'));
switch (result)
{
case 'F': s.DisplayGenre(FICTION); break;
case 'M': s.DisplayGenre(MYSTERY); break;
case 'S': s.DisplayGenre(SCIFI); break;
case 'C': s.DisplayGenre(COMPUTER); break;
}
}
void Sort(Store s)
{
char c;
Genre result;
do
c = GetAChar("Enter Genre - (F)iction, (M)ystery, (S)ci-Fi, or (C)omputer: ");
while ((c != 'A') && (c != 'T'));
s.Sort(c);
}
void Intro(Store s)
{
double amount;
cout << "*** Welcome to Bookstore Inventory Manager ***\n"
<< "Please input the starting money in the cash register: ";
/* cin >> amount;
s.SetCashRegister(amount);*/
}
int main()
{
Store mainStore;// Create and initialize a Store.
Intro(mainStore);//Display intro & set Cash Regsiter
ShowMenu();// Display the menu.
/*mainStore.Insert("A Clockwork Orange", "Anthony Burgess", SCIFI, 30.25);
mainStore.Insert("X-Factor", "Anthony Burgess", SCIFI, 30.25);*/
char command;// menu command entered by user
do
{
command = GetCommand();// Retrieve a command.
switch (command)
{
case 'A': Add(mainStore); break;
case 'F': Find(); break;
case 'S': Sell(); break;
case 'D': mainStore.DisplayStore(); break;
case 'G': ViewGenre(mainStore); break;
case 'O': Sort(mainStore); break;
case 'M': ShowMenu(); break;
case 'X': break;
}
} while ((command != 'X'));
return 0;
}
Please, any and all help you can offer is amazing.
Thank you.
Welcome to the exciting world of C++!
Short answer: you're passing Store as a value. All your menu functions should take a Store& or Store* instead.
When you're passing Store as a value then an implicit copy is done (so the mainStore variable is never actually modified). When you return from the function the Store::~Store is called to clean up the copied data. This frees mainStore.bookList without changing the actual pointer value.
Further menu manipulation will corrupt memory and do many double frees.
HINT: If you're on linux you can run your program under valgrind and it will point out most simple memory errors.
Your Store contains dynamically-allocated data, but does not have an assignment operator. You have violated the Rule of Three.
I don't see the Store class being instantiated anywhere by a call to new Store() which means the booklist array has not been created but when the program exits and calls the destructor, it tries to remove the array that was never allocated and hence that's why i think you are getting this error. Either, modify the destructor to have a null check or instantiate the class by a call to the constructor. Your code shouldn't still be working anywhere you are trying to use a Store object.
Hope this helps