Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Exzotick
0 / 0 / 0
Регистрация: 25.05.2014
Сообщений: 25
#1

Возврат функцией массива структур - C++

27.05.2014, 17:39. Просмотров 793. Ответов 23
Метки нет (Все метки)

Пишу программу, которая в зависимости от выбора пользователя считывает информацию о студентах, вводимую с клавиатуры, либо использует заранее подготовленный массив. После этого сортирует массив и выводит таблицу в виде упорядоченного по группам и алфавиту списка. Проблема с использованием массива-заготовки. Как правильно передать его в функцию? И еще вопрос: вот у меня есть структура students, у нее поля name, group и др. Можно ли получить размер определенного поля структуры, не используя непосредственно переменных с этим структурным типом (т.е., я знаю, что, если student1 - переменная структурного типа students, можно написать "sizeof (student1.name)", а можно ли еще как-то)?
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//7.4
#include <iostream>
#include <algorithm>
#include <windows.h>
#include <cstring>
#include <iomanip>
//#include <cstdio>
using namespace std;
 
const int name_size = 30, n = 6;
struct students
{
    char name[name_size];
    char group[n];
    int age;
    float average;
    float scholarship;
};
 
students* fill_arr(int);
students* use_arr();
students  fill_name(students);
students  fill_group(students);
int fill_age(students);
float fill_average(students);
float fill_scholaship(students);
void print_data(students);
void print_data_tab(students);
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    char choice;
    students *students_arr = NULL;
    int students_num;
    cout << "Заполните информацию о студентах \n1-ввести данные с клавиатуры \n2-использовать заготовку" << endl;
    cin >> choice;
    switch (choice)
    {
    case '1':
        cout << "Введите количество студентов: ";
        cin >> students_num;
        students_arr = fill_arr(students_num);
        break;
    case '2':
        students_arr = use_arr();
        students_num = sizeof (students_arr) / sizeof (students);
        break;
    }
    system("cls");
    cout << "\nИнформация о студентах: \n" << endl;
    int i, j; students temp;
    for (i = 0; i < students_num; i++)
        for (j = 0; j<students_num - i - 1; j++)
            if (strcmp(students_arr[j].group, students_arr[j + 1].group) > 0)
                swap(students_arr[j], students_arr[j + 1]);
            else
            if (strcmp(students_arr[j].group, students_arr[j + 1].group) == 0)
                if (strcmp(students_arr[j].name, students_arr[j + 1].name) > 0)
                    swap(students_arr[j], students_arr[j + 1]);
    for (int i = 0; i < students_num; i++)
        print_data_tab(students_arr[i]);
    system("pause");
}
students* fill_arr(int students_num)
{
    students* students_arr = new students[students_num];
    for (int i = 0; i < students_num; i++)
    {
        students_arr[i] = fill_name(students_arr[i]);
        students_arr[i] = fill_group(students_arr[i]);
        students_arr[i].age = fill_age(students_arr[i]);
        students_arr[i].average = fill_average(students_arr[i]);
        students_arr[i].scholarship = fill_scholaship(students_arr[i]);
    }
    return students_arr;
}
students* use_arr()
{
    students student1 = { "Урманов Роман Сергеевич", "Б8120", 18, 5.0, 7500 },
        student2 = { "Спицын Вячеслав Валерьевич", "Б8120", 17, 4.5, 0 },
        student3 = { "Аристова Дарья Павловна", "Б8120", 18, 4.0, 0 },
        student4 = { "Иванов Петр Владимирович", "М6180", 22, 5.0, 9000 },
        student5 = { "Дорошин Сергей Александрович", "М6180", 22, 4.9, 2800 },
        student6 = { "Годенко Николай Борисович", "Б5216", 19, 4.3, 2400 },
        student7 = { "Афанасьев Виктор Иванович", "Б5216", 19, 4.0, 1900 },
        student8 = { "Галинов Вячеслав Иванович", "Б5216", 19, 3.8, 0 };
    students default_students_arr[] = { student1, student2, student3, student4, student5, student6, student7, student8 };
    return default_students_arr;
}
students  fill_name(students stu_data)
{
    cout << "\nВведите имя студента: ";
    cin.get();
    gets_s(stu_data.name, sizeof (stu_data.name));
    return stu_data;
}
students fill_group(students stu_data)
{
    cout << "Введите группу: ";
    gets_s(stu_data.group, sizeof (stu_data.group));
    return stu_data;
}
int fill_age(students stu_data)
{
    cout << "Введите возраст студента: ";
    cin >> stu_data.age;
    return stu_data.age;
}
float fill_average(students stu_data)
{
    cout << "Введите средний балл студента: ";
    cin >> stu_data.average;
    return stu_data.average;
}
float fill_scholaship(students stu_data)
{
    cout << "Введите размер стипендии: ";
    cin >> stu_data.scholarship;
    return stu_data.scholarship;
}
void print_data(students stu_data)
{
    cout << "ФИО студента: " << stu_data.name << endl
        << "Группа: " << stu_data.group << endl
        << "Возраст: " << stu_data.age << endl
        << "Средний балл: " << stu_data.average << endl
        << "Стипендия: " << stu_data.scholarship << endl << endl;
}
void print_data_tab(students stu_data)
{
    cout << setiosflags(ios::left) << setw(sizeof (stu_data.group)) << stu_data.group << setw(sizeof (stu_data.name)) << stu_data.name << setw(4) << stu_data.age << setw(5) << stu_data.average << setw(6) << stu_data.scholarship << endl;
}
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.05.2014, 17:39
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Возврат функцией массива структур (C++):

