Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * 1) Вы протестировали программу. Все хорошо работало.
- * 2) Вам не понравилось то, что у меня слишком большой код в main. Я разбил на функции, которые делают основные действия.
- * 3) Также я использовал функцию gets. Минус ее использования в том, что я могу начать считывать строку, размер которой больше буфера.
- * В таком случае поведение не определено. Например, у меня выкидывается ошибка "Segmentation fault", а у моих одногруппников буфер начинал перезаписываться.
- * 4) Поэтому нужно использовать функцию fgets, которая принимает в качестве аргумента максимальное кол-во считываемых символов.
- * Эта функция возвращает указатель на считанную строку. Если был достигнут конец файла, и не было считано ни одного байта, то возвращается NULL.
- * Также NULL вернется, если произошла ошибка чтения файла. Например, подали указатель на файл, не открытый для чтения.
- * Функция перестает считывать строку в трех случаях:
- * 1. Закончилась строка символом переноса. В этом случае возвращается строка с символом переноса в конце, так как этот символ последний считанный. После переноса нулевой символ.
- * 2. Если считано (n - 1) символов. Не n, потому что оставляется место под нулевой символ.
- * 3. Достигнут конец файла. К считанной строке добавляется нулевой символ.
- */
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
- const int max_size = 100;
- typedef struct List_entry {
- char *string;
- struct List_entry *next;
- } List_entry;
- typedef struct List {
- List_entry *first;
- List_entry *last;
- } List;
- List_entry* get_new_list_entry(char *new_string);
- void destroy_list(List *list);
- void print(List list);
- List_entry* push_back(List *list, List_entry *entry);
- //// Функция по-прежнему огромная, разделяйте дальше.
- int main(int argc, char *argv[]) {
- // Объявления списка, указателя на новый элемент списка и буффера под новую строку.
- List list;
- list.first = NULL;
- list.last = NULL;
- List_entry *new_list_entry = NULL;
- char new_string[max_size];
- // Бесконечный цикл, выход из которого произойдет, когда первый символ считанной строки будет '.'
- ////Заведите макрос или именованную константу, которая будет обозначать условие, до которого исполняется ваш цикл.
- while(1) {
- // Считываем строку (или первые (mas_size - 1) символов строки. В этом случае на следующей итерации цикла продолжим считывать эту строку)
- //// Исходя из вашего объяснения пользователь не сможет ввести все 100 значащих символов для него. Если вам нужно дополнительное место под 0, то заводите массив сооветствующего размера.
- //// Надо исходить из человеческих требований, пользователь не должен учитывать нюансы устройства строк.
- if (fgets(new_string, max_size, stdin) == NULL) {
- perror("Error of fgets");
- return EXIT_FAILURE;
- }
- // Проверка на конец считывания
- //// Заведите именованную константу, которая будет отражать смысл этого сравнения. Код должен описывать себя сам.
- if (new_string[0] == '.') {
- break;
- }
- //// Логику создания элемента списка по строке и добавление этого элемента в список имеет смысл объединить в одну функцию: можно передавать список и строку в качестве параметров.
- // Создаем новый элемент списка
- new_list_entry = get_new_list_entry(new_string);
- if (new_list_entry == NULL) {
- return EXIT_FAILURE;
- }
- // Добавляем новый элемент в список
- if (push_back(&list, new_list_entry) == NULL) {
- //// Куда производится печать ошибки? Объяснить, что не так и исправить.
- printf("Error of a pushing back the element to the list\n");
- return EXIT_FAILURE;
- }
- }
- // Выводим список
- print(list);
- // Освобождаем память
- destroy_list(&list);
- return EXIT_SUCCESS;
- }
- List_entry* get_new_list_entry(char *new_string) {
- // Выделяем память под новый элемент списка
- List_entry *new_list_entry = (List_entry*) malloc(sizeof(List_entry));
- if (new_list_entry == NULL) {
- perror("Error of an allocation memory for (List_entry)");
- return NULL;
- }
- new_list_entry->next = NULL;
- // Выделяем память под строку и инициализируем ее полученным параметром
- new_list_entry->string = (char*) malloc(strlen(new_string) + 1);
- if (new_list_entry->string == NULL) {
- //// Текст должен содержать смысл и контекст, в котором произошла ошибка. Объяснить как работает perror. Тут явное непонимание.
- perror("Error of an allocation memory for (char*)");
- free(new_list_entry);
- return NULL;
- }
- strcpy(new_list_entry->string, new_string);
- return new_list_entry;
- }
- void destroy_list(List *list) {
- if (list == NULL) {
- return;
- }
- List_entry *entry = list->first;
- List_entry *buffer_entry;
- while (entry != NULL) {
- buffer_entry = entry->next;
- free(entry->string); //
- free(entry); //
- entry = buffer_entry;
- }
- }
- void print(List list) {
- //// Что если вам передали NULL список? Исправить код.
- List_entry *entry = list.first;
- while (entry != NULL) {
- printf("%s", entry->string);
- entry = entry->next;
- }
- }
- List_entry* push_back(List *list, List_entry *entry) {
- if (entry == NULL) {
- return NULL;
- }
- if (list == NULL) {
- return entry;
- }
- if (list->first == NULL) {
- list->first = entry;
- list->last = entry;
- return entry;
- }
- list->last->next = entry;
- list->last = entry;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement