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;
    }
}

Объяснение кода листинга программы

  1. В представленном коде используется цикл for для перебора элементов массива структур FileMode, который, в свою очередь, содержит информацию о именах файлов и режимах их открытия.
  2. Переменная i инициализируется нулем и увеличивается на единицу после каждой итерации цикла.
  3. Внутри цикла вызывается функция fopen, которая пытается открыть файл с заданным именем и режимом.
  4. Если функция fopen вернула NULL, то есть файл не удалось открыть, то управление переходит к следующей итерации цикла.
  5. Если функция fopen вернула ненулевой указатель, то есть файл был успешно открыт, то переменная fp принимает это значение.
  6. Если файл не удалось открыть ни на одной из итераций цикла, то выполнение программы завершится, и в консоли будет выведено сообщение об ошибке.
  7. Если все файлы были успешно открыты, то переменная fp будет содержать указатель на каждый из них в порядке их открытия.
  8. В структуре FileMode указатель filename содержит имя файла, а указатель mode содержит режим открытия файла.
  9. Значение переменной files_count определяет количество элементов в массиве структур FileMode.
  10. В данном коде нет использования оператора goto, поэтому он здесь не применим.

Оцени полезность:

14   голосов , оценка 4.143 из 5