Function with structure as argument producing error: free(): invalid pointer: 0x00007efd47b - c++

I've made an addDepartment function that takes a structure as an argument. When I enter input to initialize the "dept[counter].departmentHead" at the bottom of the function, it triggers the error message.
I'm copying the logic from another code I wrote using classes instead of structures and that one works fine so I'm really not sure why this one isn't working. Tried messing with the index to make sure I wasn't going over the size of the array but that doesn't seem to fix the issue.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>
using namespace std;
struct Department{
string departmentName;
string departmentHead;
int departmentID;
double departmentSalary;
};
//...
Department addDepartment(Department dept[3]){
int repeat=0;
int counter=0;
if (counter>2){
cout<<"The array is full, you can not add any more Departments."<<endl;
}
else{
cout << "Please Enter Department Details:"<<endl;
cout << "Department ID : ";
cin >> dept[counter].departmentID;
for(int x=0; x<3; x++){
for (int y=x+1; y<3; y++){
if(dept[x].departmentID==dept[y].departmentID)
repeat++;
}
}
if(repeat!=0)
cout<<"Value must be unique!"<<endl;
else{
cout << "Department Name : ";
cin >> dept[counter].departmentName;
cout << "Head of Department : ";
cin >> dept[counter].departmentHead;
counter++;
}
}
}
//...
int main()
{
Employee emp[5];
Department dept[3];
initialID(emp,dept,0);
initialID(emp,dept,1);
int response;
while(response!=6){
displayMenu();
cout<< "Please make a selection : \n";
cin >> response;
while((response!=1)&&(response!=2)&&(response!=3)&&(response!=4)&&(response!=5)&&(response!=6)){
cout<< "Please enter a valid choice (1 - 6): ";
cin >> response;
}
if(response==1){
addDepartment(dept);
}
else if(response==2){
//addEmployee(emp,dept);
}
else if(response==3){
}
else if(response==4){
}
else if(response==5){
//salaryReport(dept);
}
}
cout << "Thank you, goodbye.";
}

Why it breaks.
The addDepartment function never actually returns a department. When the function exits, the space where the return newly created Department would be is left uninitialized. This causes undefined behavior. The compiler tries to destruct the Department object like it normally would, but because it was never initialized, free gets called on garbage (causing the error).
We can fix this by adding a line to addDepartment returning the actual department:
Department addDepartment(Department dept[3]){
int repeat=0;
int counter=0;
if (counter>2){
cout<<"The array is full, you can not add any more Departments."<<endl;
}
else{
cout << "Please Enter Department Details:"<<endl;
cout << "Department ID : ";
cin >> dept[counter].departmentID;
for(int x=0; x<3; x++){
for (int y=x+1; y<3; y++){
if(dept[x].departmentID==dept[y].departmentID)
repeat++;
}
}
if(repeat!=0)
cout<<"Value must be unique!"<<endl;
else{
cout << "Department Name : ";
cin >> dept[counter].departmentName;
cout << "Head of Department : ";
cin >> dept[counter].departmentHead;
counter++;
}
}
return /* some department */;
}
Alternatively, you could make addDepartment void.
Other considerations. Don't pass raw C arrays to functions. It doesn't do what you intend.
If you want to pass a copy of an array, pass a std::array, which will be copied automatically:
Department addDepartment(std::array<Department, 3> dept);
If want to access the elements of an existing array, pass a pointer:
Department addDepartment(Department* dept, int count);

