【问题标题】:Reading in char from file into struct将字符从文件读入结构
【发布时间】:2015-04-16 17:34:11
【问题描述】:

对于我的作业,我必须读入一个包含不同行数的文本文件。它们遵循以下格式:

AACTGGTGCAGATACTGTTGA
3
AACTGGTGCAGATACTGCAGA
CAGTTTAGAG
CATCATCATCATCATCATCAT

第一行是我将测试以下行的原始行,第二行给出剩余行数。

我在尝试将这些保存到结构时遇到问题,甚至无法保存第一行。我尝试将 void 函数与数组一起使用,它似乎可以工作,但似乎无法将其转移到结构中。

到目前为止,这是我的代码:

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

#define LENGTH 25
struct dna {
    char code[LENGTH];
};
int main(){
    char filename[] = "input1.txt";
    FILE *input = fopen("input1.txt","r");

    char firstDna[LENGTH]="";

    struct dna first;
    struct dna first.code[]= "";

    makeArray(input,first);

//  printf("%s",filename);


    system("pause");
    return 0;
}
void makeArray(FILE *input,struct dna first){
    int i=-1;
    //nested for loops to initialze array
    //from file
    while(i != '\n'){
       fscanf(input,"%c",first[i].code); 
       printf("%c", first[i].code);
       i++;
    }//closing file
    fclose(input);
}

【问题讨论】:

  • 是否有理由需要使用结构?在这种情况下,将其存储在 char 数组中会更有意义。您的代码也存在其他问题,但让我们从这个开始。
  • 唯一的原因是为了获得额外的荣誉,我想尝试掌握它,但除此之外,char 数组也可以工作! @PandaConda
  • 首先,这将无法成功完成编译。
  • @BLUEPIXY 我知道,我只是对这一切感到完全困惑。
  • 实际片段大小在24 碱基上似乎非常小。这个限制是作业的一部分吗?分配中是否指定了struct dna

标签: c file-io struct


【解决方案1】:

由于这是一个课堂作业,我想先说处理这些类型的作业的一个好方法是将其分解为任务,然后一个一个地实施它们,最后将它们连接起来。在这种情况下,任务可能类似于:

  • 将第一行解析为一个(包含一个)char 数组的结构。
  • 将数字解析为 int 变量
  • 像处理第一行一样解析文件中剩余的每一行
  • 针对文件中的其他行测试第一行(数字除外)

您还在评论中提到该结构是为了额外的功劳。出于这个原因,我建议首先使用 char 数组来实现它,然后在基本版本正常工作后将其重构为结构。这样你就有了一些可以依靠的东西,以防万一。在这一点上,这种开发方式似乎没有必要,但对于更大更复杂的项目,它变得更加重要,所以尽早养成确实是一个好习惯。

现在,让我们看一下代码。我不会在这里给你这个程序,但我会找出我在其中看到的问题。

让我们从main方法开始:

char filename[] = "input1.txt";
FILE *input = fopen("input1.txt","r");

这将打开您正在读取的文件。您正确打开了它,但在这种情况下第一行是不必要的,因为您实际上从未在任何地方使用文件名变量。

您还可以在 makeArray 函数的末尾正确关闭文件:

fclose(input);

哪个有效。但是,如果在调用 makeArray 函数后将其放入 main 方法中,这可能会更好。如果可能,在同一个函数中打开和关闭文件总是一个好主意,因为这意味着您将始终知道您没有忘记关闭文件,而无需查看整个程序。同样,在一个小项目中并不是一个真正的问题,而是一个养成的好习惯。另一种解决方案是将fopenfclose 函数放在makeArray 函数中,因此main 不必知道它们,然后只需将包含文件路径的char 数组发送到makeArray而不是FILE*

我看到的下一个问题是如何将参数传递给makeArray 函数。首先,不要使用单独的函数,而是尝试将所有内容都放在 main 方法中。使用函数是一种很好的做法,但这样做只是为了让某些东西发挥作用。

完成后,您需要注意的是,如果您要向/从函数传递或返回数组或指针,则需要查找 mallocfree 函数,您可以还没有覆盖。这可能是 C 语言中较为复杂的部分之一,因此您可能希望将其留到最后。

