dynamic memory allocation - c++

how allocate memory dynamically for the array of stucture....
eg:
class students
{
struct stud
{
int r_no;
char name[20];
}*s;
}
how to allocate memory dynamically for *s...

First of all, this is not the way of doing it, as you could use a vector of stud, for instance. With the code as you have it, it would be something like:
class students
{
public:
struct stud ... *s;
students() // ctor
{
s = new stud[100]; // say you have 100 students
// from now on you can use s[0], s[1], etc. in the class
}
};
However, what you should be using is kind of an STL vector or list:
class students
{
public:
struct stud ... ;
std::vector<stud> my_students;
students() // ctor
{
stud aStudent = {0, "Student Name"};
my_students.push_back(aStudent); // add a new student.
}
};

Why the extra wrapping of the struct in a class with nothing but a pointer?
Anyway, in C you'd do something like this:
struct stud
{
int r_no;
char name[20];
} *s;
size_t num_students = 4711;
s = malloc(num_students * sizeof *s);
Then it'd be prudent to go through and make sure all those individial structs are initialized, of course.
If you mean this to be C++, you should write constructors that take care of that, and use a new[] to allocate an array of structures.

You should make use of standard components when you can. Here std::string and std::vector would help you.
struct Student
{
int r_no;
std::string name;
};
typedef std::vector<Student> StudentList;
With such an approach, there is no point in wondering how to dynamically allocate memory. Everything's taken care of !
EDIT:
I simply typedef'ed StudentList because to me, adding more functionality to it would have been unrelated to the question.
Clearly, the last line can be replaced with a true class definition:
class StudentList
{
public:
// Add your own functionalities here
private:
std::vector<Student> m_students;
};

class students
{
public:
students(size_t noOfStudents):m_noOfStudents(noOfStudents)
{
s = new stud[m_noOfStudents];
}
~students()
{
delete s;
}
private:
struct stud
{
int r_no;
char name[20];
}*s;
size_t m_noOfStudents;
}

Related

C++ Creating Array of Objects

