c++ memory leak on my data structure - c++

So I've graduated from learning C and now learning C++. From what I understand C and C++ are similar in variety of ways so I'm trying to re-write my past C project files into C++. However I keep getting a memory leak when I try to print out my information. Can someone tell me why I am getting a memory leak in my code.
struct.h
typedef struct student_info {
char last[10];
char first[10];
int student_id;
int count_student;
} student;
typedef struct course_info {
char name[10];
int course_id;
int count_course;
student *students;
} course;
typedef struct gradebook_info {
course *courses;
} gradebook;
function.c
void new_course(gradebook *info) {
int i, loop=0;
cout << "Enter Number of Courses " ;
cin >> loop;
for(i=0; i<loop; i++) {
cout << "Enter Course ID ";
cin >> info->courses[info->courses->count_course].course_id;
cout << "Enter Course Name ";
cin >> info->courses[info->courses->count_course].name;
info->courses->count_course++;
}
}
void new_student(gradebook *info) {
int i, loop=0;
cout << "Enter Number of Students " ;
cin >> loop;
for(i=0; i<loop; i++) {
cout << "Enter Student ID ";
cin >> info->courses->students[info->courses->students->count_student].student_id;
cout << "Enter Last Name ";
cin >> info->courses->students[info->courses->students->count_student].last;
cout << "Enter First Name ";
cin >> info->courses->students[info->courses->students->count_student].first;
info->courses->students->count_student++;
}
}
void printCourse(gradebook *info) {
int i;
cout << "Course ID\tCourse Name\t" << endl;
for(i=0; i<info->courses->count_course; i++) {
cout << info->courses[i].course_id << "\t\t";
cout << info->courses[i].name << endl;
}
}
void printStudent(gradebook *info) {
int i;
cout << "Student ID\tLast Name\tFirst Name\t" << endl;
for(i=0; i<info->courses->students->count_student; i++) {
cout << info->courses->students[i].student_id << "\t\t";
cout << info->courses->students[i].last << "\t\t";
cout << info->courses->students[i].first << endl;
}
}
When I run new_course() function it works.
I run my printCourse() function it works.
I run new_student() function it works.
When I run printStudent() function it works.
Then I try to run printCourse() function again and when i=2, I get some information from my struct student.
I can't figure it out. Any help is appreciated.
main.c
gradebook *info = new gradebook; //allocate memory
do {
main_menu();
int option=0;
switch(option) {
case 1: new_course(info);
break;
case 2: new_student(info);
break;
case 3: printCourse(info);
break;
case 4: printStudent(info);
break;
}
}while(option < 13);
delete(info);

You need to allocate the pointers students and course using new.
After getting loop:
students = new student_info* [loop]
and
courses= new course_info* [loop]

You have not only to allocate memory for the gradebook, but also for the courses and the students. For example:
gradebook *info = new gradebook;
info->courses = new course_info[10];
for(int i = 0; i < 10; i++)
info->courses[i]->students = new student_info[10];
Beware, this example limits the number of courses and students per course to 10.
P.S.: Your code might work for one or two iterations if you don't allocate memory for the courses and the students. But in this case you screw up your memory.

Related

