Pointer to a structure in an array of structures - c++

So i need to get code of the structure#1 (e[0]) but i get the following error;
"error: request for member 'get_code' in 'emp1', which is of pointer type 'Employee*' (maybe you meant to use '->' ?)"
i don't really understand how to fix this. Plus, it's an assigment so i'm bound to use structures,and also, i don't know what "->" is, but if it's any operator or something, im not allowed to use it cause we haven't been taught that yet.
(Answers to the similar question suggest using -> so that doesnt work for me.)
i also tried using *(emp1).get_code()
#include <iostream>
#include <string.h>
using namespace std;
struct Employee{
private:
string code;
string name;
float salary;
public:
void set_code(string c){
code=c;
}
void set_name(string n){
name=n;
}
void set_sal(float s){
salary=s;
}
string get_code(){
return code;
}
string get_name(){
return name;
}
float get_sal(){
return salary;
}
};
int main(void) {
Employee e[2],*emp1,*emp2;
string c,n;
float s;
for (int i=0;i<2;i++){
cout<<"Enter code for employee "<<i+1;
cin>>c;
e[i].set_code(c);
cout<<"Enter name for employee "<<i+1;
cin>>n;
e[i].set_name(n);
cout<<"Enter salary for employee "<<i+1;
cin>>s;
e[i].set_sal(s);
}
*emp1=e[0];
cout<<emp1.get_code();
}

First of all, this line is not correct:
*emp1=e[0];
What your line does is assign the structure value 'e[0]' to the structure at pointer 'emp1'. However, the pointer 'emp1' is never initialized, so you'd end up writing in an invalid location.
What you need to write is:
emp1=&e[0];
That will actually set emp1 to the location of 'e[0]'.
Secondly, the symbol '->' is what you use when you want to access a member of a pointer.
In this case you should not write:
cout<<emp1.get_code();
But rather:
cout<<emp1->get_code();
The reason why you need to write that is that 'emp1' is a pointer. Thus, to access its member 'get_code', you need to use the symbol '->'.

Related

error: "gets" not declare in thi cope on codeblock 10.0

#include<iostream>
using namespace std;
class student
{
private:
int admno;
char sname[20];
float eng,math,science;
float total;
float ctotal()
{
return eng+math+science;
}
public:
void Takedata()
{
cout<<"Enter admission number ";
cin>> admno;
cout<<"Enter student name " ;
gets(sname);// here its giving the error
cout<< "Enter marks in english, math, science ";
cin>>eng>>math>>science;
total=ctotal();
};
void Showdata()
{
cout<<"Admission number "<<admno<<"\nStudent name "<<sname<<"\nEnglish "
<<eng<<"\nMath "<<math<<"\nScience "<<science<<"\nTotal "<<total;
}
};
int main ()
{
student obj ;
obj.Takedata();
obj.Showdata();
return 0;
}
use std::cin.getline instead of gets and std::string instead of char [].
As comments pointed out, gets is not declared in iostream. Furthermore, it has been deprecated in C++11 and removed in C++14, which means even if you include cstdio or stdio.h, it just do not compile in compilers supporting C++14.
But still, never use std::cin for char []. The reason is the same as gets. Both will make your program under the danger of buffer overflow when your input is longer than buffer, which will cause your program has unexpected behaviour, like crash. And crackers may even hack your whole computer with it.

How to store both an int or a string in a single variable, without losing their type?

#include<iostream>
using namespace std;
class Name
{
public:
void tell(string s){cout<<"Your name is "<<s<<endl;}
void tell(int i){cout<<"Your age is "<<i<<endl;}
};
int main()
{ Name m; string s;
while(s!="n")
{
cout<<"Input your name or age"<<endl;
cin>> s;
m.tell(s);
}
return 0;
}
The variable 's' should be able to store an int as well as string argument, without losing its type;
so that, the 'int' overload gets invoked when I pass an int argument
and the 'string' overload gets invoked when I pass a string argument to tell()
"Input your name or age" - well, you at least need to know, what you are about to store, i.e. how to interpret the input value.
If your intent is to detect if the input is a number, you could try to convert to integer, and if that conversion succeeds store the value as int, otherwise as string.
For example with boost::lexical_cast:
#include <boost/lexical_cast.hpp>
cin >> s;
try {
int age = boost::lexical_cast<int>(s);
m.tell(age);
} catch (const bad_lexical_cast &) {
m.tell(s);
}
If you don't have boost, you can try to use different means of conversion, like atoi() (difficult to detect error) or strtol() (possible to detect error) - see also How do I check if a C++ string is an int?.

Why is this program crashing ? Did I wrongly allocate memory?

Question
Design a class Employee with name and employee number. Derive Manager, Scientist and Laborer classes. The manager class has extra attributes title and dues. The scientist class has extra attribute number of publications. The Laborer class has nothing extra. The classes have necessary functions for set and display the information.
My solution
#include<iostream>
#include<cstring>
using namespace std;
class employee
{
protected:
char *name;
int number;
public:
employee()
{
cout<<"enter employee name \n";
cin>>name;
cout<<"enter employee number \n";
cin>>number;
}
void display()
{
cout<<"name \t"<<name<<endl;
cout<<"number \t"<<number<<endl;
// inside class function is a inline function
}
};
class manager: private employee
{
float due;
char *title;
public:
manager( )
{
cout<<"due\t "<<endl;
cin>>due;
cout<<"title\t"<<endl;
cin>>title;
fflush(stdin);
}
void display()
{
employee::display(); //inside class function is a inline function
cout<<"due\t"<<due<<endl;
cout<<"title\t"<<title<<endl;
//inside class function is a inline function
}
};
class labour :private employee
{
public:
void display()
{
employee::display(); //inside class function is a inline function
}
};
class Scientist :private employee
{
int number;
public:
Scientist()
{
cout<<"publication number "<<endl;
cin>>Scientist::number;
}
void display()
{
employee::display();
cout<<" pub number "<<Scientist::number<<endl;
fflush(stdin);
} //inside class function is a inline function
};
int main()
{
manager m;
m.display();
Scientist s;
s. display();
labour l;
l.display();
return 0;
}
You don't allocate any memory for title or name, so you can't read into them from std::cin. Instead of using char* you should use std::string which will do all of the allocation for you:
std::string title;
std::string name;
In the constructor of empolyee you read into an uninitialized char*. Therefore it does not point to a valid block of memory where you could store the entered name to. You could do
name = static_cast<char*>(malloc( 32 * sizeof(char) ));
to allocate memory such that name points to valid memory, but you always waste memory or do not have enough for the input. Also you have to free the memory in the destructor.
As Peter Schneider wrote in the comment of this answer, another option is to use arrays of a fixed size as a member, e.g.
char name[MAX_NAME_LENGTH];
with a e.g. preprocessor defined
#define MAX_NAME_LENGTH 64
at the top of your file. This way the copy constructor does his job. With pointers as members, you always have to write them yourself, otherwise, the original class instance and copied instance will have a member pointer pointing to the same memory. So if one the copied instance changes the name, the original instance will have a changed name, too.
The easiest solution would be to use a std::string instead of char*. It allocates memory on its own and you don't have to free anything and copying works fine, too.

stack concept with array of object in C++

