Как правильно создать и вывести список?

90
16 марта 2021, 22:50

Задание звучит так: Представить таблицу в виде линейного списка L, элементами которого являются строки таблицы: №, Фамилия, Оценки (Физика, История, Математика). Написать программу, содержащую следующие функции: - создание списка (ввод данных с клавиатуры); - просмотр списка... Вот мой код:

#include <locale.h>
#include <iostream>
using namespace std;
struct student
{
    int num; //порядковый номер
    char fio[15]; //фамилия
    int ball[3]; //[0] - балл по физике, [1] - истории, [2] - математике
};
struct list
{
    student inf;
    list * next;
};
list * org(student inf)
{
    cout << "Vvod dannih. Dlya vihoda vvedite '*'" << endl;
    for (inf.num = 1; inf.fio[0] != '*'; inf.num++)
    {
        cout << endl << "Vvedite familiyu: " << endl;
        cout << inf.num << ": ", cin >> inf.fio;
        if (inf.fio[0] == '*')
            return 0;
        cout << "Fizika: ", cin >> inf.ball[0];
        cout << "Istoriya: ", cin >> inf.ball[1];
        cout << "Matematika: ", cin >> inf.ball[2];
    }
    //return ??? что здесь надо возвращать?
}
list * view(list * beg, list * temp)
{
    student inf;
    temp = beg = 0;
    inf.num = 1;
    while (temp -> next != NULL)
    {
        cout << inf.num << ": " << inf.fio << inf.ball[0] << inf.ball[1] << inf.ball[2] << endl;
        temp = temp -> next;
        inf.num++;
    }
}
int main()
{   setlocale(LC_ALL, "rus");
    student inf;
    list * beg, * temp;
    org(inf);
    view(beg, temp);
    return 0;
}

Проблема во второй функции (вывод на экран). Она просто не выполняется. В консоли происходит ввод данных, и после ввода * программа завершается. Моё предположение - потому что не к чему обратиться (предыдущая функция не вернула ничего). Подскажите, пожалуйста, как правильно было бы написать?

Answer 1

Вы абсолютно правы, вы ничего никуда не вернули. Что бы все работало надо, в случае односвязного списка, в структуру list надо добавить указатель на следующий элемент list * next;. Далее надо в main создать указатель на начало списка - list * begin и в функцию добавления вы передаете этот указатель. Функция добавления пробегает по списку, ищет последний элемент у которого next == null;, выделяет память для нового элемента, и делает next = newElement; и только тогда элемент добавлен в список. И соответственно печать работает похожим образом. Пример работы со списком:

#include <stdio.h>
#include <string.h>
#include <conio.h>
struct Node
{
 char data[30];
 Node *next;
};
int main()
{
Node *start;    // это будет указатель на начало списка
char str[30];
Node *spis = new Node;    // создаем список
strcpy(spis->data,"0");   // инициализируем его данными
spis->next = NULL;        // следующий элемент - NULL
start = spis;               // запоминаем начало
for(int i=1; i<10; i++)   // добавим 9 элементов
 {
  spis->next = new Node;   // создаем элемент (и сразу устанавливаем ссылку на него из текущего)
  printf("element: ");
  gets(str);     
  strcpy(spis->next->data,str);  // добавляем данные
  spis->next->next = NULL;   // следующий элемент - NULL
  spis = spis->next;     // делаем новый элемент текущим
 }
// выводим
printf("\n\n");
spis = start;
while(spis)
 {
  printf("%s\n",spis->data);
  spis = spis->next;
 } 
// удаляем
Node *tmp;
spis = start;
while(spis)
 {
  tmp = spis;
  spis = spis->next;
  delete tmp;
 } 
getch();
return 0;
}
Answer 2
struct List_node  {
    size_t num = 0; //порядковый номер
    char surname[15] = " "; //фамилия       
    unsigned points[3] = {0}; //- баллы     
    List_node* next = nullptr;
};
List_node* creat()
{
    List_node *head = new List_node, *pc = head;        
    static size_t i = 0;
    while (std::cin) {  
        std::cout << "\nenter surname and points:  ";
        std::cin >> pc->surname >> pc->points[0]
            >> pc->points[1] >> pc->points[2];      
        pc->num = ++i;
        cout << pc->num;
        pc->next = new List_node;
        pc = pc->next;      
    }
    return head;
}
void show_list(List_node* p)
{
    std::cout << "\n\n number| surname   |  marks \n\n";
    while (p->next)
    {
        std::cout << p->num << ".\t " << p->surname << "\t\t"
            << p->points[0] << '\t' << p->points[1] << '\t'
            << p->points[2] << std::endl;           
        p = p->next;        
    }
}
int main() {    
    List_node* head = creat();
    show_list(head);
    //освободим память
    while (head) {
        List_node* p = head;
        head = head->next;
        delete p;
    }
    return 0;
}

Но всегда лучше все это(и удаление обьектов тоже) обернуть в класс

READ ALSO
Получить user data в Hook Proc

Получить user data в Hook Proc

Я имею класс следующего вида:

110
Что лучше цикл с условием или без него?

Что лучше цикл с условием или без него?

Обычно тело цикла выглядит как-то так:

82
как вывести значение glm::vec2 и glm::mat2

как вывести значение glm::vec2 и glm::mat2

попробовал вывести (что там лежит):

102