C:将文本文件读入结构数组

时间:2013-12-08 21:45:38

标签: c arrays file struct records

在过去的两天里,我一直试图围绕这个问题,但仍然不知道如何做到这一点。几乎我必须创建一个函数( getRawData ),该函数传递一个指向已经打开的文件的指针,并传递一个结构数组和当前在该数组中的记录数(通过paramer currSize)。该函数是将文件中的数据读入数组,并将其放在数组的末尾,并在读取后返回文件中的记录总数。我的问题是我真的不知道如何读取文件并将数据存储到数组结构中,我一直在尝试读取文件/记录,但我仍然不知道该怎么做。有问题的函数是 getRawData

整个程序实际上有两个文件而不是一个(malebabynames.csv和femalebabynames.csv),程序的重点是让程序询问用户的名字,然后检查文件的记录,看看这个名字有多受欢迎。由于某些男孩名称和女孩名称可以互换,因此需要为用户输入的每个名称读取两个文件。这是我到目前为止的代码:

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

 struct nameRecord {
    char name[31];
    int year;
    int frequency;
};
struct nameRecord;
void allCaps(char[]);
int getRawData(FILE*, struct nameRecord[], int);
void setYearTotals(struct nameRecord[], int, int);
void setNameYearTotals(char, struct nameRecord[], int, int);
void getPerHundredThousand(int, int, double);
void printData(double);
void graphPerHundredThousand(double);

int main(void)
{
    int currSizem = 0;
    int currSizef = 0;
    struct nameRecord records[currSizem];
    FILE* fp = NULL;
    FILE* fp2 = NULL;
    char name[31];
    printf("Please enter your name: ");
    scanf("%30[^\n]", name);
    printf("your name is %s\n", name);

//opening both male and female name files and reading them in order to get the total number of records in the array
    fp = fopen("malebabynames.csv", "r");
    if (fp != NULL) {
        printf("file opened\n");
        while(3 == fscanf(fp, "%[^,],%d,%d", records[currSizem].name, records[currSizem].year, records[currSizem].frequency)) {
            currSizem++;
        }
    } else {
        printf("file failed to open\n");
    }

    fp2 = fopen("femalebabynames.csv", "r");
    if (fp != NULL) {
        printf("file opened\n");
        while(3 == fscanf(fp2, "%[^,],%d,%d", records[currSizef].name, &records[currSizef].year, &records[currSizef].frequency)) {
            currSizef++;
        }
    } else {
        printf("file failed to open\n");
    }
    return 0;
}


//function that automatically capitalizes the users inputted name
void allCaps(char s[]) {
    while(*s != '\0') {
        *s = toupper((unsigned char) *s);
        s++;
    }
}
//function that reads and places the read files into the struct arrays
int getRawData(FILE* fp, struct nameRecord records[], int currSize) {
    for(i = 0; i < currSize; i++) {
        fscanf(fp, "%[^,],%d,%d", records[i].name, &records[i].year, &records[i].frequency);
    }
}

根据网站的确切说明:

  
    

您的程序将要求用户输入名称(您可以假设该名称的长度不超过30个字符)。然后它会找到     该名称在1921年至2010年间的流行并打印出一张图表     和图表。然后程序将询问用户是否愿意     另一个分析并重复这个过程。

  
     

该程序将从以下数据源中提取信息   确定名称的受欢迎程度。

ontario female baby names
ontario male baby names
     

请注意,有些名字被认为是男性和女性,所以你的   无论名称如何,程序都需要来自两个文件的数据   输入

     

由于出生人数随着时间的推移而发生变化   (你预计1945年出生的人数比过去多出生的人数更多   1920),你不能简单地使用原始数字来确定   人气。假设有100个新生儿,其中50个是婴儿   在1920年命名为“迈克尔”,与1000名新生儿一起命名为55名婴儿   迈克尔在1950年。在这种情况下,“迈克尔”的流行实际上是   1920年比1950年更高。

     

数据集是从1917年到2010年收集的。您的程序将会   确定每十万分娩名称发生的次数   从1921年开始的5年间隔(您可以忽略数据   1921年之前)。因此,如果用户输入“Allison”,您将确定   “Allison”从1921年到1925年,1926年至1930年,1931年至1935年的流行,   ......,1996-2010(1921年之间总共有18个五年期   和2010年)。您可以假设记录不超过150,000条   总共在两个文件中合并。

     

在每种情况下,总人口是所有出生人口的总和   男性和女性的年份范围。名称为你的号码   我们感兴趣的是所有出生人口的总和   年范围。您的程序将以两个值的形式显示数据   (每十万分娩名称的婴儿数)和a   该数据的图表。

2 个答案:

答案 0 :(得分:2)

现在你正走在正确的轨道上,从文件中读取每一行到一条记录中。为了为记录数组分配内存,如果你知道每个文件中会有(比方说)不超过1000个名字,那么简单的懒惰方式就是声明struct nameRecord records[1000]

但是,如果您已明确指示对记录数量没有限制,并且程序在运行时需要弄清楚,那么您需要动态分配数据:

struct nameRecord *records;

...
/* after counting currSizem lines in the file */
records = malloc(currSizem * sizeof(struct nameRecord));

现在您可以重新读取文件,因为您知道记录的数量与您所需的数量完全相同。

当您不再需要records数据时,请务必致电free()以返回您分配的内存:

free(records);

需要考虑的事项:您是否需要以不同方式对待女性和男性的婴儿名字?或者只测量他们在所有婴儿中的受欢迎程度?如果需要单独检查它们,则需要保留两个数组,每个文件一个。但是,如果要将两个文件都读入单个数据结构,那么您将需要:

  • 在阵列中分配足够的内存以容纳两个文件
  • 中阅读时注意重复的名称

答案 1 :(得分:0)

  

GetRawData函数是否正确?我需要改变什么   使它正确地读入结构数组?

如果您确保records[]的尺寸足以容纳150,000条记录,GetRawData()需要进行最小的更改以检测并返回文件中的记录数。

int getRawData(FILE *fp, struct nameRecord records[], int currSize)
{
    for (i = 0; i < currSize; i++)
        if (fscanf(fp, "%[^,],%d,%d ", records[i].name,
                                      &records[i].year,
                                      &records[i].frequency) < 3) break;
    return i;
}

然后,您可以通过

替换while中的main()循环
        currSizem = getRawData(fp, records, 150000);

        currSizef = getRawData(fp, records+currSizem, 150000-currSizem);

- 在此之后,记录 0 currSizem-1 将保留男性,并通过 currSizem + currSizef-记录 currSizem 1 将容纳女性。