其他一些东西。我不会详细介绍这些内容,但会尝试了解概念,而不仅仅是复制粘贴:

  • struct dna first.code[]= ""; 应该是 first.code[0] = \0;\0 在 C 中用于终止字符串,因此这会使字符串为空。
  • %c 传递给fscanf 读取单个字符(您也可以为此使用fgetc)。在这种情况下,使用%s 可能会更容易,它会将单词作为字符串返回。
  • 假设您确实使用了%s,您可能应该这样做,您需要在循环之前调用它两次 - 一次获取第一个 DNA 序列,另一次获取其他 DNA 序列的数量(迭代次数)。
  • 循环的每次迭代都会根据文件中的下一个 DNA 序列测试原始 DNA 序列。

希望对你有帮助!

【讨论】:

  • first.code = "" 不起作用。 *first.code = '\0'first.code[0] = '\0' 会。
  • fscanf() 不会逐行读取,它在 OP 的代码中一次读取一个字符。
  • 非常感谢您的回复!将文件名保存为 char 用于稍后的作业,我还没有将 printf 语句与所有其他内容一起正式化。我将如何第二次调用fscanf 以获取实际剩余行数?我意识到如何将其保存为变量并在不同的循环中使用它来保存剩余的行,但我不确定它如何让它只处理第二行。我在函数中找到的while 循环是否可以按原样获取第一行?再次感谢! @PandaConda
  • first.code 是一个数组,不能用first.code = ""; 设置。你可以写strcpy(first.code, "");,但更简单的方法是将第一个字节设置为'\0'
  • @bravesaint:你明白了:P
【解决方案2】:

要修复的样本

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

#define LENGTH 25

struct dna {
    char code[LENGTH];
};

struct dna *makeArray(FILE *input, int *n);//n : output, number of elements

int main(void){
    char filename[] = "input1.txt";
    FILE *input = fopen(filename,"r");

    struct dna first = { "" };
    fscanf(input, "%24s", first.code);//read first line
    printf("1st : %s\n", first.code);

    int i, size;
    struct dna *data = makeArray(input, &size);//this does close file

    for(i = 0; i < size; ++i){
        printf("%3d : %s\n", i+1, data[i].code);
    }
    free(data);//release data

    system("pause");
    return 0;
}

struct dna *makeArray(FILE *input, int *n){//n : output, number of elements
    int i;

    fscanf(input, "%d", n);//read "number of remaining lines"

    struct dna *arr = calloc(*n, sizeof(struct dna));//like as struct dna arr[n] = {{0}};

    for(i = 0; i < *n; ++i){
        fscanf(input, "%24s", arr[i].code);
    }
    fclose(input);

    return arr;
}

【讨论】:

  • 这似乎工作得很好。我只是在试图阅读它时不知所措,因为我无法完全理解某些部分发生的事情。例如:'struct dna *data' - 保存在哪里?这完全是一个新结构吗? 'fscanf(input, "%d", n)' 只是读取文本文件的第二行并将其保存为 "n",对吗?我也不知道 'calloc(*n, sizeof(struct dna))' 是做什么的?!不过非常感谢!
  • 虽然这是一个解决方案,但我认为对于这样的问题,稍微解释一下这些概念会很有用。例如,我怀疑bravesaint 之前是否会涵盖%24s、引用和解除引用或calloc/free 等内容。
  • 关闭makeArray() 中的文件是非常糟糕的风格。您还应该测试您是否真的可以阅读size片段。
  • 1) struct dna *data 收到makeArray 的返回。 makeArray 是在堆上分配的内存区域。
  • 2) fscanf(input, "%d", n)' : n 是由 &amp;size 在 main 传递的指针。
【解决方案3】:

一个简单的解决方法可能是:

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

#define LENGTH 25

struct dna {
    char code[LENGTH];
};

void makeArray(FILE *input,struct dna *first){
    int i=0;
    fscanf(input,"%c",&first->code[i]);
    printf("%c",first->code[i]);
    while(first->code[i] != '\n' && i < LENGTH){
        i++;
        fscanf(input,"%c",&first->code[i]);
        printf("%c",first->code[i]);
    }
}

int main() {
    struct dna first;
    char filename[] = "input1.txt";
    FILE *input     = fopen(filename,"r");
    makeArray(input,&first);
    fclose(input);
    printf("%s",first.code);
    return 0;
}

PS:我试图不更改您的原始代码 为了更改 makeArray 函数中的代码[长度],您必须传递它的地址,这就是我以这种方式调用 mkaeArray 函数的原因:makeArray(input,&amp;first);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 2021-02-15
    • 2021-02-13
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多