繁体   English   中英

如何从C中的用户输入正确读取文件?

[英]How to read in file properly from user input in C?

我正在尝试读取用户输入并打开用户输入的文件。 我的程序似乎在打印语句之后立即退出。 任何帮助,将不胜感激!

  printf("What is the name of the file? \n");
  scanf("%s", "fileName");
  FILE* inFile = NULL;
  inFile = fopen("fileName", "r");
  if(inFile == NULL) {
    printf("Could not open this file");
  }

您问题的根源(正在使用scanf ,但这完全是一个不同的问题)是:

scanf("%s", "fileName");

那应该是:

char fileName[128];
if( 1 == scanf("%127s", fileName)) ...

您不能写入字符串文字,因此将字符串文字的地址传递给 scanf 是一场等待发生的灾难。 您确实应该使用 PATH_MAX 而不是硬编码的 128,但是您需要使用 sprintf 来构造格式字符串,这似乎有损本示例。 为了完整性:

#include <limits.h>
...
char fileName[PATH_MAX];
char fmt[64];
snprintf(fmt, sizeof fmt, "%%%ds", PATH_MAX - 1);

if( 1 == scanf(fmt, fileName) ){
    FILE* inFile = fopen(fileName, "r");
    if( inFile == NULL ){
        perror(fileName); 
        exit(EXIT_FAILURE);
    }
    ...
}

但请注意,您几乎肯定不想使用scanf从输入流中读取输入文件。 最好将其作为命令行参数并在argv可用。

继续我的评论,直到您彻底了解scanf()的陷阱,建议您对所有用户和文件输入使用fgets() ,以便您在每次读取时使用完整的输入行。 这样,输入流中保留的内容不取决于使用的转换说明符以及是否发生匹配失败 如果您随后需要从fgets()读取的行中提取信息,您可以使用sscanf()并且无论sscanf()成功还是失败,它都不会影响输入流中未读的内容。

所有面向行的输入函数fgets()和 POSIX getline()读取并包含'\\n'作为它们填充的缓冲区的一部分。 您只需修剪'\\n'从存储线您的来电后,结束fgets()使用strcspn()来确定字符前的数'\\n' ,然后覆盖'\\n'nul-终止字符'\\0' (它只是 ASCII 0 )。

您以完全相同的方式处理用户输入或从文件中读取的行。 例如,您可以提示用户输入文件名,读取输入,打开文件,然后读取文件中的所有行,如下所示:

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

#define MAXC 1024       /* if you need a constant, #define on (or more) */

int main (void) {
    
    char fname[MAXC], line[MAXC];                   /* storage for filename & line */
    FILE *fp = NULL;                                /* FILE pointer */
    
    fputs ("enter filename: ", stdout);                     /* prompt */
    
    if (!fgets (fname, MAXC, stdin) || *fname == '\n') {    /* check EOF or empty line */
        puts ("(user canceled input)");
        return 1;
    }
    fname[strcspn (fname, "\n")] = 0;                       /* trim \n from end */
    
    if (!(fp = fopen (fname, "r"))) {               /* validate file open succeeds */
        perror ("fopen-fname");                     /* fopen sets errno on failure */
        return 1;
    }
    
    putchar ('\n');                                 /* provide space before output */
    while (fgets (line, MAXC, fp)) {                /* read each line from file */
        line[strcspn (line, "\n")] = 0;             /* trim \n from end */
        puts (line);                                /* output line */
    }
    
    fclose (fp);                                    /* close file when done */
}

请注意,在进行任何类型的输入时,必须验证每一步。 否则,如果验证失败,并且输入失败,并且盲目使用包含不确定值的变量,则会调用未定义行为

示例使用/输出

$ ./bin/readfile
enter filename: dat/fleas.txt

My dog has fleas
My cat has none
Lucky cat

fgets()提供了处理输入的最强大的方法之一。 您也可以使用scanf() —— 只要您了解与其使用相关的每个陷阱并防范它。 如果您还有其他问题,请告诉我。

您可以使用fscanf()函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM