在过去的两天里,我一直试图围绕这个问题,但仍然不知道如何做到这一点。几乎我必须创建一个函数( 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 该数据的图表。
答案 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 将容纳女性。