【问题标题】:Trouble using fscanf in C在 C 中使用 fscanf 时遇到问题
【发布时间】:2014-03-02 05:52:20
【问题描述】:

我在使用 fscanf 从文件中读取字符串并打印每个字符串中的字母数时遇到了困难。该文件如下所示:

ACGTTTTAAGGGCTGAGCTAGTCAGTTCATCGCGCGCGTATATCCTCGATCGATCATTCTCTCTAGACGTT ACGTTTTAAGGGCTTAGAGCTTATGCTAATCGCGCGCGTATATCCTCGATCGATCATTCTCTCTAGACGTT TCGTTTGAAGGGCTTAGTTAGTTAGTTCATCGGCGGCGTATATCCTCGATCGATCATTCTCTCTCTAGACGTT //文件结束

(文件中的每一行都是一个单独的字符串,每个字符串的最大字符数为241)

这是我尝试过的,但似乎不起作用:

include <stdio.h>
FILE *input;

int main ()

{

  int i=0, count=0;

  char sequence[241];

  /*reads DNA sequence from input, stores it in an array, and returns the # of                 
  letters read as an int */

  input=fopen("dna_input.dat", "r");

  while (fscanf(input, "%c", &sequence[i++]) != EOF)     
     count++;

  printf ("The number of letters in a sequence is: %d\n", count);

  return 0;    
}

【问题讨论】:

  • while 循环将\n 作为序列的一部分。使用fgets()
  • fscanf 返回分配的输入项的数量,而不是 EOF 指示符。此外,如果您只想从文件中读取一行,请尝试fgets,然后在结果上使用strlen
  • 为什么要逐字阅读?读取整个字符串并找到它的长度。
  • 你的目标是什么,你想打印文件/你想逐行读取文件还是逐字符读取文件??
  • 很抱歉给您带来了困惑。这个函数是我正在尝试调试的另一个程序的一部分。我的另一个程序中的实际函数声明是:int read_DNA(char sequence[])。目标是从输入文件中读取“DNA”序列,将其存储在数组 sequence[] 中并返回读取的字母数。

标签: c file input scanf


【解决方案1】:

您的代码中没有任何内容可以识别行尾——只有文件的结尾。此外,您正在将整个文件读入一个仅足够容纳一行的缓冲区。而且,您打算打印每一行的结果,还是只打印整个文件?因为它在做后者(如果它没有先从缓冲区溢出崩溃)。

假设每行:

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

int main()
{
    FILE *input;
    char sequence[242];

    input = fopen("dna_input.dat", "r");
    while (fgets(sequence, 242, input) != NULL)
    {
        printf("The number of letters in a sequence is: %d\n",
               strlen(sequence) - 1); /* don't count trailing \n */
    }
    fclose(input);
    return 0;
}

是的,抱歉,我在这里没有找到 fscanf() 的用途。 :)

【讨论】:

  • #include &lt;strlen.h&gt;?
  • Braino -- string.h (for strlen)
【解决方案2】:

对读取字符并处理它们的代码稍作改动:

#include <stdio.h>
FILE *input;

int main ()

{

  int i=0, count=0;

  char sequence[241];

  /*reads DNA sequence from input, stores it in an array, and returns the # of                 
  letters read as an int */

  input=fopen("dna_input.dat", "r");

  int c ;
  while ( (c = fgetc(input) != EOF))
  {
     if ( c != '\n')
     {
        sequence[i++] = c;
        count++;
     }
     else
     {
        printf ("The number of letters in a sequence is: %d\n", count);

        /* Terminate the sequence with a null character */
        sequence[i] = '\0';

        /* Reset the counters */
        i = 0;
        count = 0;
     }
  }

  /* Take care of the last line if it does not end in a newline character */
  if ( count > 0 )
  {
     printf ("The number of letters in a sequence is: %d\n", count);
  }

  return 0;    
}

另外,如果您希望sequence 成为一个以空字符结尾的字符串,您可能希望将其创建为一个包含 242 个字符的数组,最后一个用于存储以空字符结尾的字符。

【讨论】:

  • 如果最后一行 is 不包含终止换行符怎么办?这将只打印到文件中的倒数第二行。
  • @ajay 观察力不错。让我编辑答案来解决这个问题。
【解决方案3】:

这里的主要问题是 fscanf 不返回它读取的字符,因此它永远不会返回 EOF。另外,要记住的是换行符 (\n) 被视为一个字符,因此您可能需要将其过滤掉。另一个更安全的选择是只使用 fgets() 来读取您的输入:

fgets() instruction manual

编辑:既然您想知道 cmets,您需要知道的一件事是字符串的结构。字符串是以 0 也就是 '\0' 结尾的字符数组(不要与 '0' 混淆)。手动查找字符串长度的方法是:

char *str = "Hello, world!";
int len = 0;
while (str[len] != 0)
    len++;

基本上你正在做的是遍历字符串,每次你到达一个不为零的字符时,你都会增加长度,当你到达一个为 0 的字符时,你会停止。希望这会有所帮助!

【讨论】:

  • 谢谢。我现在使用 fgets() 而不是 fscanf(),但我仍然不确定如何成功打印每行读取的字母数。这是作业的一部分,我不能使用 strlen。
  • 在做之前你应该知道C字符串结构。只需找到空终止字节,即字符串的结尾
  • @user3303851 我刚刚添加了关于字符串及其长度的部分
【解决方案4】:

fscanf 返回成功匹配和分配的项目数,可以少于提供的数量,在早期匹配失败的情况下甚至为零。但是,如果在第一次成功转换或匹配失败发生之前到达输入结尾,则返回 EOF。此外,格式字符串中的%c 转换说明符匹配所有字符,包括空格。

fscanf 的上述两个特性意味着你的while 循环条件只有在fscanf 到达文件末尾时才会为false,但在此之前它可能会溢出@987654328 指向的缓冲区@ 如果文件有超过 241 个字符。这是未定义的行为,很可能会导致段错误。

您应该改用fgetsfgets 还会读取一个换行符,如果遇到一个换行符,则将其存储在缓冲区中,然后再返回。文件中的所有行都将以换行符终止,但最后一行可能不包含终止换行符。您还应该检查文件 I/O 错误。

#include <stdio.h>

int main(void) {
    int len; 
    char sequence[241 + 1]; // +1 for the terminating null byte
    FILE *input = fopen("dna_input.dat", "r");
    if(input == NULL) {     
        printf("Error in opening the file\n");
        return -1;
    }
    while(fgets(sequence, 242, input) != NULL) {
        len = strlen(sequence);
        if(sequence[len-1] == '\n')
            --len;
        printf("The number of letters in the sequence is: %d\n", len);
    }
    fclose(input);
    return 0;
}

【讨论】:

    猜你喜欢
    • 2015-08-04
    • 2017-12-04
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 2013-02-25
    • 2015-10-21
    • 1970-01-01
    相关资源
    最近更新 更多