C:读取文本文件到一个结构数组 [英] C: Reading a text file into a struct array

查看:125
本文介绍了C:读取文本文件到一个结构数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图总结我的脑子解决此问题,在过去2天,仍然不知道如何做到这一点。 pretty多,我不得不做出一个函数( getRawData )传递一个指向文件的指针已经打开阅读,目前在该数组传递结构的数组和记录数(通过paramer currSize)。的功能是从该文件中的数据读入该阵列放置在阵列的端和读出之后将返回的文件中的记录的总数。我的问题是,我真的不知道如何处理读取文件和数据存储到数组结构,我一直试图在文件/记录的读取和我仍然在做什么损失。有关该功能的 getRawData

整个程序实际上有两个文件,​​而不是一个(malebabynames.csv和femalebabynames.csv)和程序的关键是让程序要求用户提供他们的姓名,然后检查通过的文件的记录,看看多么受欢迎的名字。由于一些男孩的名字和女孩的名字是可以互换的,这两个文件需要读每名用户输入。这里的code我到目前为止有:

 的#include<&stdio.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&文件ctype.h GT; 结构nameRecord {
    焦炭名[31];
    INT年;
    INT频率;
};
结构nameRecord;
无效ALLCAPS(的char []);
INT getRawData(FILE *,结构nameRecord [],int);在
无效setYearTotals(结构nameRecord [],INT,INT);
无效setNameYearTotals(CHAR,结构nameRecord [],INT,INT);
无效getPerHundredThousand(INT,INT,双);
无效printData(双);
无效graphPerHundredThousand(双);INT主要(无效)
{
    INT currSizem = 0;
    INT currSizef = 0;
    结构nameRecord记录[currSizem]
    FILE * FP = NULL;
    FILE * FP2 = NULL;
    焦炭名[31];
    的printf(请输入您的姓名:);
    scanf函数(%30 [^ \\ n],名);
    的printf(你的名字为%s \\ n,名);//打开男性和女性的名字的文件和以获得阵列中的记录的总数读取它们
    FP = FOPEN(malebabynames.csv,R);
    如果(FP!= NULL){
        的printf(文件打开\\ n);
        而(3 ==的fscanf(FP,%[^,],%D,%D,记录[currSizem] .name和记录[currSizem] .year,记录[currSizem]。频率)){
            currSizem ++;
        }
    }其他{
        的printf(文件无法打开\\ n);
    }    FP2 = FOPEN(femalebabynames.csv,R);
    如果(FP!= NULL){
        的printf(文件打开\\ n);
        而(3 ==的fscanf(FP2,%[^,],%D,%D,记录[currSizef] .name和&安培;记录[currSizef] .year,&安培;记录[currSizef]。频率)){
            currSizef ++;
        }
    }其他{
        的printf(文件无法打开\\ n);
    }
    返回0;
}
//功能,可自动将大写输入用户名
无效ALLCAPS(char中[]){
    而(* S!='\\ 0'){
        * S = TOUPPER((无符号字符)* S);
        小号++;
    }
}
//函数读取和读出文件放到结构阵列
INT getRawData(FILE * FP,结构nameRecord记录[],诠释currSize){
    对于(i = 0; I< currSize;我++){
        的fscanf(FP,%[^,],%D,%D,记录[I] .name和&安培;记录[I] .year,&安培;记录[I]。频率);
    }
}

精确的指令按照网站:


  

    

您程序会要求用户输入一个名称(你可以假设名称将不​​超过30个字符)。然后,它会发现
    名字的1921年和2010年,并打印出的图表之间的普及
    和图形。然后程序会询问用户是否希望做
    另一种分析和重复这一过程。


  
  
  

该计划将拉动从以下数据源的信息
  确定名字的受欢迎程度。

 安大略女宝宝名字
安大略男宝宝名字

请注意,有些名称被认为是男性和女性让你
  程序将无论从两个文件所需要的名字的数据
  进入。


  
  

由于这一事实,即出生人数已经随时间的变化
  (你期望比有在1945年,有更多的产
  1920),你不能简单地用原始数据确定
  人气。假设有100个出生和婴儿的50人
  名为迈克尔,在1920 VS 1000出生名为婴儿的55
  迈克尔于1950年在这种情况下,迈克尔的普及竟是
  在1920年比1950年更高。


  
  

数据集收集从1917年到2010年你的程序会
  确定每十万出生的多少次出现的名字
  从1921年开始5年区间(可以忽略数据
  1921年之前)。因此,如果用户输入艾里时,将确定
  佳佳的1921年普及到1925年,1926-1930,1931-1935,
  ...,1996- 2010年(总共有1921年之间185年期
  和2010年)。你可以假设,有没有超过15万条记录
  在两个文件总和


  
  

