Returning a structure pointer - c++

I'm quite new with c++ and need some help with the following code.
#include <iostream>
using namespace std;
struct student {
string name;
int age;
float marks;
};
struct student *initiateStudent(string , int , float);
int main ( ) {
int totalStudents = 1;
string name;
int age;
float marks;
cin >> totalStudents;
student *stud[totalStudents];
for( int i = 0; i < totalStudents; i++ ) {
cin >> name >> age >> marks;
stud[i] = initiateStudent(name,age,marks);
}
cout << stud[0]->name;
return 0;
}
struct student *initiateStudent(string name, int age, float marks)
{
student *temp_student;
temp_student->name = name;
temp_student->age = age;
temp_student->marks = marks;
return temp_student;
}
I need in the function initiateStudent return a struct pointer to the pointer array stud by passing the members name, age, marks.
I know that the problem sofar is the fact that temp_student is destroyed when I return to the main file.
So my question is how it could be done by just passing the members of the struct and then return back with information to the pointer array stud.
Thank you very much.

Semi-answer To explain the bad habits:
#include <string>
#include <iostream>
#include <vector>
//using namespace std; often injects subtle bugs. Use with caution
// read more here:
// http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
struct student
{
std::string name; // explicit namespacing reduces possibility of unwanted collisions
int age;
float marks;
//added constructor in place of initialization function.
student(std::string name, int age, float marks):name(name), age(age), marks(marks)
{
}
};
int main()
{
int totalStudents = 1;
std::string name;
int age;
float marks;
while (!(std::cin >> totalStudents)) // testing input for success
// Needed extra brackets caught by M.M
// teach me to not test even a throw-away example
{
std::cout << "must... have... good... input..." << std::endl;
cin.clear(); // clear the error and get rid of any other garbage the user may have input.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
//student *stud[totalStudents]; illegal in C++
std::vector<student *> stud(totalStudents); // using dynamic array instead
for (int i = 0; i < totalStudents; )// i++ removed
{
if (std::cin >> name >> age >> marks) //testing input
{
stud[i] = new student(name, age, marks); // using constructor
i++; // and put here. Only increment if input is valid.
}
else
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
std::cout << stud[0]->name;
for (student * stu: stud) // cleaning up allocated memory
{
delete stu;
}
return 0;
}
One of the beauties of C++ is you rarely need to self-manage memory. In fact there are huge advantages in not doing it above and beyond not having to clean up after yourself.
#include <string>
#include <iostream>
#include <vector>
struct student
{
std::string name;
int age;
float marks;
student(std::string name, int age, float marks):name(name), age(age), marks(marks)
{
}
};
int main()
{
std::string name;
int age;
float marks;
std::vector<student> stud; // look ma! No pointer!
while (std::cin >> name >> age >> marks) //exits loop on bad input
{
stud.emplace_back(name, age, marks); // building directly in vector
// vector will size itself as needed.
}
std::cout << stud[0].name;
return 0;
}
One more caveat: >> is whiespace delimited. That means it stops when it finds whitespace (space, tab, end of line...) so a name of "John Jacob Jingleheimer-Shmidt" will go into name as "John". >> will then attempt to interpret "Jacob" as age, and that will not go so well.

the simple solution is to make your initiateStudent() creates temp_student on the heap (with new): and returns it. keep in mind heap allocated memory is not freed automatically so don't forget to free it later on yourself.
#include <iostream>
#include <string>
using namespace std;
struct student {
string name;
int age;
float marks;
};
struct student *initiateStudent(string , int , float);
int main ( ) {
int totalStudents = 1;
string name;
int age;
float marks;
cout << "Total student: ";
cin >> totalStudents;
cin.sync(); // very very important to not affect the next input (name)
student* stud = new student[totalStudents];
for( int i = 0; i < totalStudents; i++ )
{
cout << "Name: ";
getline(cin, name);
cin.sync();
cout << "age: ";
cin >> age;
cout << endl;
cout << "Marks: ";
cin >> marks;
cout << endl;
cin.sync();
stud[i] = *initiateStudent(name, age, marks);
}
cout << "Student 1: " << stud[0].name << endl;
delete[] stud;
stud = NULL;
return 0;
}
struct student *initiateStudent(string name, int age, float marks)
{
student *temp_student = new student;
temp_student->name = name;
temp_student->age = age;
temp_student->marks = marks;
return temp_student;
}

Related

Difficulty in understanding c++ string literals

Here the below code is my some part of my program. It doesn't execute it says c++ forbids converting string constants to char*.How can I fix this error?
#include <cstring>
#include <iostream>
using namespace std;
class Bank
{
private:
char name[20];
int acc;
float amount;
public:
Bank()
{
strcpy("",name);
acc = 0;
amount = 0;
}
void open(int a)
{
cout << "Enter name:";
cin >> name;
acc = a;
cout << "Enter Amount" << endl;
cin >> amount;
}
void edit(int flag, float a);
};
int main()
{
Bank B[10];
}
std::strcpy("", name); needs to be std::strcpy(name, "");
Although, setting aside the fact that std::string would be a far better type for name (the future King of England, Charles Mountbatten-Windsor, would not be able to be a customer), writing
name[0] = 0;
would be sufficient.

How to create dynamically allocated 2D array of Structures in C++?

I am trying to create 2D array of structures and print the value. How "Segmentaion fault (core dumped)" message".
#include <iostream>
#include <string>
using namespace std;
struct student{
string name;
int age;
float marks;
};
student* initiateStudent(string name, int age, float marks){
student *studFun;
studFun->name = name;
studFun->age = age;
studFun->marks = marks;
return studFun;
}
int main() {
int totalStudents = 1;
string name;
int age;
float marks;
cin >> totalStudents;
student** stud = new student*[totalStudents];
for(int i=0;i<totalStudents;i++){
stud[i] = new student[1];
cin >> name >> age >> marks;
stud[i] = initiateStudent(name,age,marks);
}
delete [] stud;
return 0;
}
I am compiling it using Netbeans for C++. Can anyone tell me whats wrong with this code ?
This should work
#include <iostream>
#include <string>
using namespace std;
struct student{
string name;
int age;
float marks;
};
student* initiateStudent(string name, int age, float marks){
student *studFun = new student();
studFun->name = name;
studFun->age = age;
studFun->marks = marks;
return studFun;
}
int main() {
int totalStudents = 1;
string name;
int age;
float marks;
cin >> totalStudents;
student** stud = new student*[totalStudents];
for(int i=0;i<totalStudents;i++){
stud[i] = new student[1];
cin >> name;
cin >> age;
cin >> marks;
stud[i] = initiateStudent(name,age,marks);
}
delete [] stud;
return 0;
}

C++ Storing a string into a class

I made a topic a bit ago regarding structs. And I know that classes have the same concept as structs. How would I go about storing a string into the class?
This is the class
class studentType
{
public:
void setData(string, int);
string getName() const;
int getId() const;
private:
string name;
int sid;
};
void studentType::setData(string, int) {
name = ??;
sid = ??;
}
string studentType::getName() const {
return name;
}
int studentType::getId() const {
return sid;
}
The main consists of:
int main() {
studentType object, number;
cout << "enter name and code of item1: ";
cin >> object.setData() >> object.setData();
cout << "enter name and code for item2: ";
cin >> number.setData() >> number.setData();
system("pause");
return 0;
}
How would I fix the cin issue? I already have string defined in the header. And yes, I know using namespace std; isn't preferred but it's for simplicity
int id;
string name;
cout << "enter name and code of item1: ";
cin >> name >> id;
object.setData(name, id);
cout << "enter name and code for item2: ";
cin >> name >> id;
object.setData(name, id);
You should instead use a constructor for your class though:
class studentType {
public:
studentType(string name, int sid)
: name(name)
, sid(sid)
{ }
// ...
You can then initialize your objects with the correct name and ID:
cin >> name >> id;
studentType object(name, id);
But I suppose constructors will come up very soon in the tutorial or course you're currently doing.
cin >> object.setData() >> object.setData();
the >> operator doesn't call object.setData; it takes a reference and sets the reference contents to the extracted input. The expression object.setData() calls the function, which returns void. Of course, the >> operator cannot take a void argument. Also, there aren't enough arguments in the funcall because object.setData expects a string and an int.
You should do this:
std::string name;
int num;
cin >> name >> num;
object.setData(name, num);
Your setData function can be as such:
void studentType::setData(string name, int sid) {
this->name = name;
this->sid = sid;
}
And in your main():
First cin the values and then call the setData function, i.e.
int main(){
string name;
int code;
studentType object, number;
cout << "enter name and code of item1: ";
cin >> name >> code;
object = studentType();
object.setData(name, code);
// your remaining code
}
Just a note of caution:
If you use cin to get the name and code, the name can only be a single word. Say if you are writing a name of two words, the first word will be put in name and the second will be attempted to put in code.
In simpler terms, cin is space-delimited.
What you're looking for is std::getline(). I would use cin for getting your integers, but not for the strings. I would separate the user input like this. Like #Suhaib Ahmad said, cin is space-delimited. To get a string including spaces from stdin, use std::getline().
void studentType::setData(string n, int i) {
this->name = n;
this->sid = i;
}
-
int main(void) {
string n;
int i;
studentType object, number;
cout << "Enter name for item1: ";
getline(cin, n);
cout << "Enter code for item1: ";
cin >> i;
object = studentType(); // make sure you construct your studentType, I also recommend using a constructor function
object.setData(n, i);
cout << "Enter name for item2: ";
getline(cin, n);
cout << "Enter code for item2: ";
cin >> i;
number = studentType();
number.setData(n, i);
system("pause");
return 0;
}
The way you are using setData(), with no arguments given, as a place to store the cin input is incorrect. You would need to declare variables first, and then initialize your class with the variables.

How to let a user add to and remove from "slots" in an array?

I have a project in my C++ class - we're supposed to make a "simple student management system" comprised of a class for the student attribute variables, and a main function with a branch statement that lets the user input names and IDs for the students. I know that I need to use an array to make "slots" for the students, and that my branch statements need to let the user input values into those slots, but I'm not exactly sure how to do it. Here is the code that I have so far.
#include <string>
#include <iostream>
#include <utility>
using std::string;
using std::cin;
using std::cout;
using std::endl;
struct Student {
private:
int id;
string name;
int birthday;
public:
Student()
{
id = 0;
birthday = 0;
}
Student(int id, string name, int birthday)
{
//set your parameters to the class variables
this->id = id;
this->name = name;
this->birthday = birthday;
}
void setID(int id)
{
this->id = id;
}
int getID() {
return id;
}
void setName(string name)
{
this->name = name;
}
string getName()
{
return name;
}
void setBirthday(int birthday)
{
this->birthday = birthday;
}
int getBirthday()
{
return birthday;
}
void output() {
cout << id << name << birthday << endl;
}
};
int main() {
Student arr[50];
cout << "Student Management System" << endl;
cout << "Press 'a' to add a student" << endl;
char a = 1;
int y = 1;
while (a == 'a') {
switch (y)
{
cout << "Input Student ID:";
cin >> id;
}
}
}
What I'm focusing on most is the fourth line from the bottom. I was told that I need to use my setters, so I said that I want what my user inputs to be treated as the value of the ID variable that I set in the class. However, when I wrote this out, I was given an error. Could someone tell me what the issue is?
You should try to get your switch statement working correctly. To use classes setters, you can store the user input to a temporary variable then from your one student you can call the member function. i.e. in your case:
arr[index].setID(tempInputVariable);
There is no id in your main function or as a global variable.
I suggest you overload operator >> to have your structure extract its members from the data stream:
struct Student
{
//...
public:
friend std::istream& operator>>(std::istream& input, Student& s);
};
std::istream& operator>>(std::istream& input, Student& s)
{
input >> s.id;
input >> s.name;
input >> s.birthday;
return input;
}
Although the above code doesn't use setters, it is the preferred method for inputting data.
The overload can be modified to use setters (kind of overkill):
std::istream& operator>>(std::istream& input, Student& s)
{
int id;
input >> id;
s.setID(id);
std::string name;
input >> name;
s.setName(name);
int birthday;
input >> birthday;
s.setBirthday(birthday);
return input;
}
If you don't like the overload, you can perform the steps in your main function:
//...
Student new_student;
//...
{
int student_id;
std::cout << "Input Student ID:";
std::cin >> student_id;
new_student.setID(student_id);
std::string student_name;
std::cout << "Input Student Name: ";
std::cin >> student_name;
new_student.setName(student_name);
int student_birthday;
std::cout << "Input Student Birthday: ";
std::cin >> student_birthday;
new_student.setBirthday(student_birthday);
}
Edit 1: The Database
You'll probably need to store or remember the students. This is easy using the first method above:
std::vector<Student> database;
Student s;
std::cout << "Enter student information (ID, Name and birthday, separated by spaces:\n";
std::cin >> s;
// Append to the database
database.push_back(s);
If you haven't learned std::vector you can try an array:
const size_t MAXIMUM_STUDENTS = 16;
Student database[MAXIMUM_STUDENTS];
size_t database_index = 0;
//...
Student s;
std::cout << "Enter student information (ID, Name and birthday, separated by spaces:\n";
std::cin >> s;
// Append to database
database[database_index] = s;
++database_index;

C++ program hangs when using cin.getline()

I am making a program keeping track of different persons, which I try to read in from a file. I use a constructor that takes an ifstream file as an argument, and I then try to read in the data from the file. I can read the first line, which is just an int (a unique number for each person), but when I try to go to the next line and getline it, the program hangs. Does anyone know why?
#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
#include <cstdlib>
using namespace std;
const int MAXPERS = 100;
const int MAXTXT = 80;
const int DATELEN = 7;
class Person {
private:
int nr;
char* firstName;
char birthDate[DATELEN];
public:
Person() {
char fname[MAXTXT];
cout << "First name: "; cin.getline(fname, MAXTXT);
firstName = new char[strlen(fname) + 1];
strcpy(firstName, fname);
cout << "Birth date (DDMMYY): ";
cin >> birthDate; cin.ignore();
}
Person(int n, ifstream & in) {
nr = n;
char fname[MAXTXT];
cin.getline(fname, MAXTXT);
firstName = new char[strlen(fname) + 1];
strcpy(firstName, fname);
in >> birthDate;
}
void display() {
cout << "\nFirst name: " << firstName;
cout << "\nBorn: " << birthDate;
}
void writeToFile(ofstream & ut) {
ut << firstName << "\n" << birthDate;
}
};
void readFromFile();
Person* persons[MAXPERS + 1];
int lastUsed = 0;
int main() {
readFromFile();
persons[1]->display();
return 0;
}
void readFromFile() {
ifstream infile("ANSATTE.DAT");
if(infile) {
while(!infile.eof() && lastUsed < MAXPERS) {
int nr;
infile >> nr;
persons[++lastUsed] = new Person(nr, infile);
}
}
}
My file looks like this:
1
Andy
180885
2
Michael
230399
In your constructor you have
cin.getline(fnavn, MAXTXT);
So your program is waiting for you to type something in. If you meant to get the name from the file then you need
in.getline(fnavn, MAXTXT);
^^ ifstream object
You are also going to run into the issue of mixing >> with getline. You will need to add
infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
after infile >> nr; in your while loop.
strlen(fname + 1) will be strlen(fname) - 1 if fname is one-character long or more and indeterminate if fname is zero-character long. It should be strlen(fname) + 1.
strlen(fnavn + 1) has the same issue and should be strlen(fnavn) + 1.