program stopped working when I'm trying to input [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm working on a project, to create a linked list in class but I can't even start working on it because every time I run the program it's will stop working when I want to input data.
Can someone tell me how to input data properly using class? and if possible please let me know how to improve this program. The code that I've done is quite long.
I'll try to make it short and simple for you guys to understand. A lot of people been suggesting me to use std::string but our lecturer never mentioned about it so we have no idea how to use it.
If I have to use it that means I have to start learn it from the beginning which means it will take time for me to really understand it.
We're also required to have a function where we can update the data stored, search the data based on one of its data and make a summary for it.
#include <iostream>
#include <stdlib.h>
#include <cstdlib>
#include <conio.h>
#include <stdio.h>
#include <string>
using namespace std;
//CLASS USED IN PROGRAM
class carInsurance
{
private:
int total;
int customerNo;
string name;
string iCno;
char dob[10];
string nationality;
string address;
char phoneNo[15];
string email;
string occupation;
char carNo[10];
char expireDate[11];
float insuranceAmount;
char carUsage[30];
char manufacturingDate[11];
int package;
int option;
int additional;
int noCustomer[10];
public:
void add();
void presetdata();
static void deleteFunc(carInsurance noCustomer[]);
static void viewAll(carInsurance noCustomer[]);
//constructor name has to be the same as class
carInsurance(int carInsurance_total,
int carInsurance_customerNo,
string carInsurance_name,
string carInsurance_iCno,
char carInsurance_dob[10],
string carInsurance_nationality,
string carInsurance_address,
char carInsurance_phoneNo[15],
string carInsurance_email,
string carInsurance_occupation,
char carInsurance_carNo[10],
char carInsurance_expireDate[11],
float carInsurance_insuranceAmount,
char carInsurance_carUsage[30],
char carInsurance_manufacturingDate[11],
int carInsurance_package,
int carInsurance_option,
int carInsurance_additional)
{
total = carInsurance_total;
customerNo = carInsurance_customerNo;
name = carInsurance_name;
iCno = carInsurance_iCno;
dob[10] = carInsurance_dob[10];
nationality = carInsurance_nationality;
address = carInsurance_address;
phoneNo[15] = carInsurance_phoneNo[15];
email = carInsurance_email;
occupation = carInsurance_occupation;
carNo[10] = carInsurance_carNo[10];
expireDate[11] = carInsurance_expireDate[11];
insuranceAmount = carInsurance_insuranceAmount;
carUsage[30] = carInsurance_carUsage[30];
manufacturingDate[11] = carInsurance_manufacturingDate[11];
package = carInsurance_package;
option = carInsurance_option;
additional = carInsurance_additional;
} // end of constructor
carInsurance()
{ // Set all variables to null
total = 0;
customerNo = 0;
name = " ";
iCno = " ";
dob[10] = '\0';
nationality = " ";
address = " ";
phoneNo[15] = '\0';
email = " ";
occupation = " ";
carNo[10] = '\0';
expireDate[11] = '\0';
insuranceAmount = 0;
carUsage[30] = '\0';
manufacturingDate[11] = '\0';
package = 0;
option = 0;
additional = 0;
}
// SET
void setChar(char carInsurance_dob[10],
char carInsurance_phoneNo[15],
char carInsurance_carNo[10],
char carInsurance_expireDate[10],
char carInsurance_carUsage[30],
char carInsurance_manufacturingDate[10])
{dob[10] = carInsurance_dob[10];
phoneNo[15] = carInsurance_phoneNo[15];
carNo[10] = carInsurance_carNo[10];
expireDate[11] = carInsurance_expireDate[11];
carUsage[30] = carInsurance_carUsage[30];
manufacturingDate[11] = carInsurance_manufacturingDate[11];}
void setname(string carInsurance_name){name = carInsurance_name;}
void setiCno(string carInsurance_iCno){iCno = carInsurance_iCno;}
void setAddress(string carInsurance_address){address = carInsurance_address;}
void setString(string carInsurance_nationality, string carInsurance_email,string carInsurance_occupation)
{nationality = carInsurance_nationality; email = carInsurance_email; occupation = carInsurance_occupation;}
void setInt(int carInsurance_total, int carInsurance_customerNo, int carInsurance_package, int carInsurance_option, int carInsurance_additional)
{customerNo = carInsurance_customerNo; package = carInsurance_package; option = carInsurance_option; additional = carInsurance_additional;}
void setFloat (float carInsurance_insuranceAmount){insuranceAmount = carInsurance_insuranceAmount;}
// GET
string getname(){return name;}
string getiCno(){return iCno;}
string getaddress(){return address;}
string getString(){return nationality; return email; return occupation;}
int getInt(){return total; return customerNo; return package; return option; return additional;}
float getFloat(){return insuranceAmount;}
}; //end class
Here goes my main:
//function declaration
//to prevent overload run function outside
void add();
//THE MAIN FUNCTION OF PROGRAM
int main()
{
carInsurance obj; // obj is class object
carInsurance *noCustomer[10];
int choice;
while(choice != 4)
{
cout << "1. ADD, UPDATE, DELETE\n" << "2. SEARCH\n" << "3. VIEW ALL\n" << "4. SUMMARY REPORT\n" << "5. EXIT\n" << endl;
cout << "Enter your choice: ";
cin >> choice;
system("cls");
switch(choice)
{
case 1:
{
cout << "___________________________________\n";
cout << "\n\tADD/UPDATE/DELETE\n";
cout << "___________________________________\n";
cout << "\n1. ADD\n2. UPDATE\n3. DELETE\n" << endl;
cin >> choice;
system("cls");
switch(choice)
{
case 1:
{
int i;
int total = 0;
cout << "How many customer? ";
cin >> total;
for(i=0; i<total; ++i)
{
cout << "________________________________\n";
cout << "\n\tCUSTOMER NO. " << 1 + i;
cout << "\n________________________________\n";
noCustomer[i]->add(); // this is function call to input
}
break;
}
case 2:
{
int paymentID;
//cout << "UPDATE" << endl;
cout << "\nEnter the customer ID that you want to update:";
cin >> paymentID;
// function here
break;
}
case 3:
{
int paymentID;
//cout << "DELETE" << endl;
cout << "\nEnter the customer ID that you want to delete:";
cin >> paymentID;
noCustomer[10]->deleteFunc(noCustomer[10]);
break;
}
} // End of switch case for add,update,delete
system("cls");
break;
} // End of case 1
case 2:
{
cout << "___________________________\n";
cout << "\n\t SEARCH\n";
cout << "___________________________\n";
system("pause");
system("cls");
break;
}
case 3:
{ cout << "___________________________\n";
cout << "\n\tVIEW ALL\n";
cout << "___________________________\n";
obj.presetdata();
noCustomer[10]->viewAll(noCustomer[10]);
cout<<"\n";
system("pause");
system("cls");
break;
}
case 4:
{
cout << "___________________________\n";
cout << "\n\tSUMMARY REPORT\n";
cout << "___________________________\n\n";
cout << "1. Sorted by different month\n2. Sorted by different car type\n3. Sorted by different insurance" << endl;
cin >> choice;
switch(choice)
{
case 1:
{
break;
}
case 2:
{
break;
}
case 3:
{
break;
}
default:
cout << "Wrong input! Please choose again: ";
cin >> choice;
system("pause");
}
break;
}
case 5:{
cout << "___________________________\n";
cout << "\n\tTHANK YOU!\t\n";
cout << "___________________________";
exit(0); }
default:
continue;
}// End of switch case
}// End of while
return 0; //indicates success
}//End of main
I see a problem in the inner switch statement:
case 1:
{
int i;
int total = 0;
cout << "How many customer? ";
cin >> total;
for(i=0; i<total; ++i)
{
cout << "________________________________\n";
cout << "\n\tCUSTOMER NO. " << 1 + i;
cout << "\n________________________________\n";
noCustomer[i]->add(); // this is function call to input
break;
}
}
case 2:
The break operator breaks the loop, but does not prevent executing case 2: branch.
Yet another problem: re-assignment of choice. User may input 4 in any input request that will break while (choice != 4) unexpectedly. You can avoid troubles with break and re-assignments by using functions.
There is a lot of out of array bounds access by indexes that are equal to array sizes.
It is not clear what you want to reach in dob[10] = carInsurance_dob[10]; It copies 11th char. Maybe you want to copy the whole char array. Use std::string for error-free code.

C++ swap function with array of records

I have just started to learn C++ and have been working on a few problems to hone my skills. Currently I am having a problem swapping some values of my array of records. The input validation works fine but then when I try to swap the values around the program stops responding and crashes. Here is how I have created it:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int grandprixnum;
struct DriverData {
string driver;
int car;
string team;
int grid;
int points;
};
DriverData * grand = new DriverData[grandprixnum];
int input()
{
cout << "How many drivers where there? ";
cin >> grandprixnum;
cin.sync();
DriverData * grand = new DriverData[grandprixnum];
for (int i=0; i<grandprixnum; i++)
{
cout << "Driver numbers: "<< i+1 << " \n";
cout << "What is the drivers name? \n";
getline (cin, grand[i].driver);
cin.sync();
cout << "What is the drivers car number? \n";
cin >> grand[i].car;
while (grand[i].car > 99 || grand[i].car < 1)
{
cout << "Please enter a value between 1 and 99! \n";
cin >> grand[i].car;
}
cin.sync();
cout << "What team is the driver racing for? \n";
getline (cin, grand[i].team);
cin.sync();
cout << "What grid are they in? \n";
cin >> grand[i].grid;
cin.sync();
while (grand[i].grid < 0 || grand[i].grid > 22)
{
cout << "Please enter a grid number between 1 and 22! \n";
cin >> grand[i].grid;
}
cin.sync();
cout << "What are their total points? \n";
cin >> grand[i].points;
cin.sync();
while (grand[i].points > 25 || grand[i].points < 0)
{
cout << "Please enter the drivers points between 0 and 25! \n";
cin >> grand[i].points;
}
}
}
int sorting ()
//This part _______________________________
{
for(int a=1; a<=grandprixnum; a++)
{
for(int b=0; b<=grandprixnum; b++)
{
if(grand[b].points < grand[b+1].points)
{
swap(grand[b].driver, grand[b+1].driver);
swap(grand[b].car, grand[b+1].car);
swap(grand[b].team, grand[b+1].team);
swap(grand[b].grid, grand[b+1].grid);
swap(grand[b].points, grand[b+1].points);
}
}
}
}
//To here_________________________________
int showtable ()
{
cout << "Driver Car Team Grid Points \n";
for(int c=0; c<grandprixnum; c++)
{
cout << grand[c].driver << grand[c].car << grand[c].team << grand[c].grid << grand[c].points << "\n";
}
}
int main()
{
input ();
sorting ();
showtable ();
}
I have looked around and cannot find an example or someone having the same problem as me. If someone could show me what is wrong with it. Thank you in advance.
EDIT: I have tested the swap before and it does work but it seems to struggle with the array of records.
You access to your array out of bounds. Your array has a length of grandprixnum so you can access to elments from 0 to grandprixnum-1
for(int a=1; a < grandprixnum; a++)
// ^
{
for(int b=0; b < grandprixnum-1; b++)
// ^ ^^ -1 because of b+1
{
if(grand[b].points < grand[b+1].points)
{
...
}
}
}
If ter is nothing to return in a function you dont need a return type. Use void sorting(), void input(), void showtable()
You declareted your array grand twice. On time global and second time local in function input. Declare it global and allocate it in function input.
DriverData * grand = NULL;
int input()
{
...
grand = new DriverData[grandprixnum];
Remove equal sign from this line:
for(int b=0; b<=grandprixnum; b++)
So it will be like this:
for(int b=0; b<grandprixnum; b++)
And replace this line
DriverData * grand = new DriverData[grandprixnum];
with
grand = new DriverData[grandprixnum]; // will store in global variable

printing name in multiple for loops and arrays

I've come across a little problem, how do I print the winning candidate's name? See the instructions here are, input five names, their number of votes and percentage of votes, whoever has the highest wins. I don't know if I did my code right, but it works.. well except for the name part. I've tried everything from a lot of for loops to transfer the array or what.
I'm almost done with the code.
Here's the code
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
char candidates[50];
int votes[5]={0};
float percent[5]={0};
int a,b,c,d,e,i;
int maxx;
int champ=0;
char winner[50];
cout << "Enter the candidates' last names: ";
cout << endl;
for(a=1;a<=5;a++)
{
cout << a << ". ";
cin >> candidates;
}
cout << endl;
cout << "Enter their number of votes: " << endl;
for(b=1;b<=5;b++)
{
cout << b << ". ";
cin >> votes[b];
}
cout << endl;
cout << "percentage of votes: " << endl;
for(c=1;c<=5;c++)
{
cout << c << ". ";
percent[c]=votes[c]*0.2;
printf("%.2f\n", percent[c]);
}
cout <<"Candidates\t\tVotes\t\t% of Votes" << endl;
for(int k=1;k<=5;k++)
{
cout << candidates[k] << "\t\t\t" << votes[k] << "\t\t\t";
printf("%.2f\n", percent[k]);
}
maxx=percent[0];
for(d=1;d<=5;d++)
{
if(maxx<percent[d]);
{
//what happens here?
}
}
return 0;
}
You should keep a 2d array of characters or array of string for storing candidate names instead of a 1-d array.
char candidates[5][10]; //
for(int i = 0; i < 5; i++)
{
cin >> candidates[i];
}
Then keep a variable to store index for winning candidate
int winIndex = 0;
int winPercent = 0;
for(int i = 0; i < 5; i++)
{
if(percent[i] > winPercent)
{
winPercent = percent;
winIndex = i;
}
}
Finally print name of winning candidate;
cout << candidates[winIndex];
In object oriented approach, you may create a class with following information
class Candidate
{
string name;
int votes;
float percent;
};
Use string candidates[50]; instead of char candidates[50];
then cin >> candidates[a];

