0

Я не знаю в чем проблема, вчера у меня все прекрасно работало, сегодня захожу в VS дошлифовать код, и файл, который должен хранить БД, отказывается открываться. Если вначале работы программы выбираю "создать новый файл, и начать работу в нем" то в названии файла записывается рандомные символы. Вот часть кода:

printf("Продолжить работу в старом файле?\n"
        "(1)-Да (0)-Нет, я хочу создать новый\n->");
    scanf("%d", &access_mode);
printf("Введите название файла (name.txt)\n-> ");
scanf("%[^\n]", fname);

do {
    system("cls");

    if (access_mode == 1) {
        if ((cfPtr = fopen(fname, "r+")) == NULL) {
            printf("File could not be opened.\n");
            return 0;
        }
    }
    else {
        if ((cfPtr = fopen(fname, "w+")) == NULL) {
            printf("File could not be opened.\n");
            return 0;
        }
        access_mode = 1;
    }

https://ideone.com/lIQWkT

rendy
  • 49
  • 7
  • Как именно вы вводите данные? Если вы ввели символ 0, затем сразу нажали Enter, то события развиваются следующим образом: 1) Ноль считывается в переменную access_mode, во входном потоке остаётся символ перевода строки, 2) Здесь scanf("%[^\n]", fname) первый же символ, который пытается считать scanf() — это перевод строки. Но он не соответствует маске. scanf завершает свою работу, не записав ни единого символа в fname. – wololo Mar 12 '21 at 10:40
  • @wololo ну так раньше то все работало, и название файла считывалось и открывалось. Если же я заменю scanf() на fgets(), особо ничего не поменяется. – rendy Mar 12 '21 at 10:53
  • 1
  • fgets() также считывает символы пока не наткнётся на перевод строки. А ваш поток как раз с перевода строки и начинается. Перед тем как читать имя файла опустошите входной поток. int tmp = EOF; while((tmp = getchar()) != '\n' && tmp != EOF);. 2) ну так раньше то все работало. Обращение к неинициализированной переменной вызывает неопределённое поведение. Предсказать результат работы программы нельзя. Одна из возможных реализаций неопределённого поведения — «программа работает через раз».
  • – wololo Mar 12 '21 at 11:12
  • @wololo спасибо за объяснение стало понятнее, но вот только я не до конца понимаю написанную вами строку int tmp = EOF; while((tmp = getchar()) != '\n' && tmp != EOF); Разве не проще написать while (getchar() != '\n'); – rendy Mar 12 '21 at 11:20
  • 1
  • Объявляем переменную tmp: int tmp = EOF;. Заодно и инициализировали, но в данном конкретном случае это не обязательно, можно написать и так int tmp;. 2) В цикле делаем следующее: a) Считываем один символ tmp = getchar() в переменную tmp. b) Если считанный символ отличен от символа перевода строки (tmp = getchar()) != '\n' и отличен от символа конца файла && tmp != EOF, то выполняем очередную итерацию цикла. Обратите внимание на точку с запятой ; после цикла.
  • – wololo Mar 12 '21 at 11:27
  • Разве не проще написать while (getchar() != '\n'); Проще, и это будет работать. Но в принципе во входном потоке может оказаться и символ конца файла. Например, если вы перенаправите ввод из файла. Цикл while (getchar() != '\n'); при встрече конца файла станет бесконечным. – wololo Mar 12 '21 at 11:33