Re: Access Violation Error Help
Quote:
Originally Posted by
Shadow_Govt
Your right! Thanks for pointing that out.
I made edits to my last post. If you write a function for resizing the string, and use that to get you new strings, that would, at the very least, neaten the code up somewhat so that it becomes easier to spot problems (and harder to make mistakes).
Note that the function takes care of everything -- allocation and deallocation -- this removes a lot of the "naked" calls to "delete[]" and "new char[]" all over your code. Remember that I did not test that function. If there is a bug, you will have to focus on it. But at least it moves the focus to a central location, and not all over your code.
I would also suggest you write a similar function for resizing the arrays of pet info. Something like this:
Code:
char **ResizePetInfo(char**& petInfo, unsigned int newSize)
{ ///
function here to do all of the resizing of the petInfo array
}
//...
petName = ResizePetInfo(petName, animalcount);
//...
Then this eliminates the naked new/delete calls you're making to resize the pet information. I am not going to write it, as it's your assignment.
Regards,
Paul McKenzie
Re: Access Violation Error Help
I noticed that the program works if I dont delete each individual element in the memory, but this causes leaks, and I cant have that. Where am I going wrong?
Here is the code:
Code:
#define _CRTDBG_MAP_ALLOC
#include < iostream >
#include < iomanip >
#include < cctype >
#include < cstring >
using std::cout;
using std::cin;
using std::endl;
using std::setw;
using namespace std;
//Variables
const int MAX = 60;
const int CAT = 20;
const int DOG = 35;
int menu_choice;
char again = 'Y';
char ** petName = 0;
char ** petTemp = 0;
char ** ownName = 0;
char ** ownTemp = 0;
char ** petType = 0;
char ** typeTemp = 0;
int animalcount = 0;
int catCount = 0;
int dogCount = 0;
int totalCount = 0;
int count[60] = {0};
int * arrayCount = &count[0];
int catCost = 0;
int dogCost = 0;
int overallCost = 0;
int input = 0;
//Functions
void MenuChoice( int &menu_choice );
void ProcessMenu( int &menu_choice );
void GetPet( char **& petName, char **& ownName, char **& petType );
void DisplayAll();
void RemovePet( char **& petName, char **& ownName, char **& petType );
void TotalCat( int &catCount, int &catCost );
void TotalDog( int &dogCount, int &dogCost );
void TotalDay( int &overallCost, int &catCost, int &dogCost, int &totalCount );
void AvgCap( int * &arrayCount );
char Exit( char again );
int main()
{
//Test for Leaks.
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//Memory Allocation
petName = new char * [256];
ownName = new char * [256];
petType = new char * [256];
//Function Pointers
void (*fn_ptr_Menu)( int & );
fn_ptr_Menu = MenuChoice;
void (*fn_ptr_Process)( int & );
fn_ptr_Process = ProcessMenu;
while( again == 'Y' )
{
fn_ptr_Menu( menu_choice );
fn_ptr_Process( menu_choice );
}
//Delete Memory.
for( int i = 0; i < totalCount; i++)
{
delete[] petName[i];
delete[] ownName[i];
delete[] petType[i];
}
delete[] petName;
delete[] ownName;
delete[] petType;
system( "pause" );
return 0;
}
/***********************************************************************************************************************
*Name: MenuChoice
*Parameters: &menu_choice
*Return: none
*Purpose: This function is to display the menu to the user.
***********************************************************************************************************************/
void MenuChoice( int &menu_choice )
{
cout << "\t\t\t\n\nMenu\n\n" << endl;
cout << "1) Board a Critter " << endl;
cout << "2) Remove a Critter " << endl;
cout << "3) Display all Critters " << endl;
cout << "4) Count all Critters and Calculate Daily Proceeds " << endl;
cout << "5) Exit " << endl;
cout << "\n\nPlease enter a menu choice, 1 to 5: " ;
cin >> menu_choice;
}
/***********************************************************************************************************************
*Name: ProcessMenu
*Parameters: &menu_choice
*Return: none
*Purpose: This function is to process the menu choice.
***********************************************************************************************************************/
void ProcessMenu( int &menu_choice )
{
//Function Pointer
void (*fn_ptr_disAll)();
fn_ptr_disAll = DisplayAll;
if( menu_choice < 1 || menu_choice > 5 )
{
cout << "\n\nPlease enter a number between 1 and 5! " << endl;
}
else
{
switch ( menu_choice)
{
case 1 ://Get Pet.
{
GetPet( petName, ownName, petType );
break;
}
case 2://Remove Pet
{
fn_ptr_disAll();
RemovePet( petName, ownName, petType );
break;
}
case 3://Display all info
{
fn_ptr_disAll();
break;
}
case 4://Display totals and avg
{
TotalCat( catCount, catCost );
TotalDog( dogCount, dogCost );
TotalDay( overallCost, catCost, dogCost, totalCount) ;
AvgCap(arrayCount);
break;
}
case 5://Exit the program
{
again = Exit( again );
break;
}
}
}
}
/***********************************************************************************************************************
*Name: GetPet
*Parameters: petName, ownName, petType
*Return: none
*Purpose: This function gets the pet info from the user and gets the counts.
***********************************************************************************************************************/
void GetPet( char **& petName, char **& ownName, char **& petType )
{
if( animalcount == 12)
{
cout << "\n\nYou cannot board anymore animals! You are at maximum capacity! " << endl;
}
else
{
cout << "Which cage number do you want to add the critter to? ( 1 to 12) ";
cin >> input;
if( input < 1 || input > 12 )
{
cout << "Please input a number between 1 and 12! " << endl;
}
else
{
//buffer.
char buffer[MAX] = {0};
//temp arrays
petTemp = new char * [animalcount + 1];
ownTemp = new char * [animalcount + 1];
typeTemp = new char * [animalcount + 1];
//addresses for temp
for( int i = 0; i < animalcount; i++ )
{
petTemp[i] = petName[i];
ownTemp[i] = ownName[i];
typeTemp[i] = petType[i];
}
int k = input - 1;
//Get input for the Pet Name, Owner name, and Pet Type.
cout << "\n\nPlease input Pet Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, 20 );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
petTemp[k] = new char[strlen( buffer ) + 1];
strcpy( petTemp[k], buffer );
cout << "\n\nPlease input Owner Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer , 20 );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
ownTemp[k] = new char[strlen( buffer ) + 1];
strcpy( ownTemp[k], buffer );
cout << "\n\nPlease input critter type ( cat / dog ): ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, 8 );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
typeTemp[k] = new char[strlen( buffer ) + 1];
strcpy( typeTemp[k], buffer );
//delete old information
delete [] petName;
delete [] ownName;
delete [] petType;
//add the new info.
petName = petTemp;
ownName = ownTemp;
petType = typeTemp;
//Add to the counts.
animalcount++;
totalCount ++;
//Add count to the avg array function helper.
* arrayCount = totalCount;
arrayCount++;
//cat count.
_strlwr( *petType );
char * breaker[10]= {0};
* breaker = petType[k];
int result;
result = strcmp( * breaker, "cat" );
int result1;
result1 = strcmp( * breaker, "dog" );
if( result == 0 )
{
catCount++;
}
if( result1 == 0 )
{
//dog count.
dogCount++;
}
cout << "\n\nCritter " << input << ", has been added! " << endl;
}
}
}
/***********************************************************************************************************************
*Name: DisplayAll
*Parameters: none
*Return: none
*Purpose: This function displays all pet infomation to the user.
***********************************************************************************************************************/
void DisplayAll()
{
cout.setf( ios::left );
cout << setw(10) << "Cage Num." << setw(20) << "Pet Name" << setw(20) << "Owner's Name" << setw(20) << "Pet Type" << endl;
for( int i = 0; i < totalCount; i++ )
{
cout << setw(10) << i+1 << setw(20) << petName[i] << setw(20) << ownName[i] << setw(20) << petType[i] << endl;
}
}
/***********************************************************************************************************************
*Name: RemovePet
*Parameters: petName, ownName, petType
*Return: none
*Purpose: This function displays all pet infomation to the user.
***********************************************************************************************************************/
void RemovePet( char **& petName, char **& ownName, char **& petType )
{
cout << "Which cage number do you want to remove the critter from? ( 1 to 12) ";
cin >> input;
if( input < 1 || input > 12 )
{
cout << "Please input a number between 1 and 12! " << endl;
}
else
{
int j = input - 1;
strcpy( petName[j], "Empty" );
strcpy( ownName[j], "Empty" );
strcpy( petType[j], "Empty" );
//Correct the count
animalcount--;
cout << "\n\nCritter " << input << ", has been removed. " << endl;
}
}
/***********************************************************************************************************************
*Name: Exit
*Parameters: again
*Return: none
*Purpose: This function exits the program.
***********************************************************************************************************************/
char Exit( char again )
{
again = 'n';
return again;
}
/***********************************************************************************************************************
*Name: TotalCat
*Parameters: int &catCount, int &catCost
*Return: none
*Purpose: This function finds the cat costs and displays.
***********************************************************************************************************************/
void TotalCat( int &catCount, int &catCost )
{
catCost = catCount * CAT;
cout << "\n\nThe Amount of Cats today is: " << catCount << ". " << endl;
cout << "The Sum of today's Cat earnings is: " << catCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: TotalDog
*Parameters: petType
*Return: none
*Purpose: This function finds the dog costs and displays.
***********************************************************************************************************************/
void TotalDog( int &dogCount, int &dogCost )
{
dogCost = dogCount * DOG;
cout << "\n\nThe Amount of Dogs today is: " << dogCount << ". " << endl;
cout << "The Sum of today's Dog earnings is: " << dogCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: TotalDay
*Parameters: int &overallCost, int &catCost, int &dogCost, int &animalcount
*Return: none
*Purpose: This function finds the total for the day.
***********************************************************************************************************************/
void TotalDay( int &overallCost, int &catCost, int &dogCost, int &totalCount )
{
overallCost = catCost + dogCost;
cout << "\n\nThe Total Amount of Critters today is: " << totalCount << ". " << endl;
cout << "Total amount of animals right now: " << animalcount << ". " << endl;
cout << "The Sum of today's earnings is: " << overallCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: AvgCap
*Parameters: none
*Return: none
*Purpose: This function finds the total avg for the day of animals.
***********************************************************************************************************************/
void AvgCap( int * &arrayCount )
{
int avg = 0;
int sum = 0;
arrayCount = &count[0];
for( int i = 0; i < totalCount; i++, arrayCount++ )
{
sum += * arrayCount;
}
avg = sum / totalCount;
cout << "\n\nThe Average Amount of Critters today is: " << avg << ". " << endl;
}
Re: Access Violation Error Help
Quote:
Originally Posted by
Shadow_Govt
I noticed that the program works if I dont delete each individual element in the memory, but this causes leaks, and I cant have that. Where am I going wrong?
Remember that you have to do the debugging, as it's your assignment. Since your code is very hard to follow, here is some advice:
First, your dynamically allocated slots should have been initialized to 0. You didn't do that in the beginning of your program.
Second, notice that your input routines are practically identical. The only difference is the prompt and the array you're saving the information in. This is where you could have written a function, thus making the code much shorter and easier to follow and maintain.
Code:
void GetPet( char **& petName, char **& ownName, char **& petType )
{
if( animalcount == 12)
{
cout << "\n\nYou cannot board anymore animals! You are at maximum capacity! " << endl;
}
else
{
cout << "Which cage number do you want to add the critter to? ( 1 to 12) ";
cin >> input;
if( input < 1 || input > 12 )
{
cout << "Please input a number between 1 and 12! " << endl;
}
else
{
GetInput(&petName[input-1], "\n\nPlease input Pet Name: ");
GetInput(&ownName[input-1], "\n\nPlease input Owner Name: ");
GetInput(&petType[input-1], "\n\nPlease input critter type ( cat / dog ): ");
++animalcount;
}
}
}
That's practically the entire function.
GetInput() would look like this (lines missing):
Code:
void GetInput(char** pBuffer, const char* prompt)
{
char buffer[MAX];
// Write the input routine, but use the passed in prompt as the prompt
//.. For you to do
// Assign the new string
*pBuffer = AssignNewString( // parameters missing, you fill them in)
}
But I need to go back a few posts -- how do you really justify what I mentioned a few posts ago, and that is you do not have ragged arrays. Here is your exact input statement:
Code:
cout << "Which cage number do you want to add the critter to? ( 1 to 12) ";
cin >> input;
if( input < 1 || input > 12 )
{
cout << "Please input a number between 1 and 12! " << endl;
}
So you *do* have 12 slots, and only 12 slots. That is exactly why I don't understand the dynamic allocation of the "slots" array. There is no change in the number -- it's not as if you "grow" the number of slots on the fly -- it's always 12. Otherwise, that input above doesn't make logical sense.
The only thing dynamic in this assignment that I see is the string generation. Then yes, you don't know how long the input strings will be, so you dynamically allocate. That is a different story than the slots you are placing the strings in.
I'm saying all of this because hardly anyone here will want to work with the code you posted as it stands, so the best thing you could do is organize it in a way that is "user friendly" or more plainly, "helper friendly". I mentioned already to write a function, but you didn't do that.
Speaking of which, here is a better version of AssignNewString. Note that in the code above in GetInput, all you have to do is call it with the appropriate parameters.
Code:
char *AssignNewString(const char* oldString, const char *newString)
{
if ( !newString )
return 0;
unsigned int newSize = strlen(newString);
char *pTemp = new char [newSize+1];
strcpy(pTemp, newString);
delete [] oldString;
return pTemp;
}
I made amendments to the function, but you should have at least attempted to write this function to remove and "resize" a string with new data.
So, just this alone shows that the code need not be messy. Anytime you are asked to do an assignment like this, the best you can do is not to compound the problem by being as messy as the assignment given. You try and compartmentalize the code into blocks (i.e. functions) that handle the details. Now, if there is a problem in allocating the strings, I know exactly where to go, and that is AssignNewString. If there is something wrong with the input, again, it is in GetInput().
Regards,
Paul McKenzie