在C中使用fscanf时遇到麻烦

时间:2014-03-02 05:52:20

标签: c file input scanf

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

  

ACGTTTTAAGGGCTGAGCTAGTCAGTTCATCGCGCGCGTATATCCTCGATCGATCATTCTCTCTAGACGTT   ACGTTTTAAGGGCTTAGAGCTTATGCTAATCGCGCGCGTATATCCTCGATCGATCATTCTCTCTAGACGTT   TCGTTTGAAGGGCTTAGTTAGTTAGTTCATCGGCGGCGTATATCCTCGATCGATCATTCTCTCTAGACGTT   //文件结尾

(文件中的每一行都是一个单独的字符串,每个字符串中的最大字符数为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;    
}

4 个答案:

答案 0 :(得分:2)

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

假设每行:

#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()的使用方法。 :)

答案 1 :(得分: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个字符的数组,最后一个字符用于存储终止空字符。

答案 2 :(得分:1)

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

fgets() instruction manual

编辑:因为您在评论中想知道,您需要知道的一件事是字符串的结构。字符串是一个字符数组,以0表示'\ 0'结尾(不要与'0'混淆)。手动查找字符串长度的方法是:

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

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

答案 3 :(得分:1)

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

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

您应该使用fgets代替。 fgets还会读取换行符,如果遇到换行符,则将其存储在缓冲区中,然后再返回。除最后一行(可能不包含终止换行符)外,文件中的所有行都将换行。您还应该检查文件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;
}