i need to create array on the heap aby to hold a specific number set by the user

hey guys new to this site looking some help for my final project i having to create a project that takes car data saves it to the heap and has a bunch of error checking not all the way done but getting there. but i cant grasp the heap and how to input it correctly into my code here is what i have. and it has to be under 175 lines and i still have to have it ask user if they want to write to a new file or existing. thanks ahead once again question is how do i create array on the heap able to hold the number of vech specified buy user.
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
class carData4
{
public:
void setYear(int& year);
void setMake(string make);
void setModel(string);
void setMileage(int& mileage);
void setName(string name);
void setNumber(string number);
int getYear(){ return itsYear; }
string getMake(){ return itsMake; }
string getModel(){ return itsModel; }
int getMileage(){ return itsMileage; }
string getName(){ return itsName; }
string getNumber(){ return itsNumber; }
private:;
int itsYear;
string itsMake;
string itsModel;
int itsMileage;
string itsName;
string itsNumber;
};
void carData4::setYear(int & year)
{
do
{
cout << "Enter the cars Year from 1910 and 2014:\n ";
cin >> year;
itsYear = year;
if (year < 1910 || year > 2014)
cout << "INVALID! please enter a correct year! ";
} while (year < 1910 || year > 2014);
}
void carData4::setMake(string make)
{
cout << "Enter the cars make:\n\n";
cin >> make;
itsMake = make;
}
void carData4::setModel(string model)
{
cout << "Enter the cars model:\n\n";
cin >> model;
itsModel = model;
}
void carData4::setMileage(int & mileage)
{
do{
cout << "Enter the cars mileage:\n\n";
cin >> mileage;
itsMileage = mileage;
}
while (mileage <0 || mileage >10000000);
cout << "NOPE enter within 0 and million miles.\n\n";
cin >> mileage;
itsMileage = mileage;
}
void carData4::setName(string name)
{
cout << "Enter your name :";
cin >> name;
itsName = name;
}
void carData4::setNumber(string number)
{
cout << "Enter Your phone number (XXX)XXX-XXXX:";
cin >> number;
itsNumber = number;
}
int main()
{
carData4 car1;
int year, mileage, numCars, ;
string make, model, name, number;
cout << "How many vehicles are to be added to inventory?.\n\n";
cin >> numCars;
for (int i = 1; i < numCars; i++){
car1.setYear(year);
car1.setMake(make);
car1.setModel(model);
car1.setMileage(mileage);
car1.setName(name);
car1.setNumber(number);
cout << car1.getYear() << "\t" << car1.getMake() << "\t " << car1.getModel()
<< "\t" << car1.getMileage() << "\t " << car1.getName() << "\t " << car1.getNumber() << endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
i add some is this correct????????????????
int main()
{
carData4 car1; // *car1=new carData4[numCars];
int year,mileage,numCars;
double *cars;
string make,model,name,number;
cout << "How many vehicles are to be added to inventory?.\n\n";
cin >>numCars;
cars = new double [numCars];
for (int i=1; i<numCars;i++){
car1.setYear(year);
car1.setMake(make);
car1.setModel(model);
car1.setMileage(mileage);
car1.setName(name);
car1.setNumber(number);
cout << car1.getYear() << "\t" << car1.getMake() << "\t " << car1.getModel()
<< "\t" << car1.getMileage() << "\t " << car1.getName() << "\t " << car1.getNumber() <<endl;
delete [] cars;
}
system("PAUSE");
return EXIT_SUCCESS;
}
The best way to have dynamic storage for your use case would be to use a vector, like so:
std::cout << "How many vehicles are to be added to inventory?.\n\n";
std::size_t n;
std::cin >> n;
std::vector<carData4> cars ( n );
//gives you:
//cars[0] ... cars[ n-1 ]
http://en.cppreference.com/w/cpp/container/vector
To dynamically allocate an array based on user input:
unsigned int array_capacity;
cout << "Enter array capacity: ";
cin >> array_capacity;
int * my_array = new int[array_capacity];
Remember to delete the array using delete [] my_array;.
Edit 1: using Car class
CarData4 * my_cars = new CarData4[numCars];

How to use a dynamically sized array of structs?

I have to make my homework. It is console application which uses an array of structs that keep information about a computer(brand, year of manufactoring, weight and inventory number). So I wrote a completely working program, but I want to use a dynamic array, because I dont know how many records the user will input.
Is there way to do this. To add new records in array until the user say n/N? Any suggestions?
This is my version of program:
#include "stdafx.h"
#include <iostream>
using namespace std;
struct ComputerInfo
{
char computerMark[20], invertarNumber[6];
unsigned int year;
float weight;
};
ComputerInfo computerArray[300];
ComputerInfo AddComputers(ComputerInfo compterArray[], int counter)
{
cout << "Enter mark of the computer: ";
cin >> computerArray[counter].computerMark;
cout << "Enter year of establish: ";
cin>> computerArray[counter].year;
while ((computerArray[counter].year < 1973)
|| (computerArray[counter].year > 2013))
{
cout << "INVALID YEAR!!!" << endl;
cout << "Enter year of establish: ";
cin>> computerArray[counter].year;
}
cout << "Enter computer weidth: ";
cin >> computerArray[counter].weight;
cout << "Enter computer invertar number(up to six digits): ";
cin >> computerArray[counter].invertarNumber;
return computerArray[counter];
}
void ShowRecords()
{
int counter = 0;
while (computerArray[counter].year != 0)
{
cout << "Mark: " << computerArray[counter].computerMark << endl;
cout << "Year: " << computerArray[counter].year << endl;
cout << "Weidth: " << computerArray[counter].weight << endl;
cout << "Inv. number: " << computerArray[counter].invertarNumber << endl << endl;
counter++;
}
}
void MoreThanTenYearsOld(ComputerInfo computerArray[])
{
int counter = 0;
float counterOldComputers = 0;
float computerPer = 0;
while (computerArray[counter].year == 0)
{
if (computerArray[counter].year <= 2003)
{
counterOldComputers++;
}
counter++;
}
computerPer = counterOldComputers / 3;
cout << endl;
cout << "Percantage of old computers is: " << computerPer << endl;
}
int main()
{
int counter = 0;
float computerPer = 0;
char answer = 'y';
for (int i = 0; i <= 299; i++)
{
strcpy(computerArray[i].computerMark,"");
}
while((answer == 'Y') || (answer == 'y'))
{
computerArray[counter] = AddComputers(computerArray, counter);
cout << endl;
cout << "Do you want to enter more records (Y/N): ";
cin >> answer;
cout << endl;
counter++;
}
MoreThanTenYearsOld(computerArray);
return 0;
}
Yes. Instead of your array, use
std::vector<ComputerInfo> computerArray;
and you can add as many objects as you want:
ComputerInfo c;
// read the data
computerArray.push_back(c);
now, computerArray[0] will have the info in c.
You'll need to #include <vector>.
Also, instead of char computerMark[20] you can use a std::string.
You have two options:
1) Use std::vector instead of an array. This is a very powerful tool and certainly worth learning how to use.
2) Dynamically allocate the array and resize it as you add more items. Basically this means writing your own version of std::vector. This is a good way to strengthen your programming skills. You will learn what goes into writing standard classes and functions. However, I advise using std::vector in more serious programming because it has already been thoroughly tested and debugged.