Сортировка элементов массива структур шаблонной функцией - C++
Как отсортировать с помощью шаблонной функции по значению полей в массиве структур? Кто знает, подскажите пожалуйста. Программа, которую...

Возвращение функцией значения динамического массива структур - C++
Auto readfile() { ifstream file(file); int i = 0, color; Auto *A = new Auto; while (!file.eof()) { file &gt;&gt; A.name &gt;&gt;...

Возврат функцией указателя на функцию - C++
Всем привет! У меня возникла такая проблема: класс имеет поле-указатель на функцию. В методе, который осуществляет доступ к этуму полю,...

Возврат функцией экземпляра класса - C++
Подскажите, будет ли корректной с точки зрения выделения памяти и всего прочего такая запись: MyObject fun(....) { myObject Obj =...

Динамические массивы структур;Классы. Класс массивы структур;Классы. Класс динамического массива структур. - C++
Здраствуйте.Помогите с практичкой мое задание 4.3. Строка таблицы данных содержит следующую информацию о владельцах авто: ф.и.о....

Возврат массива - C++
Не спрашивайте зачем я это делаю, если можно просто использовать strcpy. char tostrcpy(char *to, char *from); int main(int i) { ...

23
Kuzia domovenok
1892 / 1747 / 119
Регистрация: 25.03.2012
Сообщений: 5,936
Записей в блоге: 1
27.05.2014, 17:52 #2
а зачем тебе узнавать размер поля? Он всегда постоянен!
0
Exzotick
0 / 0 / 0
Регистрация: 25.05.2014
Сообщений: 25
27.05.2014, 18:20  [ТС] #3
Например, чтобы задать ширину поля вывода для setw.
0
montkay
10 / 10 / 8
Регистрация: 19.02.2014
Сообщений: 72
27.05.2014, 18:57 #4
Чтобы правильно передать массив структур нужно в сигнатуре функции указать следующие аргументы:
(students * pStud, int n) - если нам понадобиться изменять данные массива структур и этот массив создан динамически, или (const students * pStud, int n) - если нам не понадобиться изменять данные массива структур и этот массив создан динамически.

Чтобы узнать размер полей структуры можно ещё применить следующее:
1) name - sizeof(char) * name_size;
2) group - sizeof(char) * n;
3) age - sizeof(int);
4) average - sizeof(float);
5) scholarship - sizeof(float).
0
Kuzia domovenok
1892 / 1747 / 119
Регистрация: 25.03.2012
Сообщений: 5,936
Записей в блоге: 1
27.05.2014, 20:11 #5
Цитата Сообщение от Exzotick Посмотреть сообщение
Например, чтобы задать ширину поля вывода для setw.
звучит бредово. При чём тут setw? Ты точно не путаешь с длиной строки? strlen(name) тебе ничего не говорит?
0
montkay
10 / 10 / 8
Регистрация: 19.02.2014
Сообщений: 72
27.05.2014, 20:56 #6
Kuzia domovenok, если уж на то пошло, то нужно прописать как strlen(stud.name), где нужно сделать предварительное объявление и инициализацию student stud;
0
Exzotick
0 / 0 / 0
Регистрация: 25.05.2014
Сообщений: 25
28.05.2014, 08:58  [ТС] #7
Kuzia domovenok, вы мой код смотрели? Мне нужно вывести таблицу, и я хочу, чтобы под вывод имени отводилось столько знаков, сколько отведено под это поле в структуре.

Добавлено через 31 минуту
montkay, я правильно понимаю, что pStud - это указатель на массив структур, а n - количество его элементов? А нельзя создать массив и инициализировать его внутри функции, которая не принимает никаких параметров, возвращает только указатель на него, а потом присвоить значение этого указателя другому указателю в главной функции (как это я сделал)?

Добавлено через 13 минут
montkay, и еще по поводу размера поля. Конструкция "name - sizeof(char) * name_size;", насколько понимаю, возможна только потому, что я задал размер массива константой. А если он был задан просто числом (например, char name[30])?
0
montkay
10 / 10 / 8
Регистрация: 19.02.2014
Сообщений: 72
28.05.2014, 10:17 #8
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Exzotick, начну с последнего вашего вопроса. Чтобы узнать размер поля структуры нужно узнать размер типа данных это поля. Но если поле структуры представлено в виде массива, то нужно, помимо размера типа данных, указать также количество элементов массива. По этому чтобы узнать размер поля структуры char name[30] нужно sizeof(char) * 30.

Да, вы правильно поняли - pStud - это указатель на массив структур, а n - количество его элементов. Если создать массив структур внутри функции, то этот массив по завершению функции будет уничтожен (если этот массив будет создан на стеке, а если нет - то без очистки динамической памяти будет засорятся оперативка). И для того, чтобы сохранить массив в программе, нужно в функцию передавать значение по ссылке или по указателю. Количество элементов есть обязательным (если используется динамический массив, а это как раз ваш случай).

Передавать в главную функцию указатель как это сделали вы - недопустимо, потому что указатель должен указывать на существующий объект. Сейчас объясню. Вот вы создаете и инициализируете в функции массив, а по завершению функции он умирает. Тогда на что будет указывать возвращаемое значение? Фактически это может быть всё, что угодно, но вряд ли нужное вам значение. Чтобы функция возвращала указатель, нужно чтобы она принимала указатель, обрабатывала его каким-то образом, а потом возвращала его. Тогда проблем не будет, ведь возвращаемое значение - существует вне функции, которую вызываете вы, а следовательно - после завершения функции объект будет живым =) И не забывайте использовать количество элементов обязательно, чтобы всегда знать, какой кусок памяти нужно обработать. Ведь если не знать размера этого куска памяти, то программа вплоть до аварийного завершения будет его обрабатывать.
0
Exzotick
0 / 0 / 0
Регистрация: 25.05.2014
Сообщений: 25
28.05.2014, 13:20  [ТС] #9
Не могли бы вы все-таки описать функцию и как ее вызывать. А то у меня никак не получается это правильно сделать.
0
montkay
10 / 10 / 8
Регистрация: 19.02.2014
Сообщений: 72
28.05.2014, 15:34 #10
Exzotick, хорошо. Только скажите какую именно функцию и что она должна делать.
0
Exzotick
0 / 0 / 0
Регистрация: 25.05.2014
Сообщений: 25
28.05.2014, 16:22  [ТС] #11
В функции main предоставляется выбор: заполнить массив вручную или использовать заготовку. Вот во втором случае массивом students_arr должен стать массив default_students_arr, который задан в функции use_arr.
0
montkay
10 / 10 / 8
Регистрация: 19.02.2014
Сообщений: 72
28.05.2014, 18:24 #12
Приблизительно так может выглядеть функция. Но если вы захотите записать больше 8 человек в массив, то всем, кроме первых восьми, будет присвоено значение {"Nobody", "None", 0, 0.0, 0}.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void use_arr(students * pStud, int n)
{
    const int num_stud = 8;
    students stud_nobody = {"Nobody", "None", 0, 0.0, 0};
        students stud[num_stud] = {
        { "Урманов Роман Сергеевич", "Б8120", 18, 5.0, 7500 },
                { "Спицын Вячеслав Валерьевич", "Б8120", 17, 4.5, 0 },
                { "Аристова Дарья Павловна", "Б8120", 18, 4.0, 0 },
                { "Иванов Петр Владимирович", "М6180", 22, 5.0, 9000 },
                { "Дорошин Сергей Александрович", "М6180", 22, 4.9, 2800 },
                { "Годенко Николай Борисович", "Б5216", 19, 4.3, 2400 },
                { "Афанасьев Виктор Иванович", "Б5216", 19, 4.0, 1900 },
        { "Галинов Вячеслав Иванович", "Б5216", 19, 3.8, 0 }
    };
        for (int i = 0; i < n; i++)
        if (i < num_stud)
            pStud[i] = stud[i];
        else
            pStud[i] = stud_nobody;
}
0
Exzotick
0 / 0 / 0
Регистрация: 25.05.2014
Сообщений: 25
28.05.2014, 18:34  [ТС] #13
montkay, А почему эта функция не возвращает указатель? И еще, можно ли сделать так, чтобы первые восемь были записаны заранее, а остальные вводились с клавиатуры и добавлялись в массив?
0
montkay
10 / 10 / 8
Регистрация: 19.02.2014
Сообщений: 72
28.05.2014, 19:50 #14
Эта функция не возвращает указатель, потому что суть её существования заключается в заполнении массива, который начинается по адресу "students * pStud", что указано в сигнатуре функции. Для чего нужно возвращать указатель? С помощью функции вы обрабатываете кусок памяти (для чего в сигнатуре нужно указывать начало массива и количество элементов). Если честно, то задам вам встречный вопрос, если вы не против - почему у вас многие функции возвращают значение? Не легче ли заполнить массив структур, а потом просто в нужный момент обращаться к членам массива и указывать их значение?

