Creating and clearing an array of structures - c++

I've been trying to write a short program allowing the user to add entries to a "database", listing the entries they have put in, and the ability to clear all the entries without ending the program. Here's what i've got
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
struct BIRTH
{int month; int year;};
struct ID
{string name; bool vip; float score;
struct BIRTH date;} ;
int main(int argc, char** argv) {
ID **ptrarr;
ptrarr = new ID * [10];
for (int r=0; r<10; r++)
{ptrarr[r] = new ID[1] ;}
int counter = 0;
while(counter<100){
cout << "Type add to create a new entry" << endl;
cout << "Type list to see all entries" << endl;
cout << "Type clear to delete all entries" << endl;
cout << "Type exit to terminate" << endl;
string command = "0";
getline (cin,command);
if(command=="add")
{
cout << "Enter name" << endl;
getline (cin,ptrarr[counter][1].name);
cout << "VIP? 1 for yes, 0 for no" << endl;
cin >> ptrarr[counter][1].vip;
cout << "Enter score" << endl;
cin >> ptrarr[counter][1].score;
cout << "Month of birth" << endl;
cin >> ptrarr[counter][1].date.month;
cout << "Year of birth" << endl;
cin >> ptrarr[counter][1].date.year;
counter++;
}
else if(command=="list")
{
for (int i=0; i<counter; i++)
{int n=i+1;
cout << n << " "
<< ptrarr[i][1].name << " ";
if (ptrarr[i][1].vip)
{cout << "VIP ";}
cout << "Score: " << ptrarr[i][1].score << " "
<< "Born: " << ptrarr[i][1].date.month << "/" << ptrarr[i][1].date.year << endl;
}
}
else if(command=="clear")
{delete[] ptrarr;
cout << "Entries cleared" << endl;}
else if(command=="exit")
{return 0;}
else
cout << "try again" << endl;
}
return 0;
}
Now here's the deal: the following code successfully compiles, but when I type in the "add" command, the program crashes (achievement unlocked, didn't think it's possible to obtain with such a short code). The most important thing is that the array is made of a multitype structure and that the "clear" command wipes out all the entries in the array.
NOTE: I understand that there are thousand better ways to write this piece of code, but I'm writing it to practice the things I have covered so far regarding C++. So unless it is absolutely necessary for the code to run, please do not introduce any new gimmicks =)

Replace all ptrarr[counter][1] with ptrarr[counter][0] fixes the problem.
Further advices:
I. This code has redundancy:
ID **ptrarr;
ptrarr = new ID * [10];
for (int r=0; r<10; r++)
{ptrarr[r] = new ID[1] ;}
Replace it with:
ID *ptrarr;
ptrarr = new ID [10];
Then you do not need extra [0] at the end of each ptrarr[counter]
II. functions make your code more readable:
if(command=="add")
add();
else if(command=="list")
list();
else if(command=="clear")
clear();
else if(command=="exit")
return 0;
else
cout << "try again" << endl;
Then decisions are made in a smaller area (Good practice for large programs.)
III. There is another mistake in your code:
else if(command=="clear")
{delete[] ptrarr;
cout << "Entries cleared" << endl;}
Here you should reset the counter. Also if you regard my point (I) this part is fine. Otherwise, if you use new with a for loop, I am afraid that you need to delete with a for loop too. Merely removing the root of the array tree brings you memory leak!
Also, if you cleared the list by delete, wont you need to store data in the list anymore? Using delete in linked lists is a good idea, but it does not apply here. Just reseting the counter does the job and it does not show IDs in the list anymore. The for inside the list does only count up to the counter.
If you exit the program don't you free the memory?
I say
delete [] ptrarr;
is good for being at exit.

You are creating an an array of pointers, each one of which points to one element:
ptrarr[r] = new ID[1] ;
The maximum index that you can use with ptrarr[r] is 0. Since you are using ptrarr[counter][1], you are accessing memory that is out of bounds. This leads to undefined behavior. Crashing is one such undefined behavior.
There are other issues with your code that you may want to fix.
More out of bounds memory access
You are using:
int counter = 0;
while(counter<100){
...
getline (cin,ptrarr[counter][1].name);
That is again going to lead to undefined behavior if counter > 10 since you allocated only 10 pointers for ptrarr.
Deleting the contents
You are using:
else if(command=="clear")
{
delete[] ptrarr;
cout << "Entries cleared" << endl;
}
There are couple of problems with this:
You have memory leak. You never call delete [] on what ptrarr[0] - ptrarr[9] point to. You'll have to use:
else if(command=="clear")
{
for ( int i = 0; i < 10; ++i )
{
delete [] ptrarr[i];
}
delete[] ptrarr;
cout << "Entries cleared" << endl;
}
Remember that every allocation must have a corresponding deallocation. Otherwise, you are leaking memory.
Once you call delete [] ptrarr;, it points to dangling memory. I don't see any code that reallocates memory for ptrarr while you continue to use it.
You need to reallocate memory and reset counter to 0 when the user chooses "clear".
My suggestion
You don't two levels of pointers. You just need something like:
int const MAX_ITEMS = 100;
ID* IDarr = new ID[MAX_ITEMS];
Instead of ptrarr[counter][1], use IDarr[counter].
Use MAX_ITEMS in the expression of the while statement instead of the magic number 100.
int counter = 0;
while(counter<MAX_ITEMS){
When processing "clear", you don't need to deallocate or allocate memory. Just reset counter.
else if(command=="clear")
{
counter = 0;
cout << "Entries cleared" << endl;
}
Make sure to deallocate memory before returning from main.
Here's the complete main function with the changes:
int main(int argc, char** argv) {
const int MAX_ITEMS = 100;
ID* IDarr = new ID[MAX_ITEMS];
int counter = 0;
while(counter < MAX_ITEMS){
cout << "Type add to create a new entry" << endl;
cout << "Type list to see all entries" << endl;
cout << "Type clear to delete all entries" << endl;
cout << "Type exit to terminate" << endl;
string command = "0";
getline (cin,command);
if(command=="add")
{
cout << "Enter name" << endl;
getline (cin, IDarr[counter].name);
cout << "VIP? 1 for yes, 0 for no" << endl;
cin >> IDarr[counter].vip;
cout << "Enter score" << endl;
cin >> IDarr[counter].score;
cout << "Month of birth" << endl;
cin >> IDarr[counter].date.month;
cout << "Year of birth" << endl;
cin >> IDarr[counter].date.year;
counter++;
}
else if(command=="list")
{
for (int i=0; i<counter; i++)
{
int n=i+1;
cout << n << " " << IDarr[i].name << " ";
if (IDarr[i].vip)
{
cout << "VIP ";
}
cout
<< "Score: " << IDarr[i].score << " "
<< "Born: " << IDarr[i].date.month << "/" << IDarr[i].date.year << endl;
}
}
else if(command=="clear")
{
counter = 0;
cout << "Entries cleared" << endl;
}
else if(command=="exit")
{
// Don't use return 0;
// Just break out of the while loop so that memory
// can be deallocated at the end of this function.
break;
}
else
cout << "try again" << endl;
}
delete [] IDarr;
return 0;
}

Array indices start at 0.
ptrarr[counter][1] refers to the second element of ptrarr[counter]. ptrarr[counter] points to an array of one element.

try this :
if(command=="add") {
cout << "Enter name" << endl;
getline (cin,ptrarr[counter][0].name);
cout << "VIP? 1 for yes, 0 for no" << endl;
cin >> ptrarr[counter][0].vip;
cout << "Enter score" << endl;
cin >> ptrarr[counter][0].score;
cout << "Month of birth" << endl;
cin >> ptrarr[counter][0].date.month;
cout << "Year of birth" << endl;
cin >> ptrarr[counter][0].date.year;
counter++;
}
else if(command=="list") {
for (int i=0; i<counter; i++){
int n=i+1;
cout << n << " "<< ptrarr[i][0].name << " ";
if (ptrarr[i][0].vip){
cout << "VIP ";
}
cout << "Score: " << ptrarr[i][0].score << " "
<< "Born: " << ptrarr[i][0].date.month << "/" << ptrarr[i][0].date.year << endl;
}
}
Conclusion :
Just as you initialized counter with 0 you should have used 0 index to access the first element;
Same goes while listing.
Arrays are 0 index based.

Related

Changing the values of pointers via addresses

This week, we were tasked to create a program where:
Program displays the addresses and values of the array
User inputs the corresponding address he wants to change
User inputs the new value for that address
I was able to figure how a pointer works but it displays another number instead of the inputted value.
Here's the code:
int j =1, var, nx;
int array[4] = {3618, 6555, 5012, 1869};
int* pa; //pointer
char choice;
int remember = 0;
pa = array;
cout << endl;
cout << "\t------------------------" << endl;
cout << "\t\t Values" << endl;
cout << "\t------------------------" << endl;
for(int i = 0; i<4; i++){
cout << "\tarray" << j;
cout << " = " << std::dec << *(pa + i);
cout << " (" << pa + i << ")" << endl;
j++;
}
cout << "\t------------------------" << endl << endl;
cout << "\tPlease enter an address: ";
cin >> hex >>var;
cout << endl;
cout <<"\tYou entered: " << hex << var << endl;
cout << "\tPlease enter a new value: ";
cin >> nx;
pa = (int*)var;
cout << endl;
*pa = nx;
pa = array;
j=1;
cout << endl;
cout << "\t------------------------" << endl;
cout << "\t\t New Values" << endl;
cout << "\t------------------------" << endl;
for(int i = 0; i<4; i++){
cout << "\tarray" << j;
cout << " = " << std::dec << *(pa+i);
cout << " (" << &array[i] << ")" << endl;
j++;
}
cout << "\t------------------------" << endl << endl;
The problem is cin >> nx; is reading the value as hex. I'm quite sure this is happening because the previous use of cin in the program read the value as hex: cin >> hex >>var;. I observed the same thing happening with a cout statement I added to your program when testing it.
If that is changed to cin >> std::dec >> nx;, the behavior of the program is correct.
E.g., using your test run: 353 in hex when converted to decimal is 851.
A helpful tip for future: You don't need the j variable: inside the for loops you can just use i + 1.
What OP is seeing is the the hex modifier still being in effect.
cin >> hex >>var;
turns on hex. Nothing turned it off again.
So when OP types in 353, the program interprets it as a hexadecimal number. 0x353 == 851.
Solution:
Revert to decimal input.
cin >> dec >> nx;
A good habit to get into is to use descriptive words as your variables. It makes it a whole lot easier to debug, and more importantly understand what is going on.
Now, if I'm interpreting this correctly, you are setting pa equal to a new pointer called var, instead of setting pa equal to var. Here is a reference page on pointers, Scroll to the dereference operator to see what I was talking about. The (int*) is unnecessary.

Search in Dynamic Array

When I'm searching an integer in my dynamic array, the search function isn't working well as its always showing its positioned at 1. whether the data is actually there or not.
What i'm actually trying to do is using dynamic data structure, I'm adding the data. Deleting, searching and saving to txt file. and Loading it back. But the problem is search. I used switch cases and search is at Case 4.
#include<iostream>
#include<string>
#include<fstream> //to save file in text
using namespace std;
int main()
{
int *p1;
int size = 0;
int counter = 0;
p1 = new int[size];
int userchoice;
int i;
int position;
while (1)
{
cout << "Please enter your choice " << endl;
cout << endl;
cout << "To insert Press '1'" << endl;
cout << "To Delete press '2'" << endl;
cout << "To View press '3'" << endl;
cout << "To Search press '4'" << endl;
cout << "To Save Press '5'" << endl;
cout << "To Load Previously saved Data press '6'" << endl;
cout << "To Exit press '7'" << endl;
cout << endl;
cout << "Enter your choice: ";
cin >> userchoice;
switch (userchoice) // User's selection from the menu
{
case 1: //Insert Number
cout << "Enter a Number: ";
cin >> p1[size];
counter++;
size++; //Add's memory space
break;
case 2: //Delete Number
int udelete;
cout << "Enter a number to delete: ";
cin >> udelete; //User enters Number to be deleted
//Checking if the number is in an array.
for (position = 0; position<size; position++)
{
if (p1[position] == udelete)
break;
}
if (position>size)
{
cout << "The number is not in the memory: ";
cout << endl;
break;
}
for (i = position; i<size; i++) {
p1[i] = p1[i + 1];
}
size--;
cout << "Successfully Deleted!!! ";
cout << endl;
break;
case 3: // View
for (i = 0; i<size; i++)
{
cout << "Your data" << " " << i << " " << "-->" << p1[i] << endl;
}
break;
case 4:
{
int usearch;
cout << "Please enter the figure you would like to search ";
cout << "->";
cin >> usearch;
for (i = 0; i>size; i++)
{
if (p1[size] == usearch)
break;
}
if (usearch == size)
{
cout << "not found. ";
}
cout << "Position at: " << i + 1 << endl;
break;
}
case 5: // Save
{
ofstream save;
save.open("Dynamicdata.txt", ofstream::out | ofstream::app);
for (i = 0; i<size; i++)
{
save << p1[i] << endl;
}
save.close();
cout << "File Saved " << endl;
break;
}
case 6: //Read from File
{
string read;
ifstream file_("Dynamicdata.txt");
if (file_.is_open())
{
while (getline(file_, read))
{
cout << read << "\n";
}
file_.close();
}
else
cout << "File Not open" << endl;
cin.get();
break;
}
case 7:
{
return 0;
}
}
}
}
Your problem is that the size of your array is 0. Here you set size to 0 and then size for the size of p1
int size=0;
int counter=0;
p1 = new int[size];
You are going to need to make size bigger so that you can actually store elements in p1 or instead of using arrays and dynamic memory allocation use a std::vector and let it handle that for you.
The code has undefined behaviour because initailly the dynamically allocated array pointed to by pointer p1 has no elements
int size=0;
^^^^^^^^^^
//...
p1 = new int[size]; // size is equal to 0
So in the following code snippet an atttempt to write data to p1[size] results in undefined behaviour
case 1: //Insert Number
cout<<"Enter a Number: ";
cin>>p1[size]; // undefined behaviour
^^^^^^^^^^^^^
counter++;
size++; //Add's memory space
break;
You need to reallocate the array to reserve memory for the added new element.
Take into account that for example this loop
for (i = 0; i>size; i++)
^^^^^^^
{
if (p1[size] == usearch)
break;
}
will never iterate because variable i set to zero can not be greater than size that at least equal to zero.
And it would be logically more correct to write
if (p1[i] == usearch)
^^^^^
instead of
if (p1[size] == usearch)
^^^^^^^^
Consequently this if statement
if (usearch == size)
^^^^^^^
{
cout << "not found. ";
}
should be replaced with this for statement
if (i == size)
^^
{
cout << "not found. ";
}

C++ inventory item removal

Increase the inventory to be 10 items. DONE!!!
Create a for loop that asks the user to input the initial items in the inventory.DONE!!!
After the for loop create a minor story where the healer changes two items (i.e. items 4 and 8).What I want is to SWAP an item for another item ie would you like to trade your {[item] for [item2] y or n
Sort the inventory in alphabetical order. You can use your own sort if you want, but here is a bubble sort algorithm:
// A simple inventory program using a struct to store data
// in an array.
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
// define a data structure
struct InventoryRecord
{
string name; // inventory item name
int qty; // how many are in stock
double value; // the value
};
// const for the max size of the record array
const int MAX_SIZE = 9;
// function prototypes
void addData(InventoryRecord list[], int& size);
void dispData(const InventoryRecord list[], int size);
void remData( const InventoryRecord list[], int size);
void saveFile(const InventoryRecord list[], int size);
void openFile(InventoryRecord list[], int& size);
char getMenuResponse();
int main(int argc, char *argv[])
{
InventoryRecord recList[MAX_SIZE];
int numOfRecs = 0;
bool run = true;
do
{
cout << "Hero's Inventory - " << numOfRecs << " items in your bag" << endl;
switch ( getMenuResponse() )
{
case 'A': addData(recList, numOfRecs); break;
case 'D': dispData(recList, numOfRecs); break;
case 'R': remData(recList, numOfRecs); break;
case 'O': openFile(recList, numOfRecs); break;
case 'S': saveFile(recList, numOfRecs); break;
case 'Q': run = false; break;
default : cout << "That is NOT a valid choice" << endl;
}
} while (run);
cout << endl << "Program Terminated" << endl;
// system("PAUSE"); // Program exits immediatly upon "Quit" if commented out
return EXIT_SUCCESS;
}
// Task: Allow data entry of one inventory item
// Accepts: References to the inventory array and its size
// Returns: Nothing
// Modifies: The array and size 'actual parameter'
// NOTE: Could be modified to allow entry of more than one item
void addData(InventoryRecord list[], int& size)
{
InventoryRecord tmp; // declare a temp item that we will load before putting in the array
char response;
char str[256]; // needed for cin.getline; we are going to use a char array
if (size < MAX_SIZE) {
system("cls");
cout << "Please enter 10 items helpful to your quest! " << endl;
cout << "Enter item: " << endl << endl;
cout << "Name: ";
// Get up to 256 characters from the keyboard including white space.
// Stop reading if encounter the \n first. If there's any chance of
// more than 256 characters you will have to clean up cin with
// cin.ignore before the next input.
cin.getline(str, 256, '\n'); // for char arrays; different from the other getline
tmp.name = str;
cout << "Quantity: ";
cin >> tmp.qty;
cout << "Value: ";
cin >> tmp.value;
cout << endl;
// see if this record should be added to the array
cout << "Add to inventory? (y/n) ";
cin >> response;
if (toupper(response) == 'Y')
list[size++] = tmp;
} else {
cout << "Inventory is full; cannot enter more units." << endl;
system("pause");
}
system("cls");
}
void dispData(const InventoryRecord list[], int size)
{
system("cls");
double cost = 0;
if(size < 1) {
cout << "Nothing to display" << endl;
} else {
cout << "All Items in your Bag" << endl << endl;
cout << fixed << setprecision(2);
cout << "Item Name Qty Value" << endl;
cout << "~~~~~~~~~~~~~~~~~~" << endl;
cout << left;
for (int i = 0; i < size; i++) {
cout << setw(21) << list[i].name << right
<< setw(4) << list[i].qty
<< setw(10) << list[i].value << left << endl;
cost = cost + list[i].value * list[i].qty;
}
cout << "~~~~~~~~~~~~~~~~~~~" << endl;
cout << right << setw(3) << size;
cout << " items listed";
cout << right << setw(19) << cost << endl << endl;
}
system("PAUSE");
system("cls");
}
void remData(const InventoryRecord list[], int size) {
system("cls");
cout <<"Enter Item you wish to remove from your inventory: " << endl;// This is being displayed so user can see items in the inventory
double cost = 0;
if(size < 1) {
cout << "Nothing to display" << endl;
} else {
cout << "All Items in your Bag" << endl << endl;
cout << fixed << setprecision(2);
cout << "Item Name Qty Value" << endl;// It is not displaying right the alignment is off
cout << "~~~~~~~~~~~~~~~~~~" << endl;
cout <<"Item Name: ";/* from here I do not know what to do! What I want is have use type the item name they want removed
also display an error if they enter an item wrong*/
cout << left;
for (int i = 0; i < size; i++) {
cout << setw(21) << list[i].name << right
<< setw(4) << list[i].qty
<< setw(10) << list[i].value << left << endl;
cost = cost + list[i].value * list[i].qty;
}
cout << "~~~~~~~~~~~~~~~~~~~" << endl;
cout << right << setw(3) << size;
cout << " items listed";
cout << right << setw(19) << cost << endl << endl;
}}
// Save records to disc
void saveFile(const InventoryRecord list[], int size) {
ofstream outfi("Inventory.txt");
// make sure the file stream is open before doing IO
if (!outfi.fail()) {
system("cls");
cout << "Saving inventory to the disc ";
for(int i = 0; i < size; i++) {
outfi << list[i].name << ';'
<< list[i].qty << ';'
<< list[i].value;
// Start a new line after all but the last record
// Simplifies reading the file as EOF is at end of last line
if (i < size-1) outfi << endl;
}
cout << endl << size << " records writen to the disc." << endl;
outfi.close();
system("PAUSE");
system("cls");
}
else {
cout << "ERROR: problem with file" << endl;
system("PAUSE");
system("cls");
}
}
// Open file and load array
void openFile(InventoryRecord list[], int& size)
{
ifstream infi("Inventory.txt");
string str;
stringstream strstrm;
// make sure the file stream is open before doing IO
if (!infi.fail()) {
system("cls");
cout << "Reading inventory from the disc ";
size = 0; // overwrite any existing records
while(!infi.eof() && size < MAX_SIZE) {
// get and store the name
getline(infi, str, ';');
list[size].name = str;
// get, convert and store the quantity
getline(infi, str, ';');
strstrm.str(""); strstrm.clear(); // empty and clear the stringstream
strstrm << str;
strstrm >> list[size].qty;
// get, convert and store the cost
getline(infi, str);
strstrm.str(""); strstrm.clear(); // empty and clear the stringstream
strstrm << str;
strstrm >> list[size++].value;
}
cout << endl << size << " records read from the disc." << endl;
system("PAUSE");
system("cls");
}
else { // something went wrong with opening the file
cout << "ERROR: problem with file" << endl;
system("PAUSE");
system("cls");
}
}
char getMenuResponse()
// Task: Put the menu on screen and get a response
// Accepts: Nothing
// Returns: The users response
// Modifies: Nothing
// NOTE: Characters are far more intuitive at the command
// line than numbers; avoid using numbers.
{
char response;
cout << endl << "Make your selection" << endl
<< "(A)dd Items, (D)isplay Items, (R)emove items, (O)pen File, (S)ave File, (Q)uit" << endl
<< "> ";
cin >> response;
cin.ignore(256, '\n');
// clean-up up to 256 chars including the delimiter specified (\n, the endl)
// OR stop when the \n is encountered after removing it.
return toupper(response);
}
To remove an element from your inventory, you just need to move all elements after the removed element one position forward. Once that is done, you also need to reduce the lengthy by one. For example, to remove the elements at the position index from an array array with currently length elements you could use
if (index < length) {
std::copy(array + index + 1, array + length, array + index);
++length;
}
There are essentially two ways to remove the element, the easiest is swap the element which you want to delete with the last one and resize the list:
void deleteElem(Data[] list, int & listLength, int ix) {
if (ix < listLength - 1) {
list[ix] = list[listLength - 1];
}
--listLength;
}
The second solution is memmove everthing after the to deleting element one to the left:
void deleteElem(Data[] list, int & listLength, int ix) {
memmove(list[ix], list[ix + 1], (listLength - ix - 1) * sizeof(Data));
--listLength;
}
EDIT: There was an error in the length for memmove, always the same. You should read the documentation.

Trying to delete pointers triggers breakpoints

The purpose of the program that I'm working on is creating a class to "improve" the default integer array data type by simulating a dynamic array of pointers. I keep running into errors when trying to delete pointers and arrays of pointers where it says "Windows has triggered a breakpoint in project4.exe.
This may be due to a corruption of the heap, which indicates a bug in project4.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while project4.exe has focus.
The output window may have more diagnostic information."
class Array
{
private:
int length;
int* data;
public:
Array();
Array(const Array &cpy);
~Array();
bool addint(int toadd);
bool deletelast();
int getlength();
friend ostream& operator<<(ostream &out, const Array &n);
};
ostream& operator<<(ostream &out, const Array &n);
Array::Array()
{
length = -1;
data = NULL;
}
Array::Array(const Array &cpy)
{
length = cpy.length; //value of length is copied
if (length < 0)
data = NULL;
else
{
data = new int [length];
for (int i=0; i<=length; i++)
data[i] = cpy.data[i];
}
}
Array::~Array()
{
if (length != 0)
delete [] data;
else
delete data;
data = NULL;
}
bool Array::addint(int toadd)
{
length ++;
int* point = new int[length];
for (int i=0; i < length; i++)
point[i] = data[i];
point[length] = toadd;
if (length != 0)
delete [] data;
data = point;
point = NULL;
return true;
}
bool Array::deletelast()
{
int* temppoint;
if (length > 0)
temppoint = new int [length-1];
else
temppoint = new int[0];
for (int i=0; i<length; i++)
temppoint[i] = data[i];
if (length == 0)
temppoint[0] = 0;
length --;
delete [] data;
data = temppoint;
temppoint = NULL;
return true;
}
void menu(Array var)
{
int selection=0,
input;
bool success;
Array* arrcpy;
while (selection != 3)
{
if (var.getlength() == -1)
{
cout << "What would you like to demonstrate?" << endl << "1) Add an integer " << endl
<< "2) Exit" << endl << "Enter your selection: ";
cin >> selection;
if (selection == 2)
selection = 4;
}
else
{
cout << endl << "Now what would you like to demonstrate?" << endl << "1) Add an integer " << endl
<< "2) Delete the last entered integer" << endl << "3) Copy constructor" << endl << "4) Exit" << endl << "Enter your selection: ";
cin >> selection;
}
if (selection==1)
{
cout << endl << "The length of the array before adding a new value is: " << var.getlength() + 1 << endl;
cout << "Please enter the integer that you wish to add: ";
cin >> input;
success = var.addint(input);
if (success)
cout << endl << "The data input was a success!" << endl << "The length of the array is now: "
<< var.getlength() + 1 << endl << "The new value of the array is: " << var << endl;
else
cout << endl << "The input failed" << endl;
}
if (selection == 2)
{
cout << endl << "The lenght of the array before the deletion is: " << var.getlength() + 1 << endl
<< "and the value held in the array is: " << var << endl;
success = var.deletelast();
if (success)
cout << endl << "The data deletion was a success!" << endl << "The length of the array is now: "
<< var.getlength() + 1 << endl << "The new value of the array is: " << var << endl;
else
cout << endl << "The deletion failed" << endl;
}
if (selection == 3)
{
cout << endl << "The lenght of the array being copied is: " << var.getlength() + 1 << endl
<< "and the value held in the array is: " << var << endl;
arrcpy=new Array(var);
cout << endl << "The length of the copied array is: " << arrcpy->getlength() +1 << endl
<< "and the value contained in the array is: " << *arrcpy;
delete arrcpy;
}
}
}
This is all of the relevant source code that I have in terms of the issue that I'm having. It's coming up that every instance of the delete operator and the delete [] operator has resulted in this breakpoint error and I'm not sure what I'm doing wrong.
Edit: Rewrote the code to have the value of length default to 0 instead of -1 and everything works now!
I believe the for (int i=0; i<=length; i++) in the copy constructor should contain i<length (less than, not less than or equal to). That's one clear problem.
Also you're passing the bound in the addint() method. The last element in an array is at index [length-1].
int* point = new int[length];
Since your length starts at -1, the first call of this line would be to do new int[0]. Could be the problem.. If you insist on not fixing the semantics of length, you want length+1 here
Unrelated point, you should look at how std::vector does it, instead of reallocating every addition, you should try overallocating and only reallocating if the space is filled.
I understand this is an old thread and I'll admit I haven't read all the comment but on the topic of why it seems to work when lenght is changed to 0 I believe it could be due to a nullptr being given to an array being made of an invalid size and later, trying to delete such pointer would result in the breakpoint.

Loading from a Struct data type and trouble passing that data to another function

I have asked my classmates and they have no clue why this is. The Program is supposed to be a banking program. I initially noticed problems specifically in my function findCustomer. What it is supposed to do is to take in a certain piece of the structure 'account' find if the account number matches up to the input you put in, and then declare it a match.
int findCustomer(account arr[], int customers)
{
int index;
cout << "Account Number?: ";
cin >> index;
for (int i = 0; i <= customers + 1; i++)
if (arr[i].acctNum == index)
{
cout << "You dun good!"; //I put this here to try to figure out what the problem was when it was passing in.
return i;
break;
}
else if (arr[i].acctNum != index)
{
cout << "Account Number (" << index << ") Does Not exist!" << endl;
system("Pause");
system("CLS");
return -1;
}
After that it is supposed to pass into a deposit/withdrawal function (they both act the same with minor differences).
void deposit(account arr[], int customers)
{
char type;
float money;
int i;
i = findCustomer(arr, customers);
cout << i << "At this point" << endl;
if (i = -1)
{
cout << "You dun goofed!"; //again put here as a trigger
// what normally goes here is a return; statement to break the function
}
type = submenu();
cout << "How much would you like to deposit?: ";
cin >> money;
cout << "Number \t Name \t Balance" << endl;
cout << "=========================================" << endl;
if (type = 's')
{ arr[i].sBal += money;
cout << arr[i].acctNum << "\t" << arr[i].name << "\t" << arr[i].sBal;
}
else if (type = 'c')
{ arr[i].cBal += money;
cout << arr[i].acctNum << "\t" << arr[i].name << "\t" << arr[i].cBal;
}
}
The output I am getting suggests that there is a change from 0 to -1 right in the middle of the function without any declaration to do so (leaving me with a giant wth over my head) which of course dorks the entire function. I also seem to be having problems reading in certain account numbers that have been said to have been loaded in previous functions. Any and all help would be much appreciated.