Позвольте пользователю указать имя файла в C - PullRequest
0 голосов
/ 21 марта 2019

Это мой код:

char filename[30];
FILE *fp;
printf(" Enter the filename: ");
gets(filename);
strcat(filename,".txt");
fp=fopen("e:\\filename","a+");

Итак, моя проблема в том, что я хочу, чтобы пользователь указал имя файла, затем открыл этот файл и записал его.Но каждый раз, когда я запускаю этот код, он открывает файл с именем: filename вместо открытия значения, которое присутствует в строке filename [30].

1 Ответ

2 голосов
/ 21 марта 2019

Вы «Танцуете на наземной мине» и заигрываете с Неопределенное поведение , объединяя текст без проверки, достаточно ли символов в filename перед вызовом strcat.Что делать, если пользователь вводит 26 символов filename (или более)?(подсказка: неопределенное поведение)

Это усугубляется тем фактом, что вы используете gets для ввода.gets настолько небезопасен и подвержен переполнению буфера, что был полностью удален в C11.Если ваш профессор предлагает использовать gets - обратитесь к другому профессору.См .: Почему get () настолько опасен, что его никогда не следует использовать!

Вместо этого используйте fgets или POSIX getline, чтобы прочитать filename, защищая границы ваших массивов с помощью fgets или динамически выделяя столько памяти, сколько необходимо для filename в случае getline.

Все линейно-ориентированный ввод функции, такие как fgets и getline read и включают завершающий '\n' в буферах, которые онизаполнить.Вам просто нужно обрезать '\n' от конца строки.Вы можете сделать это путем получения длины с помощью strlen и установки buffer[strlen(buffer) - 1] = '\0'; или с помощью функции strcspn, которая обеспечивает немного больше функциональности за один вызов.

В целом, вы можете сделать что-то подобноек следующему (это просто выводит вызов fopen вместо фактического открытия файла):

#include <stdio.h>
#include <string.h>

#define MAXC 30         /* if you need a constant, #define one (or more) */
#define FEXT ".txt"     /* (including string constants) */

int main (void) {

    char filename[MAXC];
    size_t  available = MAXC - 1,   /* chars available in filename */
            length = 0,
            extlen = strlen (FEXT);
    FILE *fp;

    fputs (" Enter the filename: ", stdout);    /* no conversion needed */
    if (!fgets (filename, MAXC, stdin)) {
        fputs ("(user canceled input)\n", stderr);
        return 1;
    }

    /* trim '\n' from end of filename saving length using strcspn() */
    filename[(length = strcspn (filename, "\r\n"))] = 0;

    if (available - length < extlen) {
        fprintf (stderr, "error: insufficient space available for '%s'.\n", 
                FEXT);
        return 1;
    }

    strcat (filename, FEXT);
    /* just output what would be done */
    printf ("fp = fopen (\"e:\\%s\",\"a+\");\n", filename);
}

Пример использования / Вывод

В примере просто выводится то, чтоон откроется (а не будет фактически открывать файл), например,

$ ./bin/strcatext
 Enter the filename: my_file_to_open
fp = fopen ("e:\my_file_to_open.txt","a+");

, а затем проверит, что ваш код примет имя файла из 25 символов плюс расширение из 4 символов, например,

$ ./bin/strcatext
 Enter the filename: 1234567890123456789012345
fp = fopen ("e:\1234567890123456789012345.txt","a+");

И отклоняет 26-символьное имя файла, например,

$ ./bin/strcatext
 Enter the filename: 12345678901234567890123456
error: insufficient space available for '.txt'.

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...