在每一种情况下总人口中的所有出生的总和
  今年范围男性和女性。在名称中的数字,你
  有兴趣的是所有出生的总和与在给定的名称
  年份范围。你的程序将present的数据既作为价值
  (每十万的出生数名婴儿)和
  该数据的曲线图。



解决方案

您是在正确的轨道上现在从文件读取每行到一个记录。有关记录阵列,在每个文件分配内存,如果你知道会有(说)不超过1000名,轻松慵懒的方法是只是声明结构nameRecord记录[1000]

但如果你已经明确指示,没有限制多少条记录,程序需要去弄清楚它在运行过程中,您将需要动态分配数组:

 结构nameRecord *记录;...
/ *在文件*计数currSizem线后/
记录=的malloc(currSizem *的sizeof(结构nameRecord));

现在你可以重新读取文件,明知有一样多的记录,你所需要的。

当你不需要的记录数据更多,请确保调用免费()返回你分配的内存:

 免费(记录);

要考虑的事情:你需要区别对待女性和男性婴儿的名字?或者只是衡量他们在所有的婴儿很流行吗?如果他们需要单独检查,那么你将需要保持两个阵列,每个文件。但是,如果点读这两个文件到一个单一的数据结构,那么你将需要:


  • 在阵列中分配足够的内存来存放这两个文件

  • 在阅读时他们看着重复的名称

I've been trying to wrap my brain around this problem for the past 2 days and still have no idea how to do this. Pretty much I have to make a function(getRawData) that is passed a pointer to a file already open for reading, and passed an array of structs and the number of records currently in that array(through the paramer currSize). The function is to read the data from the file into the array placing it at the end of the array and will return the total number of records in the file after reading. My problem is that I don't really know how to approach reading the file and storing the data into the array struct, I've been trying to read up on files/records and I'm still at a loss on what to do. The function in question is getRawData

The entire program actually has two files not one(malebabynames.csv and femalebabynames.csv) and the point of the program is to get the program to ask the user for their name, then check through the records of the files to see how popular the name is. Since some boy names and girl names are interchangeable, both files need to be read for every name the user inputs. Here's the code I have so far:

    #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);
    }
}

Exact instructions as per the website:

Your program will ask the user to enter a name (you may assume that the name will be no more than 30 characters long). It will then find the popularity of the name between 1921 and 2010 and print out a chart and graph. The program will then ask the user if they wish to do another analysis and repeat the process.

The program will pull information from the following data sources in determining the popularity of a name.

ontario female baby names
ontario male baby names

Note that some names are considered both male and female so your program will needs the data from both files regardless of the name entered.

Due to the fact that the number of people born has changed over time (you expect that there were more births in 1945 than there were in 1920), you cannot simply use the raw numbers in determining popularity. Suppose there were 100 births and 50 of the babies were named "Michael" in 1920 vs 1000 births with 55 of the babies named Michael in 1950. In this case the popularity of "Michael" was actually higher in 1920 than in 1950.

The datasets were collected from 1917 to 2010. Your program will determine the how many times a name occurs per hundred thousand births in 5 year intervals starting from the year 1921 (you can ignore data before 1921). Thus, if the user entered "Allison", you will determine the popularity of "Allison" from 1921 to 1925, 1926-1930, 1931-1935, ..., 1996-2010 (there are a total of 18 five year periods between 1921 and 2010). You can assume that there are no more than 150,000 records in total in the two files combined.

In each case the total population is the sum of all births within the year range for both males and females. The number with the name you are interested in is the sum of all births with the given name in the year range. Your program will present the data in as both a value (number of babies with the name per hundred thousand births) and a graph of that data.

解决方案

You're on the right track now to read each line from the file into a record. For allocating memory for the record array, if you know that there will be (say) no more than 1000 names in each file, the easy lazy way is to just declare struct nameRecord records[1000].

But if you've been explicitly instructed that there is no limit to how many records, and the program needs to figure that out when it's run, you will need to allocate the array dynamically:

struct nameRecord *records;

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

Now you can reread the file, knowing that there are exactly as many records as you need.

When you don't need the records data any more, make sure to call free() to return the memory that you allocated:

free(records);

Something to consider: do you need to treat female and male baby names differently? Or just measure their popularity across all babies? If they need to be checked separately then you will need to keep two arrays, one for each file. But if the point is to read both files into a single data structure, then you will need to:

  • Allocate enough memory in the array to hold both files
  • Watch for duplicate names when reading them in

这篇关于C:读取文本文件到一个结构数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