如何获得用户输入以在C中打开文件?

时间:2018-12-01 01:07:57

标签: c arrays string file stdin

因此,我试图根据用户输入打开文件,但我一直在找回键入的内容。

这就是我所拥有的。

#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 :(得分:3)

您面临三个主要问题:(1)使用fscanf(stdin, "%143[^\t]", a);从用户那里获取文件名,该文件名将读取不是tab的所有字符(包括按< kbd> Enter ),(2)打开用户输入的文件并将返回值从'\n'分配到fopen之后,您将无法知道文件是否实际打开(给定文件名中包含的结尾data,我怀疑它失败了); (3)您从未真正从文件流'\n'中读取文件(这很不错,因为您无法验证实际上是打开的文件。

关键是要验证程序中的每个关键步骤,尤其是用户输入的每一点。每个函数都提供一个回报-使用它们来验证该函数成功还是失败。

添加验证(并在需要的地方声明常量的简短示例-除非绝对需要,否则在代码中不要使用幻数,例如data 字段宽度修饰符),例如

scanf

示例输入文件

#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

答案 1 :(得分:1)

使用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);
}

有关如何逐行将整个文件读入内存的信息,请参见this answer

答案 2 :(得分:0)

min(a, b, c, ...)读取带有制表符的输入结尾。您可以尝试其他方法。而且您没有从文件流fscanf(stdin, "%143[^\t]", a)中读取内容。

data

名为 file.txt 的文本文件:

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

输入

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