0

During class i had to write simple program that uses array of structs, said program needs to add elements and display one or all elements. Teacher said that we can't use vector and that we must use pointers so I can't use something like array[0] = x or x.name.

Problem is that I can't access array in add_element function and after returning from or going into other function I can't access it. From what I found problem is related to realloc but i can't figure it out.

I have two days to send it to teacher so please help.

#include <iostream>
#include <stdlib.h>
#include <string>
#include <unistd.h>

using namespace std;

struct student {
    string name, last_name, date_of_birth;
    unsigned int index;
    char gender;
};

void add_element(student tab[], int &size) {
    int new_size = size + 1;
    tab = (student*)realloc(tab, sizeof(student) * new_size);
    student *x = new student;
    cout << "set name: ";
    cin >> x -> name;
    cout << "set last name: ";
    cin >> x -> last_name;
    cout << "set date of birth: ";
    cin >> x -> date_of_birth;
    cout << "set gender: ";
    cin >> x -> gender;
    cout << "set index: ";
    cin >> x -> index;
    tab[size] = *x;
    size = new_size;
    cout << tab -> name << endl; //here i can access
    delete x;
}

void display(student tab[], int *size) {
    for (int i = 0; i < *size; i++)
        cout << (tab + i) -> name << ' ' << (tab + i) -> last_name << ", " << (tab + i) -> date_of_birth << ", " << (tab + i) -> gender << ", " << (tab + i) -> index << endl;
}
void display(student tab[], int *size, int i) {
    if (i < *size) {
        cout << (tab + i) -> name << ' ' << (tab + i) -> last_name << ", " << (tab + i) -> date_of_birth << ", " << (tab + i) -> gender << ", " << (tab + i) -> index << endl;
    }
}

int main() {
    int size = 0;
    student* students = (student*)malloc(sizeof(student) * size);
    int option;
    do {
        cout << "\x1B[2J\x1B[H";
        cout << "choose what to do\n";
        cout << "0 - add element\n1 - display all elements\n2 - display specific element\n3 - exit\n";
        cin >> option;
        switch (option) {
            case 0:
                add_element(students, size);
                cout << students -> name << endl; //after leaving function can't access
                sleep(2);
            break;
            case 1:
                display(students, &size);
                sleep(2);
            break;
            case 2:
                cout << "provide index for element to display\n";
                int n;
                cin >> n;
                display(students, &size, n);
                sleep(2);
            break;
            case 3:
            break;
            default:
                cout << "option doesn't exist\n";
                sleep(2);
        }
    }
    while (option != 3);
    delete [] students;
    return 0;
}

I tried changing how i pass array into function from reference to pointer but apart from that some small changes that doesn't change anything.

17
  • 4
    Use std::vector instead of raw owning array.
    – Jarod42
    Commented Dec 19, 2024 at 23:22
  • 1
    For the question, you don't have to post your whole code. you should reduce the code and remove all irrelevant code: student might have a single member, std::cin might be replaced by setting hard coded value, no need of menu, and so on...
    – Jarod42
    Commented Dec 19, 2024 at 23:26
  • 1
    "I have two days to send it to teacher so please help." - That is completely irrelevant here. Your urgency is not not our problem. Questions here should be asked to provide value to people long term, not just to satisfy a problem you have short term. Commented Dec 19, 2024 at 23:30
  • 1
    tab[size] = *x; is a disaster waiting to happen. tab[size] is raw memory; there is no student object there. You cannot assign a student object to it. The underlying problem is the use of malloc and realloc; they don't work well with C++ objects, because they don't initialize the allocated memory correctly. Use new student[new_size] to create an array of student objects. Commented Dec 19, 2024 at 23:33
  • 2
    As a general tip, whenever you feel the need to do a C-style explicit conversion (like the cast you do for malloc and realloc) you should take that as a sign that you do something wrong. If you're forced by your assignment to use pointers and explicit memory allocation, use new and new[]. And remember that arguments to functions are passed by value, meaning the function will have a copy of the value. Modifying a copy (like assigning to it) will not modify the original. Commented Dec 19, 2024 at 23:41

2 Answers 2

2

A lot of things wrong with this code. Here's some pointers to get you further along.

  1. Don't use malloc, realloc or free in this code, use new[] and delete[] instead. The issue is that malloc etc do not contruct or destroy objects, so if you use them the string objects in your student struct do not get constructed. This could easily crash your program later.

  2. To simulate realloc with new[] and delete[] you need to allocate a new array, copy everything over from the old array to the new array, and then delete the old array.

  3. When you want a function to modify a variable one way is to pass a reference to that function. This is true whether the variable in question is a pointer or not. That seems to be the misunderstanding that you are asking about here.

  4. Don't allocate a variable and then free it at the end of the same function. There's no need for allocation in this case, just use a normal variable.

  5. Conventionally, user defined types in C++ should start with a capital letter.

Code samples to follow

Point 5

Use a capital letter to start a user defined type

struct Student {
    string name, last_name, date_of_birth;
    unsigned int index;
    char gender;
};

This is only a convention but it's a good one. It means that you won't get variable names and type names mixed up.

Point 4

Not

void add_element(Student tab[], int &size) {
    ...
    Student *x = new Student;
    cout << "set name: ";
    cin >> x -> name;
    ...
    delete x;
}

instead this code that doesn't use new or delete

void add_element(Student tab[], int &size) {
    ...
    Student x;
    cout << "set name: ";
    cin >> x.name;
    ...
}

Point 3

Not

void add_element(Student tab[], int &size) {

instead

void add_element(Student& tab[], int &size) {

but since tab is really a pointer I would prefer to be honest about that, like this

void add_element(Student*& tab, int &size) {

This is the error you are asking about. Since you did not use a reference for tab the change you made to the tab variable inside the function will not be visible outside the function. You understood this for the size variable but for some reason you forgot about it for the tab variable. Maybe you thought that because tab is a pointer the normal rules don't apply. This is a very common misunderstanding but completely incorrect.

Points 1 and 2

Here's how to reallocate your array

void add_element(Student*& tab, int &size) {
    // allocate a new array
    int new_size = size + 1;
    Student* new_tab = new Student[new_size];
    // copy the old array to the new array
    for (int i = 0; i < size; ++i)
        new_tab[i] = tab[i];
    // delete the old array
    delete[] tab;
    // use the new array
    tab = new_tab;
    size = new_size;
1
  • 1
    Hmm, "user defined types should start with a capital letter" is just one of several coding conventions. In particular, the Standard Library does not use that convention for its user-defined types, and that's a perfectly sensible patter to follow. Otherwise, a great answer to a poor question! Commented Dec 20, 2024 at 11:25
0

The quickest way, which you have already done for size, is the following; change:

void add_element(student tab[], int &size)

to:

void add_element(student &tab[], int &size)
//                       ^ A reference to an array

Also, I'd personally choose instead of:

student *x = new student;

use:

student x;

And of course use a better variable name than x. Define the struct as struct Student {...} then have Student student;.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.