Да, можно вводить после восьмого студента вручную данные:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void use_arr(students * pStud, int n)
{
    const int num_stud = 8;
    students stud_nobody = {"Nobody", "None", 0, 0.0, 0};
    students stud[num_stud] = {
        { "Урманов Роман Сергеевич", "Б8120", 18, 5.0, 7500 },
        { "Спицын Вячеслав Валерьевич", "Б8120", 17, 4.5, 0 },
        { "Аристова Дарья Павловна", "Б8120", 18, 4.0, 0 },
        { "Иванов Петр Владимирович", "М6180", 22, 5.0, 9000 },
        { "Дорошин Сергей Александрович", "М6180", 22, 4.9, 2800 },
        { "Годенко Николай Борисович", "Б5216", 19, 4.3, 2400 },
        { "Афанасьев Виктор Иванович", "Б5216", 19, 4.0, 1900 },
        { "Галинов Вячеслав Иванович", "Б5216", 19, 3.8, 0 }
    };
    for (int i = 0; i < n; i++)
        if (i < num_stud)
            pStud[i] = stud[i];
        else
        {
            fill_name(pStud[i]);
            fill_group(pStud[i]);
            fill_age(pStud[i]);
            fill_average(pStud[i]);
            fill_scholaship(pStud[i]);
        }
}
0
Kuzia domovenok
1892 / 1747 / 119
Регистрация: 25.03.2012
Сообщений: 5,936
Записей в блоге: 1
28.05.2014, 19:51 #15
Exzotick, а зачем его возвращать, если данные, переписанные по переданному в ф-ю указателю, сохранят свои изменения даже после выхода из функции?
0
28.05.2014, 19:51
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.05.2014, 19:51
Привет! Вот еще темы с ответами:

Возврат массива из функции - C++
Здравствуйте, Не пойму почему не работает данный код. Пишет cannot convert 'std::string*' to 'int*' in return По теории я жду...

Возврат массива из функции - C++
Здравствуйте. Не могу разобраться, почему при передачи массива из функции но не правильно передаётся. Вот результат.

Возврат массива из класса - C++
вот класс в котором есть массив а class Population1 { public: Population1(int,int); ~Population1(); int ProvLife(int,...

Возврат массива из функции - C++
Программа должна переводить числа с 10 системы в двоичную... но почемуто выводит некорректно... Вот код... #include &lt;iostream&gt; using...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru