【问题标题】:How to read Text Files into 2d Arrays?如何将文本文件读入二维数组?
【发布时间】:2021-12-19 10:41:00
【问题描述】:

好的,我正在制作一个评分程序/代码,它将有自己的文本文件,用于存储所有成绩。我想制作一个二维数组,其中第一个“维度”是学生,第二个“维度”是个人成绩(如果有更聪明的评分方式告诉我,顺便说一下,我选择了这种方法,因为它是唯一的我知道以后如何才能添加更多学生或更多成绩)请记住,成绩和学生的数量并不总是固定的,因此没有简单的出路。无论如何,我已经尝试了一些东西,我认为它只适用于字符而不适用于整数(即使等级是 1-5)。我也想要一种打印出来的方法,但我认为这是更大的问题。如果我找到解决方案,我会在此处发布,以便如果其他人对此有问题,他们可以在这里找到答案,无论如何谢谢

    typedef char string [20];
    string row;
    int i=0,j=0;
    char arr[20][20];
    FILE *fp;
    fp=fopen("grades.txt","r");
    for(i=0;arr[i-1][j]!=EOF;i++)
    {
        fgets(row,sizeof(row),fp);//I used fgets so I could get the size of the line
        for(j=0;j<strlen(row);j++)
        {
            fscanf(fp,"%c ",&arr[i][j]);
        }
    }

我不知道它是否会有所帮助,但我认为文本文件看起来像这样:
54455
43544
22443
21232
21121

【问题讨论】:

标签: arrays c file multidimensional-array text-files


【解决方案1】:

fgets 报告它是否有效。因此,读取到文件末尾或缓冲区已满:

for(i = 0; i < sizeof arr / sizeof *arr && fgets(arr[i], sizeof arr[i], fp); i++)
{
    // probably remove the \n that fgets writes into the buffer
    // otherwise nothing else to do
}

网站注释:

  • fgets 从文件中读取,无需额外读取 fscanf
  • fgets 读取包含换行符的行,如果您不想要它,请将其删除
  • 您需要检查fopen 是否有效

【讨论】:

  • 感谢您的帮助!但它不太好用,也许这是我在打印代码或删除 \n 时的错误,对不起,如果我有点笨,因为我有点新,无论如何这是我的代码:(该死的丑陋,我不要认为我可以在评论中做得更好
  • for(i = 0; i &lt; sizeof arr / sizeof *arr &amp;&amp; fgets(arr[i], sizeof arr[i], fp); i++) { row[strcspn(row, "\n")] = 0; for(j=0;j&lt;strlen(row);j++) { fscanf(fp,"%c ",&amp;arr[i][j]); } } printf("\n"); for(i=0;i&lt;5;i++) { printf("\n"); for(j=0;j&lt;5;j++) { printf("%c",arr[i][j]); } } }
  • 为什么要使用fscanf 来读取文件?您已经使用fgets 阅读过它。只需使用我的代码并删除 row 变量即可。
【解决方案2】:

我发现了在struct 中存储学生成绩的最佳方式。一般来说,每个学生都有名字、姓氏、成绩……你可以添加任何你想要的东西。我对fnamelnamegrades 很好。

typedef struct student_s {
    char fname[25];
    char lname[25];
    int* grades;
    int count_of_grades;  // Track number of grades for each student
} student_t;

通过分配student_t 的动态数组,您可以获得尽可能多的学生。

 // Allocate array of structs
 student_t* students = (student_t *) malloc(sizeof(student_t));

通过使用getline(),您可以一次从文件中读取整行(行以\n 结尾)。 getline() 不是标准的 C 函数,因此您需要将 #define _GNU_SOURCE 放在脚本的开头。

while ((read_len = getline(&line, &len, fp)) != -1)

函数getline()每次读取文件的下一行,数组大小count将递增并重新分配数组。

++count;
// Increase size of array beacause of new student to add
students = realloc(students, sizeof(student_t) * count);    
if (students == NULL)
{
    printf("Couldn't allocated memmory\n");
    return 1;
}

下一步是分配grades 数组,该数组将存储特定学生的所有成绩。循环通过line,您可以提取每个等级。然后只需定义 struct 的成员,您就可以为每个学生添加成绩。

// Allocate array to store all grades from file for one student
// Count of grades does not have to be the same for every student
students[index].grades = (int *) malloc(sizeof(int) * (read_len-1));

// Iterate grades read from file
for (int i=0; i<read_len-1; ++i)
{   
    // char --> char *
    char grade[2] = "\0";
    grade[0] = line[i];

    // Add grade to the array of grades
    students[index].grades[i] = atoi(grade);
}

最后,您应该将成绩数存储在数组中,以便稍后在脚本中对数据进行简单操作。

// Track number of grades
students[index].count_of_grades = read_len-1;
++index

完整代码:

#define _GNU_SOURCE    // necessery to use getline()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct student_s {
    char fname[25];
    char lname[25];
    int* grades;
    int count_of_grades;
} student_t;


int main(int argc, char const *argv[])
{
    // Allocate array of structs
    student_t* students = (student_t *) malloc(sizeof(student_t));  
    int count = 0;
    int index = 0;

    FILE* fp;
    char* line = NULL;
    size_t len = 0;
    ssize_t read_len;

    fp = fopen("data.txt", "r");
    if (fp == NULL)
    {
        return 1;
    }

    // Read line by line from file until fp reaches end of file
    while ((read_len = getline(&line, &len, fp)) != -1)
    {
        ++count;
        // Increase size of array beacause of new student to add
        students = realloc(students, sizeof(student_t) * count);    
        if (students == NULL)
        {
            printf("Couldn't allocated memmory\n");
            return 1;
        }

        // Replace with your code, which adds name to struct or get rid of it (also from struct)
        memcpy(students[index].fname, "John", 4);
        memcpy(students[index].lname, "Wash", 4);
        
        // Allocate array to store all grades from file for one student
        // Count of grades does not have to be the same for every student
        students[index].grades = (int *) malloc(sizeof(int) * (read_len-1));

        // Iterate grades read from file
        for (int i=0; i<read_len-1; ++i)
        {   
            // char --> char *
            char grade[2] = "\0";
            grade[0] = line[i];

            // Add grade to the array of grades
            students[index].grades[i] = atoi(grade);
        }

        // Track number of grades
        students[index].count_of_grades = read_len-1;
        ++index;
    }

    fclose(fp);
    if (line)
    {
        free(line);
    }

    // Print data from structs
    for (int i=0; i<count; ++i)
    {
        printf("%s: ", students[i].fname);
        for (int j=0; j<students[i].count_of_grades; ++j)
        {
            printf("%d ", students[i].grades[j]);
        }
        printf("\n");
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    相关资源
    最近更新 更多