2013-12-08 4 views
0

Я пытался обмотать мозг вокруг этой проблемы в течение последних 2 дней и до сих пор не знаю, как это сделать. В значительной степени мне нужно сделать функцию (getRawData), которая передается указателем на файл, который уже открыт для чтения, и передал массив структур и количество записей, находящихся в данный момент в этом массиве (через параметр currSize). Функция состоит в том, чтобы считывать данные из файла в массив, помещая его в конец массива и возвращая общее количество записей в файле после чтения. Моя проблема в том, что я действительно не знаю, как подходить к чтению файла и хранить данные в структуре массива, я пытался читать файлы/записи, и я все еще не понимаю, что делать. Функция в вопросе getRawDataC: Чтение текстового файла в массив структур

Вся программа на самом деле имеет два файла не один (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 год программа будет определить, сколько раз происходит название на сто тысяч родов 5 интервалов год, начиная с 1921 года (вы можете игнорировать ДАННЫЕ до 1921 года). Таким образом, если пользователь вошел в «Allison», вы определите популярность «Allison» с 1921 по 1925, 1926-1930, 1931-1935, ..., 1996-2010 (имеется в общей сложности 18 пять лет периоды между 1921 г. и 2010 гг.). Вы можете предположить, что в двух файлах вместе взято не более 150 000 записей .

В каждом случае общая численность населения является суммой всех рождений в пределах диапазона года для мужчин и женщин. Номер с названием you заинтересован в количестве всех рождений с данным именем в диапазоне . Ваша программа представит данные в виде как значения (количество младенцев с именем на 100 тысяч рождений), так и график этих данных.

+1

'struct nameRecord records [currSizem];' На данный момент 'struct nameRecord' по-прежнему имеет неполный тип. Что это? Ах, я нашел его. переместите его вверх, поэтому он будет определен, когда это необходимо. – wildplasser

+0

'& records [currSizef] .name' ->' records [currSizef] .name'. – BLUEPIXY

+0

'' [^,] '->' "% [^,]'. также Декларация i, функция ... – BLUEPIXY

ответ

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

Спасибо за подсказку, это большая помощь. Мне просто нужно измерить их популярность у всех младенцев. Правильно ли функция GetRawData? какие изменения мне нужно внести, чтобы они правильно считывали в массивы struct? – onemic

0

Правильно ли функция GetRawData? какие изменения мне понадобится , чтобы сделать его правильно считывать в массивы struct?

При условии, что вы добились того, что records[] имеет достаточные размеры для 150000 записей, 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); 

- после этого, записывает через currSizem-1 будет держать мужчин , и записи currSizem до currSizem + currSizef-1 будет удерживать самок.

Смежные вопросы