Goto, goto, goto в Си - C (СИ)
Формулировка задачи:
Привет!
После небольшого опыта программирования на assembler, я смотрю на goto как на обычный оператор
и не вижу в его использовании ничего плохого (в умеренном кол-ве, конечно)...
Прочитав ряд статей, так и не смог выяснить ответа на вопрос:
Стоит ли использовать goto в коде? Если да, то в каких случаях?
Если нет, то хотелось бы услышать критику по коду, приведенному ниже...
Вот несколько примеров, в которых я использовал этот сомнительный оператор, ибо не нашел дургого выхода:
первый
второй
void std_func(int x1, int y1, int x2, int y2) { int key; int x = (x2 - x1) / 2 + 1, y = (y2 - y1) / 2 + 1; int top = 1, bottom = y2 - y1 + 1; /* начальное пложение курсора */ gotoxy(x, y); cprintf("*"); while (1) { key = bioskey(0); switch(key) { case K_F11: /* вверх */ if (y > top) { clrscr(); y--; gotoxy(x, y); cprintf("*"); } break; case K_F12: /* вниз */ if (y < bottom) { clrscr(); y++; gotoxy(x, y); cprintf("*"); } break; case K_ESC: goto _exit; /* return тоже подойдет, но с goto как-то естественне выглядит */ } } _exit: }
if ((fd_1 = fopen(file_name1, "rb")) == NULL) { fprintf(stderr, "[**] Не удалось открыть файл : %s\n", file_name1); goto _exit; } if ((fd_2 = fopen(file_name2, "r")) == NULL) { fprintf(stderr, "[**] Не удалось открыть файл : %s\n", file_name2); goto _exit; } if ((fd_3 = fopen(file_name3, "wb")) == NULL) { fprintf(stderr, "[**] Не удалось создать файл : %s\n", file_name3); goto _exit; } /* Какой-то код... */ _exit: if (fd_1) fclose(fd_1); if (fd_2) fclose(fd_2); if (fd_3) fclose(fd_3);
Решение задачи: «Goto, goto, goto в Си»
textual
Листинг программы
// пусть где-то объявлена структура struct FileMode { char* filename; char* mode; }; FileMode file_modes[files_count]; int i; for (i = 0; i < files_count; ++i) { fp = fopen(file_modes[i].filename, file_modes[i].mode); if (!fp) { break; } }
Объяснение кода листинга программы
- В представленном коде используется цикл for для перебора элементов массива структур FileMode, который, в свою очередь, содержит информацию о именах файлов и режимах их открытия.
- Переменная
i
инициализируется нулем и увеличивается на единицу после каждой итерации цикла. - Внутри цикла вызывается функция
fopen
, которая пытается открыть файл с заданным именем и режимом. - Если функция
fopen
вернулаNULL
, то есть файл не удалось открыть, то управление переходит к следующей итерации цикла. - Если функция
fopen
вернула ненулевой указатель, то есть файл был успешно открыт, то переменнаяfp
принимает это значение. - Если файл не удалось открыть ни на одной из итераций цикла, то выполнение программы завершится, и в консоли будет выведено сообщение об ошибке.
- Если все файлы были успешно открыты, то переменная
fp
будет содержать указатель на каждый из них в порядке их открытия. - В структуре
FileMode
указательfilename
содержит имя файла, а указательmode
содержит режим открытия файла. - Значение переменной
files_count
определяет количество элементов в массиве структурFileMode
. - В данном коде нет использования оператора
goto
, поэтому он здесь не применим.