#include<iostream.h>
using namespace std;
class staticdemo
{
static int rollno;
string name;
public:
staticdemo()
{
cout<<"NAME: ";
getline(cin,name);
rollno++;
}
int getname()
{
cout<<name;
return 0;
}
static int getvalu()
{
return rollno;
}
};
int staticdemo::rollno=10;
int main()
{
int i,n;
cout<<"enter the number of studentd:";
cin>>n;
staticdemo s[n];
for(i=0;i<n;i++)
{
cout<<"name:"<<s[i].getname();
cout<<"\nroll no: "<<s[i].getvalu();
}
system("pause");
return 0;
}
I learning C++, i have a doubt in stack with array of object concept,
in my above program i get the names from user and rollno incremented through stack
while i retrieving list back it will give finally updated stack value, how to get the fully updated rollno values, (how to display the unique rollno for every names),
pls post your valuable solution
If I'm reading your question correctly, you want the rollno variable to be unique for each instance of the staticdemo class? Well then you can't have the member as static, because static members are shared among all instances of a class.
I think I roughly understand your question, although it seems a bit hard to get what you need.
What you have done is partially right, you use a static member variable "rollno" to record the count, however, if you really want what you need, you will need another non-static variable to record the index, e.g:
class staticdemo {
static int rollnoGlobal; // this will record the global count, used by everybody
int myRollno; //Non-static, this will record the rollno index for this particular object
string name;
public:
staticdemo() {
cout<<"NAME: ";
getline(cin,name);
myRollno = rollnoGlobal; // This is the step for each individual to remember its index
rollnoGlobal++;
}
int getname() {
cout<<name;
return 0;
}
static int getGlobalRollnoValue() {//return the global count;
return rollnoGlobal;
}
int getMyRollno() { // return the index or you call it rollno for this particular object
return myRollno;
}
};
int staticdemo::rollnoGlobal=10;
int main() {
int i,n;
cout<<"enter the number of studentd:";
cin>>n;
staticdemo s[n];
for(i=0;i<n;i++)
{
cout<<"name:"<<s[i].getname();
cout<<"\nroll no: "<<s[i].getMyrollno();
}
system("pause");
return 0;
}
Again if I was correct, the problem you faced is more like a understanding of static member variable and methods in C++ classes. This example you need two things:
A unique index for each variable, this is done by your original rollno static member.
Each staticdemo object must store its unique index. And this is the step you missed. After the global count increased, it increased for everybody because it is static. If you need to store it for each individual, you need another non-static member.
Side notes:
STACK is a very specific programming concept as pointed out by others, you question obviously does not need stack. You can try google what is a stack in programming.

File handling in C++ gives .exe stopped working error

I have basic file handling code of reading file named"student.dat" using visual studio.
the output reads the file and displays the result in console but visual studio pops up the dialog as
code:
#include<iostream>
#include<fstream>
#include<conio.h>
#include<string>
using namespace std;
class student
{
int admno;
// char name[20];
string name;
public:
void getdata()
{
cout<<"\n\nEnter The Name of The Student ";
//gets(name);
cin>>name;
getch();
cout<<"\nEnter The admission no. ";
cin>>admno;
// getch();
}
void showdata()
{
cout<<"\nAdmission no. : "<<admno;
cout<<"\nStudent Name : ";
cout<<name;
//puts(name);
}
int retadmno()
{
return admno;
}
};
int main()
{
student obj;
ifstream fp1;
fp1.open("student.dat",ios::binary);
while(fp1.read((char*)&obj,sizeof(obj)))
{
obj.showdata();
}
fp1.close();
return 0;
}
You are allowed to load raw data only to some POD objects. This line is an error:
fp1.read( (char*)&obj,sizeof(obj) );
because student contains std::string. std::string contains a pointer to a memory block which becomes invalid and totally useless after the object is destroyed. It means the data you load to std::string is just a garbage.
I'd think about object serialization. Boost serialization is a good way to start.
You try to store/load an object to a file, which is invalid.
while(fp1.read((char*)&obj,sizeof(obj)))
Objects may contain references to memory (std::string e.g.) that are invalid after loading. You have to provide serialization for your objects or use plain structs without pointers or references to store your data. E.g.:
struct {
int admno;
char[20] name;
}
If you need strings with variable length, you may use a string store:
struct {
int admno;
size_t name_index;
}
std::vector<std::string> names;
To store, iterate over your names and save length and .c_str of each std::string. To read, do it the other way around and read length into n, read n bytes into a buffer and construct a std::string out of the buffer.
You might have a look at http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html
You never call GetData so admno is not instantiated in ShowData