One problem that I see is that you are creating an array of 3 Department objects in main and assuming that you have 5 elements in initialID.
Change main to create an array of 5 Department objects.
int main()
{
Employee emp[5];
Department dept[5];
...

Related

if else problem salary formula for loop desire loop user input

asking desire number to become the for loop(how many employee if input is 4 then 4 loop if 3 3 loops), salary formula not working, if else statement for string name to not accept number and vice versa integer to not accept letters. another one of my problem is how can I name the loop for example the question is name hours and rate then the cout should do 1. name hours rate, 2.name hours rate 3.name hours rate... the code is working.. just need some imporvements.
#include <iostream>
#include <cstdlib>
using namespace std;
void displayRules()
{
cout<<"====================="<<endl;
cout<<" EMPLOYEE-SALARY "<<endl;
cout<<"====================="<<endl;
cout<<" "<<endl;
}
int main()
{
char ans;
do
{
system("cls");
displayRules();
struct Employee
{
string name;
double hours;
double rate;
double salary;
Employee *next;
Employee *prev;
};
Employee *head;
head=NULL;
Employee *newEmployee;
Employee *EmpPointer;
Employee *nextEmpPointer;
Employee *prevEmpPointer;
string inpname;
int inpN;
double inphours;
double inprate;
double salary;
salary = (inprate*inphours);
for(int ctr=0; ctr<3; ctr++)
{
cout<<endl;
cout<<"Enter Name: \t\t";
cin>> inpname;
cout<<"Enter # Hours Worked: \t";
cin>> inphours;
if (inphours<0)
{
cout << "Invalid Input! Program Stopped. ";
return 0;
}
cout<<"Enter Rate per Hour: \t";
cin>> inprate;
if (inprate<0)
{
cout << "Invalid Input! Program Stopped. ";
return 0;
}
newEmployee = new Employee;
newEmployee->name=inpname;
newEmployee->hours=inphours;
newEmployee->rate=inprate;
newEmployee->next=NULL;
if (head==NULL)
head=newEmployee;
else
{
EmpPointer=head;
while (EmpPointer->next)
EmpPointer=EmpPointer->next;
EmpPointer->next=newEmployee;
}
}
cout<<endl;
Employee *displayPointer;
displayPointer=head;
system("cls");
cout<<"------------------------------------------------------------"<<endl;
cout<<" =Summary of PAYROLL= "<<endl;
cout<<"------------------------------------------------------------"<<endl;\
cout<<"Employee Name\t"<<"# Hours Worked\t"<<"Rate/Hour\t"<<"Salary\t"<<endl;
while (displayPointer)
{
cout<<displayPointer->name<<"\t\t";
cout<<displayPointer->hours<<"\t\t";
cout<<displayPointer->rate<<"\t\t";
cout<<displayPointer->salary<<endl;
displayPointer=displayPointer->next;
}
cout<<"------------------------------------------------------------"<<endl;
cout<<endl;
cout << "Would you like to run the program again? (Y/N) ";
cin>>ans;
}
while (ans == 'y' or ans == 'Y');
return 0;
}
Note: The salary wasn't being calculated so I fix that.
I broke your code into small functions in which each function only does one thing and one thing only (Single Responsibility Principle).
Also, I introduce function templates that allows you to reuse a function when you provide the type.
Finally, the code is missing a clean up of pointers to prevent memory leaks. Each time you use the keyword new to obtain a pointer to memory, you need later to check if the pointer contains null and if doesn't then use the keyword delete to free that memory, else you end with memory leaks in your code. Therefore, I leave you with the task to write the function that should iterate your employee list and free the memory to prevent memory leaks.
I hope this is useful.
#include <iostream>
#include <cstdlib>
using namespace std;
struct Employee {
string name;
double hours;
double rate;
double salary;
Employee *next;
Employee *prev;
};
void displayRules() {
cout<<"====================="<<endl;
cout<<" EMPLOYEE-SALARY "<<endl;
cout<<"====================="<<endl;
cout<<" "<<endl;
}
// Here we create a function template to make this code more reusable
template <typename T>
T consoleInput(const std::string& prompt) {
T value;
std::cout << prompt;
std::cin >> value;
return value;
}
// Lets create our own assert to exit the app.
void assertGreaterEqualThanZero(const double value, const std::string& prompt){
if (value < 0) {
cout << prompt;
exit(1);
}
}
// Small functions that do one thing only makes coding easy to debug
Employee* createEmployee(string name, int hours, int rate) {
Employee *newEmployee = new Employee;
newEmployee->name=name;
newEmployee->hours=hours;
newEmployee->rate=rate;
newEmployee->salary = (rate * hours);
newEmployee->next=NULL;
// You need to set and maintain ->prev
// if you are thinking on using a double linked list
// else remove it from the structure since is unused.
return newEmployee;
}
// This is a helper function to add new employees to a list
Employee* addToEmployeeList(Employee* list, Employee* newEmployee){
if (list==NULL) {
list = newEmployee;
} else {
Employee *EmpPointer = list;
while (EmpPointer->next)
EmpPointer=EmpPointer->next;
EmpPointer->next=newEmployee;
}
return list;
}
// The only purpose of this function is to print the list provided
void printEmployeList(Employee* employeeList){
Employee *currentEmployee = employeeList;
system("cls");
cout<<"------------------------------------------------------------"<<endl;
cout<<" =Summary of PAYROLL= "<<endl;
cout<<"------------------------------------------------------------"<<endl;
while (currentEmployee){
cout<<"Employee Name\t"<<"# Hours Worked\t"<<"Rate/Hour\t"<<"Salary\t"<<endl;
cout<<currentEmployee->name<<"\t\t";
cout<<currentEmployee->hours<<"\t\t";
cout<<currentEmployee->rate<<"\t\t";
cout<<currentEmployee->salary<<endl;
cout<<"------------------------------------------------------------"<<endl;
currentEmployee=currentEmployee->next;
}
}
// I leave you with this piece that is missing.
// TODO: create function that delete each employee in the list,
// then deletes the list in order to prevent memory leaks
int main() {
char ans;
do {
system("cls");
displayRules();
Employee *employeeList;
employeeList=NULL;
for(int ctr=0; ctr<3; ++ctr) {
// Lets declare and instantiate when we need it.
string name = consoleInput<string>("Enter Name: \t\t");
// No need to use inp (as inphours) in front of your variables
// It makes it harder to read. Just put hours as a name.
double hours = consoleInput<double>("Enter # Hours Worked: \t");
assertGreaterEqualThanZero(hours, "Invalid Input! Program Stopped.");
double rate = consoleInput<double>("Enter Rate per Hour: \t");
assertGreaterEqualThanZero(rate, "Invalid Input! Program Stopped. ");
Employee *newEmployee = createEmployee(name, hours, rate);
employeeList = addToEmployeeList(employeeList, newEmployee);
}
cout << endl;
printEmployeList(employeeList);
cout << "Would you like to run the program again? (Y/N) ";
cin>>ans;
} while (ans == 'y' or ans == 'Y');
return 0;
}

What is wrong with the for loop that is trying to get input from user?

What is wrong with the for loop that is getting cname and camount from the user.
Here is my input:
size = 3
Name = "Asha R"
It throws me out of the loop and exits the program. I should be able to enter 3 names and 3 amounts based on the size I entered in the first statement.
I've tried to change the cin statements several different ways, but nothing is working. Your help is much appreciated:
#include <iostream>
#include <string>
using namespace std;
struct contribution {
string cname;
double camount = 0.0;
};
int main ()
{
int size = 0;
//get array size from user
cout << "How many members do you want to enter" << endl;
cin >> size;
//create dynamic array of contribution structure
contribution * conarr = new contribution[size];
//This is my problem area. When I enter the 1st loop and enter "Asha R" it kicks out of the loop. I tried to change the cin statements several different ways, but it's not working.
for (int i=0; i < size; i++)
{
cout << "Enter name: " ;
//getline(cin, conarr[i].cname);
getline(cin,conarr[i].cname).get();
cout << "Enter contribution amount: ";
// cin >> conarr[i].camount;
(cin >> conarr[i].camount).get();
}
delete[] conarr;
}

Looping if user input invalid

I want to create a program that when a user inputs something that I didn't define, the program prompts him again.
I did it with if statements but it only loops for 1 time and doesn't do it again. I tried loops but whenever the input is false it just breaks the condition and refuses all inputs alike. In c++.
Any help is much appreciated.
#include <iostream>
#include <string>
using namespace std;
void xD(){string x;
do{cout << "Retry\n";
cin >> x;}while(true);}
//declaring a function to make the shop
void shop(){
string x;
float coins = 500;
float bow_cost = 200;
cout << "welcome to the shop\n";
cout << "Bow(bow)costs 150 coins.\n";
cin >> x;
// if u chose bow you get this and get to choose again
if (x == "bow"){
cout << "you bought the bow.\n you now have " <<coins - bow_cost << " coins." << endl; cin >> x;}
/*now the problem that whenever I excute the code and type something other than bow it gives me the cin only once more and then fails even if I type bow in the 2nd attempt*/
//in my desperate 5k attempt, I tried creating a function for it.. no use.
//i want it o keep prompting me for input till i type "bow" and the other block excutes. but it never happens.
else{xD();}
}
int main(){
string name;
string i;
cout << "if you wish to visit the shop type \"shop\"\n";
cin >> i;
if(i == "shop"){shop();}
else{cin >> i;}
return 0;
}
The problem lies on the condition in this loop block
void xD(){
string x;
do{
cout << "Retry\n";
cin >> x;
}while(true);
}
The while(true) condition makes it loops forever regardless of the input. To fix this, you can change the condition:
void xD(){
string x;
do{
cout << "Retry\n";
cin >> x;
}while(x!="bow");
cout << "you bought the bow. and some other messages"<<endl;
}
That should work. However, it is still too complicated for me. This can be simplified into the snippet below:
void shop(){
string x;
float coins = 500;
float bow_cost = 200;
cout << "welcome to the shop\n";
cout << "Bow(bow)costs 150 coins.\n";
cin >> x;
while (x!="bow"){
cout << "Retry\n";
cin>>x;
}
cout << "you bought the bow.\n you now have " <<coins - bow_cost << " coins." << endl; cin >> x;
}
Instead of doing this approach (which is checking the condition only once):
if (x == "bow"){
cout << "you bought the bow.\n you now have " <<coins - bow_cost << "
coins." << endl; cin >> x;
} else{
xD();
}
which is actually a RECURSIVE invocation to the method xD()
you should do a do-while loop,
example:
while (x.compare("bow") != 0)
{
cout << "sorry, wrong input, try again...";
cin >> x;
}
note the use of the compare method instead of the == operator
here more about it in the documentation
You can use return value of cin >> [your input object] here to check status or istream's method fail(). As soon as input stream fails to parse whole or part of streams it fails and stay in state of failure until you clear it. Unparsed input is preserved (so you can try to parse it differently?)m so if you try to >> again to object of same type, you'll get same failure. To ignore N chars of imput, there is method
istream::ignore(streamsize amount, int delim = EOF)
Example:
int getInt()
{
while (1) // Loop until user enters a valid input
{
std::cout << "Enter an int value: ";
long long x; // if we'll use char, cin would assume it is character
// other integral types are fine
std::cin >> x;
// if (! (std::cin >> x))
if (std::cin.fail()) // has a previous extraction failed?
{
// yep, so let's handle the failure, or next >> will try parse same input
std::cout << "Invalid input from user.\n";
std::cin.clear(); // put us back in 'normal' operation mode
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); // and remove the bad input
}
// Thechnically you may do only the above part, but then you can't distingusih invalid format from out of range
else if(( x > std::numeric_limits<int>::max()) ||
( x < std::numeric_limits<int>::min()))
{
std::cout << "Invalid value.\n";
}
else // nope, so return our good x
return x;
}
}
For strings parsing is almost always successful but you'll need some mechanism of comparison of string you have and one that is allowed. Try look for use of std::find() and some container that would contain allowed options, e.g. in form of pair<int,string>, and use int index in switch() statement (or use find_if and switch() within the function you give to it).
Consider that if() statement is a one_direction road, it checks the condition and if the condition was satisfied it goes to its bracket and do blah blah blah , if there is any problem with condition compiler passes ifand jump to compile other codes.
Every time that you begin to compile the codes it begins from int main() function. You did the wrong thing in the if and else statements again
Here is the correct code .I did the necessary changes.
#include "stdafx.h"
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
#define coins 500 ;
#define bow_cost 200 ;
int shop(string x)
{
//There is no need to allocate extra memory for 500 and 200 while they are constant.``
cout << "welcome to the shop\n";
cout << "Bow(bow)costs 150 coins.\n";
do
{
cout << "Input another :\n";
cin >> x;
if (x == "bow")
{
return (coins - bow_cost); //return to function as integer
}
} while (true);
}
int main()
{
string name, i;
cout << "if you wish to visit the shop type \"shop\"\n";
cin >> i;
if (i == "shop")
{
cout << "Input :\n";
cin >> name;
cout << shop(name) << "you bought the bow.\n you now have " << " coins." << "\n";
}
//argument passed to shop funnction parameters.
system("pause");
return 0;
}

