简体   繁体   中英

How to create a function to read/write data to struct members?

I'm trying to create a program that read and print students' data with c++. for that, I've created a struct Student, a function to read data from the user and assign it to a struct instance s1 and a function to print students' data on the screen, and I think the problem is with the function that read/write data.

Here is the my code:

#include<iostream>
#include<string>
using namespace std;

struct Student
{
    char name[30];
    int age;
    double gpa;
    string department;
};

Student read_data(Student x)
{
    cout << "Name (30 characters maximum): ";
    cin.get(x.name, 30);
    cout << "Age: ";
    cin >> x.age;
    cout << "Department: ";
    cin >> x.department;
    cout << "GPA: ";
    cin >> x.gpa;

    return x;
}

void print_data(Student x)
{
    cout << 
"\n***************************************************************" << endl;
    cout << "Name: " << x.name << endl;
    cout << "Age: " << x.age << endl;
    cout << "Department: " << x.department << endl;
    cout << "GPA: " << x.gpa << endl;
}

int main()
{
    Student s1, s2, s3;

    cout << "This program stores -Temporarily- data of three students\n" << endl;

    cout << "Enter 1st student's data" << endl;

    read_data(s1);

    print_data(read_data(s1));

    system("pause");
    return 0;
}

The output of this code is:

This program stores data of three students

Enter 1st student's data
Name (30 characters maximum): Ahmed Maysara
Age: 22
Department: CS
GPA: 3.5
Name (30 characters maximum): Age: Department: GPA:
***************************************************************
Name:
Age: -858993460
Department:
GPA: -9.25596e+61
Press any key to continue . . .

As you see, the output is out of my expectations :) ..

Any help ?!

Both CinCout and David are correct. There are a couple of problems with your code as it now stands. The first problem is that while you successfully call the function read_data(s1) , s1 is a just a copy. So, when the function sets all of the values for the student using cin, it is really just setting a copy's values. You can either make it so that you are passing in the original, or you can return the student (which you are doing) and set s1 equal to the result (which you are not).

To make sure that you pass in the original, you can go to where you declared read_data. Instead of saying Student read_data(Student x) , you should place an ampersand after the parameter that you don't want to copy Student read_data(Student &x) . This is called passing by reference (you reference the original instead of referencing by copy)

Alternatively, you could con just set s1 to the result where you call it in main. You could say s1 = read_data(s1); and that would work fine, though a bit more inefficiently.

Lastly, the other glaring error in the code is that you accidentally call read_data again when you say print_data(read_data(s1)) . Instead, say print_data(s1) .

Instead of passing and returning the structure object each time on call of read_data and print_data we could add those inside the structure itself, We could create object of Student and call the functions read and print within the same.

struct Student
{
    char name[30];
    int age;
    double gpa;
    string department;

    Student(): age(0), gpa(0)
    {
        memset( name, 0, 30 );
    }

    void read()
    {
        cout << "\nName (30 characters maximum): ";
        cin.get(name, 30);
        cout << "\nAge: ";
        cin >> age;
        cout << "\nDepartment: ";
        cin >> department;
        cout << "\nGPA: ";
        cin >> gpa;
    }
    void print()
    {
        cout << "\n***************************************************************" << endl;
        cout << "Name: " << name << endl;
        cout << "Age: " << age << endl;
        cout << "Department: " << department << endl;
        cout << "GPA: " << gpa << endl;
    }
};

int main()
{
    Student s1;
    s1.read();
    s1.print();
    return 0;
}

You are passing copy of s1 into the read_data function, but not bothering to update the value based on the return arg. ie something like this should work.

s1 = read_data(s1);
print_data(s1);

Alternatively, pass by reference instead of value:

void read_data(Student& x)
{
    cout << "Name (29 characters maximum): "; // requires null terminator
    cin >> x.name; // just read into the buffer directly
    cout << "Age: ";
    cin >> x.age;
    cout << "Department: ";
    cin >> x.department;
    cout << "GPA: ";
    cin >> x.gpa;
}

And then later:

read_data(s1);
print_data(s1);

change you read_data with something like this

void read_data(Student& x)
{
    cout << "Name (30 characters maximum): ";
    ///cin.get(x.name, 30);
    cin.getline(x.name, 30);
    cout << "Age: ";
    cin >> x.age;
    cin.ignore();
    cout << "Department: ";
    std::getline(cin, x.department);
    ///cin >> x.department;
    cout << "GPA: ";
    cin >> x.gpa;
    cin.ignore();
    // return x; can't return a value from a void function
}

and in main function or where you are calling the read_data function use

Student s1, s2, s3;

cout << "This program stores -Temporarily- data of three students\n" << endl;

cout << "Enter 1st student's data" << endl;

read_data(s1);
read_data(s2);
read_data(s3);

the reason you are getting weird values in return is that you capture buffer with cin >> instead getline see

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM