Плохой дескриптор файла после рекурсивной функции для открытия файла в C

Я хочу выполнить проверку на ошибку в функции openFile в C и при ошибке: 2 я хочу снова рекурсивно вызвать ту же функцию.

Я не получаю правильного ответа, если я хочу сделать fputs() после открытия файла, я получаю сообщение об ошибке (неверный файловый дескриптор)

Вот мой код:

void openFile(FILE **fstream, char* path, char* mode) {
    *fstream = fopen(path, mode);
    if(*fstream == NULL) {
        printf("\nError number %2d : ",errno);
        perror("Error opening file: ");
        switch (errno) {
            case 2:
                printf("Creating file %s now...\n", path);
                *fstream = fopen(path, "a+");     //Creating file in append-mode
                if (fstream == NULL) {
                    perror("Couldn't open the file!\nError");
                    exit(EXIT_FAILURE);
                }
                fclose(*fstream);                 //Closing filestream
                openFile(fstream, path, mode);    //Recursive call of openFile() to re-open in read-mode
                /* freopen(path,mode,fstream) */  //Doesn't work either
                break;
            default:
                exit(EXIT_FAILURE);
                break;
        }
    } else if (*fstream != NULL) {
        printf("Successfully opened %s\n", path);
    }
}

Звонок:

   openFile(&fp, path,"r");
   if (fputs("blabla\nblabla\n",fp) == EOF) {
     perror("Unable to write file with fputs()"); 
   }

Что я делаю неправильно? Думаю дело в рекурсивном вызове функции, но что тут делать? я не понимаю..

Выход:

> .\a
Content of path: test.txt
Error number  2 : Error opening file: : No such file or directory
Creating file test.txt now...
Successfully opened test.txt
Unable to write file with fputs(): Bad file descriptor

PS: я новичок в C, я много читал и читал об указателях на YouTube, но я не понимаю ошибки.

заранее спасибо


person Patrick    schedule 04.11.2018    source источник
comment
Пожалуйста, не используйте магические числа. Ничто не говорит о том, что ошибка ENOENT должна равняться значению 2. Вместо этого используйте символические именованные константы. Также будет легче понять, какую ошибку вы обрабатываете.   -  person Some programmer dude    schedule 04.11.2018
comment
Нет смысла передавать указатель на FILE*, кроме как сделать ваш код более трудным для чтения.   -  person Swordfish    schedule 04.11.2018
comment
@Swordfish Ты уверен? Проект стандарта C11 n1570, 7.21.3 Файлы: 6 Адрес объекта FILE, используемого для управления потоком, может иметь значение; копия объекта FILE не обязательно должна служить вместо оригинала.   -  person EOF    schedule 04.11.2018
comment
@EOF Я ничего не говорил о копировании файла FILE. Параметр совершенно бесполезен, и функция должна возвращать FILE*.   -  person Swordfish    schedule 04.11.2018
comment
@Swordfish В этом конкретном случае возврат FILE* действительно позволит избежать передачи FILE**, однако в целом этого не всегда можно избежать из-за ограничения единственного возвращаемого значения функции.   -  person EOF    schedule 04.11.2018
comment
@EOF Я ничего не сказал и об общих случаях. Я сказал, что это БЕССМЫСЛЕННО в ЭТОМ случае.   -  person Swordfish    schedule 04.11.2018
comment
@Swordfish Ну, мне ужасно жаль, что я не смог прочитать невидимую часть вашего первоначального комментария, в которой указывалось, что вы предлагаете использовать возвращаемое значение и говорите только об этом конкретном случае. Виноват.   -  person EOF    schedule 04.11.2018
comment
@EOF Я думал, что будет совершенно ясно, что я говорю о рассматриваемой функции.   -  person Swordfish    schedule 04.11.2018
comment
У вас есть switch (errno) { case 2: — это 2 должно быть ENOENT или что-то подобное. Не записывайте номера ошибок (значения errno) буквально; это ограничивает надежность и ясность вашего кода. (Однако проверка errno == 0 допустима.)   -  person Jonathan Leffler    schedule 04.11.2018


Ответы (1)


Вы открыли файл с помощью "r", но пытаетесь писать. Вместо этого вам нужно "w".

person Cyber    schedule 04.11.2018
comment
Между прочим, как описано на странице руководства, man7.org/linux/man- pages/man3/fopen.3.html, режим записи может автоматически создать файл, если он не существует, что устраняет ваш switch и большую часть вашего кода. - person Daniel Farrell; 04.11.2018
comment
Да, но если файл существует, w-режим удалит его без какого-либо уведомления, поэтому я хочу обработать ошибку - person Patrick; 04.11.2018