strcpy_s unhandled exception?

I'm trying to use strcpy_s, but I'm having this error:
Unhandled Exception...
struct Item {
//Item's
int code; // Code
char* name[20];
int amount; //Amount in stock
int minAmount; //Minimum amount
float price; //Price
};
The important lines are the beginning and the line with the "#########" beside it. (spot = 0, name string was received, store was initialized in main()).
//add an item to store
void addItem(Item* store, int maxItems, int &numItems)
{
if (maxItems == numItems)
{
cout << "ERROR \n";
return;
}
int spot = numItems; // our item's spot in store[]
int code; // inputted code
//Item's attributes' input
cout << "enter code : \n"; //code
cin >> code;
store[spot].code = code; //Code
cout << "enter name : \n"; //Name
_flushall();
char* name = new char[20];
gets_s(name, 20);
numItems++; //forward the number of items
strcpy_s(*store[spot].name, 20, name); //Name UNHANDLED EXCEPTION ############################
cout << "enter amount : \n"; //Amount in stock
do
{
cin >> store[spot].amount;
if (store[spot].amount < 0) //not negative
cout << "ERROR \n";
} while (store[spot].amount < 0);
cout << "enter minimum amount : \n"; //Minimum amount for orders
do
{
cin >> store[spot].minAmount;
if (store[spot].minAmount < 0) //not negative
cout << "ERROR \n";
} while (store[spot].minAmount < 0);
cout << "enter price : \n"; //Price
do
{
cin >> store[spot].price;
if (store[spot].price < 0) //not negative
cout << "ERROR \n";
} while (store[spot].price < 0);
}
I would advice you to test calling strcpy_s and every other suspicious part of the code separately and see it there is any problem, if there is, work around it and then insert it in the addItem function.
From is visible in the posted code, you seem to be passing a pointer variable with the dereference operator in front of it in most of the functions you use, for example the signature of strncpy_s() is:
errno_t strncpy_s(char *restrict dest,
rsize_t destsz,
const char *restrict src,
rsize_t count);
You need to pass the first parameter without the * as it is a pointer: Item* store, i.e. as pass it as: store[spot].name.
Check this article about pointer assignment, which will help you understand how to pass a pointer as an argument to a function.
Edit after a comment
Your second error message could be because the member name of store is not a pointer, you probably need to pass it using & operator, i.e. pass its address:
strcpy_s(&store[spot].name, 20, name);

How to display the name from the array name?

I'm trying to study c++ about array
and I'm having a problem displaying the name from the array name
Because when I try to display the name of the passenger based on where he seat
the first letter becomes the last letter of his name..ahmm
Here's my code
#include <iostream.h>
#include <conio.h>
char* name[10]={" "};
int* seat=0;
char* pname="The Passenger is: ";
char ask;
void display();
int main()
{
clrscr();
cout<<"The Entering of name and seat number..."<<endl;
do
{
cout<<"\nEnter your name: ";
cin>>*name;
cout<<"Enter your seat number: ";
cin>>*seat;
cout<<"Do you want to input again?(Y/N): ";
cin>>ask;
}
while(ask=='y'||ask=='Y');
cout<<"\nDo you want to see the passenger's name?(Y/N): ";
cin>>ask;
if(ask=='y'||ask=='Y')
{
cout<<"\nThe Program will now direct you to the displaying of passenger's name...."<<endl;
display();
}
else
{
cout<<"\n\nThe Program will end shortly....";
}
getch();
return 0;
}
void display()
{
do
{
cout<<"\nEnter seat number to display passenger's name: ";
cin>>*seat;
cout<<pname<<*name[*seat-1]<<endl;
cout<<"Do you want to try again?(Y/N): ";
cin>>ask;
}
while(ask=='y'||ask=='Y');
cout<<"\nThe Program will now end shortly....";
getch();
}
To display the name from the array name you have at first to define the array correctly.:)
If you do not know yet about standard class std::string then the array should be defined as for example
char name[10][20];
that is it can store 10 names that have length no more than 20 characters.
Or if you know about class std:string then you can define it as
#include <string>
std::string name[10];
And it would be even better to define
#include <string>
#include <array>
std::array<std::string, 10> name;
For this program neither pointer is needed to be defined.
Take into account that when you ask to enter a seat number you should check that this number is in the range 1 - 10 (in this case you will need to decrease it by one when will use it to access the array) or 0 - 9.
You seem to be having a problem with pointers. Namely
int* seat=0;
will not allocate space for the integer, but instead allocate space for a pointer and then set this pointer and set it to address 0. When you perform
cin>>*seat;
Your program attempts to dereference the pointer which does not point to anything. Furthermore when you perform
cin >>*name
You are not writing to the whole string but instead writing to the dereference location, namely the first character of the string.
For a start change
int* seat=0;
to
int seat = 0
and
cin>>*name;
to
cin>>name;
good luck!
Edit:
also you want to change the:
cin >> *seat;
to
cin >> seat
Nevertheless you might need some more practice in the basic language features, like pointers, you could use some existing data structures. Since you are using cout and cin i assume your compiler supports the C++ standard library. I would use a map, to save the passengers.
#include <iostream>
#include <map>
struct passenger
{
char name[10];
};
std::map<int, passenger> passengers;
int seat;
char ask;
void display();
int main()
{
std::cout<< "The Entering of name and seat number..." << std::endl;
do
{
passenger p;
std::cout << "\nEnter your name: ";
std::cin >> p.name;
std::cout << "Enter your seat number: ";
std::cin >> seat;
// add passenger to the map
passengers.insert(std::pair<int, passenger>(seat, p));
std::cout << "Do you want to input again?(Y/N): ";
std::cin >> ask;
}
while(ask=='y'||ask=='Y');
std::cout << "\nDo you want to see the passenger's name?(Y/N): ";
std::cin >> ask;
if(ask=='y' || ask=='Y')
{
std::cout << "\nThe Program will now direct you to the displaying of passenger's name...." << std::endl;
display();
}
return 0;
}
void display()
{
do
{
std::cout << "\nEnter seat number to display passenger's name: ";
std::cin >> seat;
// check if passenger data is available for this seat
if(passengers.find(seat) != passengers.end()) {
std::cout << "The Passenger is: " << passengers[seat].name << std::endl;
} else {
std::cout << "Seat still available ..." << std::endl;
}
std::cout << "Do you want to try again?(Y/N): ";
std::cin >> ask;
}
while(ask=='y' || ask=='Y');
}
If you are using a pointer *seat you don't have to access it as
cin>>*seat. You only need to write cin>>seat.
While you are learning cpp, check out what pointers are too.
Here's a little info on that too, though that is not exactly the subject matter,
int *S; // pointer of type int
int x; // variable of type int
S = &x; // pointer S is now pointing to memory location of x
S = 4;
OR
x = 4; // changes the contents of memory location to which S points`
cout << *S; // displays the memory address to which S points i.e.
x