I'm having an issue with making one array with 3 objects. I'm trying to display the information of employees and my issue is that I don't know where I would assign the strings to the appropriate members and how to keep one variable for name. My code and an example are below:
class employee
{
private:
string name;
string idNumber;
public:
void setName(string);
void setIDnumber(string);
string getName();
string getIDnumber();
};
const int numEmployees = 3;
int main()
{
employee employeeInfo [numEmployees];
}
I want to create a constructor for 3 employees and input(name, idNumber). for example, in employeeInfo[0], the first employee, I want to input "Tom Jones", "123456"
and in employee[1], the second employee, "James Blyth", "QE123"
You can simply call the setter methods on the individual employee objects, eg:
int main()
{
employee employeeInfo [numEmployees];
employeeInfo[0].setName("Tom Jones");
employeeInfo[0].setIDNumber("123456");
employeeInfo[1].setName("James Blyth");
employeeInfo[1].setIDNumber("QE123");
// and so on...
...
}
If you really want to add a constructor, then it would look like this:
class employee
{
private:
string name;
string idNumber;
public:
employee() = default;
employee(string name, string idNumber);
...
};
employee::employee(string name, string idNumber) {
setName(name);
setIDnumber(idNumber);
};
...
int main()
{
employee employeeInfo [numEmployees];
employeeInfo[0] = employee("Tom Jones", "123456");
employeeInfo[1] = employee("James Blyth", "QE123");
// and so on...
}
Just note that this will default-construct the array elements first, and then construct temporary objects to overwrite the array elements.
If you want to avoid the temporaries, but still want a fixed array of objects stored consecutively, you can use placement-new to construct the array members directly using your non-default constructor, eg:
#include <type_traits>
int main()
{
std::aligned_storage_t<sizeof(employee), alignas(employee)> buffer[numEmployees];
employee* employeeInfo = reinterpret_cast<employee*>(buffer);
new(&employeeInfo[0]) employee("Tom Jones", "123456");
new(&employeeInfo[1]) employee("James Blyth", "QE123");
// and so on...
...
for(int i = 0; i < numEmployees; ++i) {
employeeInfo[i].~employee();
}
}
Or, you can use a std::vector (if you don't mind the array being allocated in dynamic memory), eg:
#include <vector>
int main()
{
std::vector<employee> employeeInfo;
employeeInfo.reserve(numEmployees);
employeeInfo.emplace("Tom Jones", "123456");
employeeInfo.emplace("James Blyth", "QE123");
// and so on...
...
}
Otherwise, create an array of pointers to objects instead, and then you can create the individual objects dynamically using new with your non-default constructor. The objects just won't be stored consecutively in memory, eg:
int main()
{
employee* employeeInfo[numEmployees];
employeeInfo[0] = new employee("Tom Jones", "123456");
employeeInfo[1] = new employee("James Blyth", "QE123");
// and so on...
...
for(int i = 0; i < numEmployees; ++i) {
delete employeeInfo[i];
}
}
Which would be safer handled with std::unique_ptr, eg:
#include <memory>
int main()
{
std::unique_ptr<employee> employeeInfo[numEmployees];
employeeInfo[0] = std::make_unique<employee>("Tom Jones", "123456");
employeeInfo[1] = std::make_unique<employee>("James Blyth", "QE123");
// and so on...
...
}

std::vector push_back class from a different namespace

I have a little example.
Im trying to add data to my std::vector from a class that is not in the same namespace.
both classes are the same.
How can i push data to to vector from a class that is not in same namespace
class A
{
public:
std::string name;
int32_t Size;
};
namespace TEST {
class A
{
public:
std::string name;
int32_t Size;
};
class File
{
public:
std::vector<A> data;
};
}
int main()
{
A data = { "outside namespace", 10 };
TEST::File file;
file.data.push_back(data);
return 0;
}
I guess you need an extra constructor in TEST::A for copying members from global A:
namespace TEST {
class A
{
public:
A(const ::A& a) :
name(a.name),
Size(a.Size)
{}
std::string name;
int32_t Size;
};
...
When pushing to vector do it like this:
int main()
{
A data = { "outside namespace", 10 };
TEST::File file;
file.data.push_back(TEST::A(data));
return 0;
}
How can i push data to to vector from a class that is not in same
namespace
The problem isnt really different namespaces, but the problem is that A and TEST::A are two different classes and you cannot push an A into a vector of TEST::As.
Just qualify the names with the namespace name:
TEST::A data = { "outside namespace", 10 };
A and TEST::A are two different classes.
You declare your vector to accept objects from the relevant class in its namespace:
std::vector<A> v; // will accept objects of class A
std::vector<TEST::A> v; // will accept objects of class TEST::A

Initialise values of a struct for use in another file

So I have my class Test.H which has a struct in it.
Class Test{
private:
struct Data
{
char *first;
int number;
int count;
};
Data *myStruct;
I am trying to use the myStruct in my User.C initialiser.
//User.C
#include "Test.H"
Test::Test(const char *alp){
myStruct.number = 0;
}
And I get an segmentation fault and error from valgrind.
I figured initially that it was due to Data* myStruct being in private, but after writing a function like this below:
Data getStruct(){
return myStruct;
}
It will still give me errors when I use it in User.C
You need to construct the struct before you can do anything with it. Calling the default constructor will initialises it's fields to 0.
You had class capitalised, that was wrong. I also don't see a reason why it has to be a pointer, so I removed that. Lastly, I added a destructor in Data so that first will be deleted. I assume it is a cstring, so I used delete[]. If it is something else, delete it in whatever manner is appropriate.
If you must have a pointer, modify the call to the constructor to use new, delete the struct in the destructor ~Test(), and reference members of myStruct with the -> operator.
class Test {
public:
struct Data {
const char* first;
int number;
int count;
~Data() {
delete[] first;
}
};
Test(const char *alp) {
// Default constructor initialises struct's fields to 0.
myStruct = Data();
myStruct.count = 7;
}
private:
Data myStruct;
};

C++ Container and Entity Classes

I'm new to the site (and to programming) so I hope I post this question appropriately and under all the proper guidelines of the site. Ok, here it goes:
So I pretty new to C++ and am trying to create classes for a program. I have to construct "container and entity classes", but where I'm struggling is trying to nail down the proper syntax for my getter and setter functions in the container class. So here's the code I have so far:
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
using namespace std;
const int MAX_STUDENTS=100;
const int MAX_COURSES=25;
const int NAME_SIZE=30;
const int COURSE_COLUMNS=4;
const int GRADE_ROWS=10;
//Entity Classes
class Course
{
//Two private member variables
private:
string courseText;
int courseID;
public:
//Constructor
Course(void)
{
//Just providing initial value to the two object variables
courseText;
courseID=-1;
}
//Setters and Getters for each variable
string getCourseText(){
return courseText;}
void setCourseText(string userEnteredText){
courseText = userEnteredText;}
int getCourseID(){
return courseID;}
void setCourseID(int userEnteredID){
courseID = userEnteredID;}
};
class Student
{
//Private member variables
private:
string studentText;
int studentID;
int** coursesAndGrades;
int enrolledCoursesCount;
int timesReallocatedColumns;
int timesReallocatedRows;
public:
//Constructor
Student(void)
{
//Just providing initial value to the object variables
studentText;
studentID=-1;
coursesAndGrades = new int*[GRADE_ROWS+1];
for(int i=0;i<(GRADE_ROWS+1);i++)
{
coursesAndGrades[i] = new int[COURSE_COLUMNS];
}
enrolledCoursesCount=0;
timesReallocatedColumns=0;
timesReallocatedRows=0;
}
//Setters and Getters for each variable
string getStudentText(){
return studentText;}
void setStudentText(string userEnteredText){
studentText = userEnteredText;}
int getStudentID(){
return studentID;}
void setCourseID(int userEnteredID){
studentID = userEnteredID;}
int getCoursesAndGrades(int gradeRow, int courseColumn){
return coursesAndGrades[gradeRow][courseColumn];}
void setCoursesAndGrades(int gradeRow, int courseColumn, int entry){
coursesAndGrades[gradeRow][courseColumn]=entry;}
int getEnrolledCoursesCount(){
return enrolledCoursesCount;}
void setEnrolledCoursesCount(int enrolledCount){
enrolledCoursesCount = enrolledCount;}
int getTimesReallocatedColumns(){
return timesReallocatedColumns;}
void setTimesReallocatedColumns(int reallocColumnCount){
timesReallocatedColumns = reallocColumnCount;}
int getTimesReallocatedRows(){
return timesReallocatedRows;}
void setTimesReallocatedRows(int reallocRowCount){
timesReallocatedRows = reallocRowCount;}
};
Now, I've got a container class called GradeBook which contains dynamically allocated arrays of these two entity class objects.
class GradeBook
{
private:
Course* courses;
Student* students;
public:
//Constructor
GradeBook(void)
{
courses = new Course [MAX_COURSES];
students = new Student [MAX_STUDENTS];
}
}
I'm trying to figure out the proper way to translate the setter and getter functions from my entity classes to the container class so I can change individual elements of each class object in the dynamically allocated array. These changes will happen in more public member functions in the container class, but I'm completely stumped. I hope this question makes sense, and I'm not looking for anyone to write all of the setters and getters for me, I just need someone to point me in the proper direction for the syntax. Thanks everyone who made it through this!
If you will have something like this:
class GradeBook
{
public:
...
Student& student(int idx) { /*some boundary check here*/
return students[idx]; }
}
then you can use that method as:
GradeBook theBook;
...
auto idOfFirstStudent = theBook.student(0).getStudentID();
You just need to decide what that student() method shall return: it can return reference (as above) or pointer to student (instance). In later case you can return nullptr in case of out-of-bound errors. In first case the only reasonable option is to throw an error.
So there's no magic needed here, but you do need to decide how you want to do it. One way would be to just write something like:
void GradeBook::setCourseText(int i, const string &txt) {
courses[i].setCourseText(txt);
}
BTW, I would highly recommend using std::vector and at() rather than new.

Struct inside a struct

I have struct
struct Course{
int cId;
string courseName;
};
and I want to add students for each Course. I thought to define another struct in to struct Course like
struct Course{
int cId;
string courseName;
struct Student{
int sId;
string studentName;
};
};
if I define struct like this how could I use it ? I have Course * cptr = new Course[1];
which for using the struct course.
How could I add Students to specified cId's ?
Your Course does not contain a Student. It just defines a struct of that name, i.e. a type Course::Student. For a type to contain an instance of another type, you just have to declare a member variable:
struct Student { .... };
struct Course
{
....
Student student;
};
If you want each course to hold more than one Student, then you can use a container. In the absence of more information, the best candidate for that is std::vector:
struct Course
{
....
std::vector<Student> students;
};
struct Course
{
// ...
struct Student
{
int sId;
string studentName;
};
};
This defines a struct Course and another struct Course::Student, but Course does not instantiate any student (there is no member of Course which has a type Student). If you want students to be a member of course, you need something like this:
struct Course
{
// ...
struct Student
{
int sId;
string studentName;
} student;
};
or
struct Course
{
// ...
struct Student
{
int sId;
string studentName;
} students[10];
};
Which would define a single student or an array of 10 students as members of Course, respectively. (NOTE: std::vector would be a better choice than a statically sized array)
Alternatively, you can declare Student as a struct outside of Course:
struct Student { ... };
struct Course
{
// ...
Student student;
// or std::vector<Student> students;
// or std::array<Student, 10> students;
// or Student* students
};
A very simple way:
struct Student
{
int sId;
string studentName;
};
struct Course
{
int cId;
string courseName;
std::vector <Student> students;
};
This way you may write
Student s;
Course c;
c.students.push_back(s);
std::vector is your friend, but if you are not allowed to use that, you can do:
struct Student {...}; // Implementation omitted for brevity...
struct Course
{
Student *students_; // Use students_=new Student[num_students]; to allocate
// memory dynamically
};
I prefer you to divide this struct into two individual struct. Then you can initialize a student object in the Course struct. Or u can implement a function in Course struct to link with Student struct.