Как получить пользовательский ввод для открытия файла в C? - PullRequest
0 голосов
/ 01 декабря 2018

Так что я пытаюсь открыть файл на основе ввода пользователя, но я просто продолжаю получать то, что набрал обратно.

Это то, что у меня есть.

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

int main(void) 
{
  FILE* data;
  char a[144];
  printf("Enter a filename:\n");
  fscanf(stdin, "%143[^\t]", a);
  data = fopen(a, "r");
  printf("%s", a);
  fclose(data);
  return 0;
}

Этомой текстовый файл.

larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane

Ответы [ 3 ]

0 голосов
/ 01 декабря 2018

Вы сталкиваетесь с тремя основными проблемами: (1) вы берете имя пользователя у пользователя с fscanf(stdin, "%143[^\t]", a);, которое будет читать все символы, кроме tab (включая завершающий '\n', генерируемый нажатием Enter ), (2) после открытия файла, введенного пользователем и присвоения возврата от fopen до data, у вас нет возможности узнать, действительно ли файл открыт (учитывая завершающий '\n', включенный в имя файла,Я подозреваю, что это не удается);и (3) вы фактически никогда не читаете из файлового потока data (что, вероятно, хорошо, если вы не смогли VALIDATE он был фактически открыт.

Ключ к проверяет каждый критический шаг в вашей программе особенно каждый бит пользовательского ввода . Каждая функция обеспечивает возврат - использует их для проверки , была ли функция выполнена или не выполнена.

Короткий пример добавления проверки (и объявления константы там, где это необходимо - не используйте магические числа в своем коде, кроме случаев, когда это абсолютно необходимо - как в поле scanf -width модификатор), например

#include <stdio.h>

#define MAXC 1024   /* if you need a constant, define one (or more)
                           ( don't SKIMP on buffer size ) */

int main (void) 
{
    FILE* data = NULL;  /* initialize all variables */
    size_t nlines = 0;
    char a[MAXC] = "";

    printf("Enter a filename: ");

    /* VALIDATE EVERY SINGLE BIT OF INPUT */
    if (fscanf (stdin, " %1023[^\n]", a) != 1) {
        fputs ("user canceled input.\n", stderr);
        return 1;
    }
    /* open/VALIDATE file open for reading */
    if ((data = fopen (a, "r")) == NULL) {
        perror ("fopen-a");
        return 1;
    }

    printf ("file opened: %s\n\n", a);

    /* reuse buffer to read each line */
    while (fgets (a, MAXC, data) != NULL)
        /* fgets include '\n' in buffer if buffer of sufficient size */
        printf ("line[%3zu]: %s", nlines++ + 1, a);
    fclose(data);

    return 0;
}

Пример входного файла

$ cat dat/file.txt
larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane

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

$ ./bin/fopen_file_from_user
Enter a filename: dat/file.txt
file opened: dat/file.txt

line[  1]: larry snedden 123 mocking bird lane
line[  2]: sponge bob 321 bikini bottom beach
line[  3]: mary fleece 978 pasture road
line[  4]: hairy whodunit 456 get out of here now lane
0 голосов
/ 01 декабря 2018

fscanf(stdin, "%143[^\t]", a) чтение конца ввода с таб.Вы можете попробовать другой метод.И вы не читали из файлового потока data.

#include <stdio.h>
#include <string.h>
int main(void) 
{
   FILE* data;
   char a[144];
   printf("Enter a filename:\n");
   fscanf(stdin, "%s", a);  //use %s not 143[^t]
   data = fopen(a, "r");

   //read from the file
   char read_from_file[100];
   while (!feof(data)) {
       fgets(read_from_file, 1024, data);
       printf("%s", read_from_file);
   }
   print("\n")

   printf("%s", a);
   fclose(data);
   return 0;
}

текстовый файл с именем file.txt :

larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane

input :

file.txt

выход :

larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane
file.txt
0 голосов
/ 01 декабря 2018

Используйте fgets(), чтобы прочитать всю строку ввода:

#include <stddef.h>  // size_t
#include <stdlib.h>  // EXIT_FAILURE
#include <stdio.h>   // FILE, fprintf(), fputs(), fgets(), fopen(), fclose()
#include <string.h>  // strlen()

enum { MAX_FILENAME_LENGTH = 120 };

int main(void)
{
    char filename[MAX_FILENAME_LENGTH + 2]; // + '\n' + '\0'
    if (!fgets(filename, sizeof(filename), stdin)) {
        fputs("Input error :(\n\n", stderr);
        return EXIT_FAILURE;
    }

    size_t length = strlen(filename);  // get rid of the newline at the end:
    if (length && filename[length - 1] == '\n')
        filename[--length] = '\0';

    // When the length of the string is not needed, the above if-statement
    // can be replaced as suggested by Jonathan Leffler:
    filename[strcspn(filename, "\n")] = '\0'

    FILE *input = fopen(filename, "r");
    if(!input) {
        fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
        return EXIT_FAILURE;
    }

    // do stuff with input

    fclose(input);
}

См. этот ответ о том, как построчно читать весь файл в память.

...