#c
Вопрос:
Я пытаюсь прочитать в текстовом файле, скажем input.txt, в массив структур, чтобы затем распечатать (и, конечно, освободить память). Хотя мое кодирование на C немного корявое, и я ищу помощи.
Input.txt содержит строки информации об одном человеке. Я хочу прочитать в людях, отсортировать по имени и распечатать в отсортированном порядке. Прежде чем я смогу это сделать, я просто пытаюсь создать массив людей, выделить память каждому человеку, скопировать данные из текстового файла, а затем распечатать их окончательно. Это даже не доходит до распечатки, как вы можете видеть, это приводит к ошибке сегментации:
Я использую следующее:
gcc -Wall -O2 -o program filename.c
и получить это
Segmentation fault: 11
input.txt содержание:
Джоан 0212672938 joan@gmail.com
Джон 0365242939 john@yahoo.com
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person {
char *name;
char *phone;
char *email;
};
int main(void) {
int i;
int peopleSize = 0;
char * pch;
FILE *f = fopen("input.txt", "r");
if (f == NULL) return EXIT_FAILURE;
struct person** people = malloc(100 * (sizeof (people[0])));
/* Create 100 people */
char *nameTmp = malloc(30 * sizeof nameTmp[0]);
char *phoneTmp = malloc(30 * sizeof phoneTmp[0]);
char *emailTmp = malloc(30 * sizeof emailTmp[0]);
/* Open the file for reading */
char *line_buf = NULL;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
/* Get the first line of the file. */
line_size = getline(amp;line_buf, amp;line_buf_size, f);
while (line_size >= 1) {
line_count = 1;
people[line_count-1] = malloc(sizeof (people[line_count-1]));
/* if fgets returns an empty space or new line, no more people to add, break loop */
/* Within str, use strtok to divide strings up into name, phone and email */
strcpy(pch, line_buf);
pch = strtok (pch, " ");
strcpy(nameTmp, pch);
printf("%sn", nameTmp);
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(phoneTmp, pch);
}
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(emailTmp, pch);
}
/* Allocate enough memory to person->name and person->phone and person->email as required */
people[line_count-1]->name = malloc((strlen(nameTmp) 1) * sizeof (people[line_count-1]->name[0]));
people[line_count-1]->phone = malloc((strlen(phoneTmp) 1) * sizeof (people[line_count-1]->phone[0]));
people[line_count-1]->email = malloc((strlen(emailTmp) 1) * sizeof (people[line_count-1]->email[0]));
/* Now copy values from temporary variables into actual person */
strcpy(people[line_count-1]->name, nameTmp);
strcpy(people[line_count-1]->phone, phoneTmp);
strcpy(people[line_count-1]->email, emailTmp);
/* Get the next line */
line_size = getline(amp;line_buf, amp;line_buf_size, f);
}
peopleSize = line_count;
/* Printing all the people out */
for (i = 0; i < peopleSize; i ) {
printf("%st", people[i]->name);
printf("%st", people[i]->phone);
printf("%s", people[i]->email);
printf("n");
}
/* Freeing all of the memory */
for (i = 0; i < peopleSize; i ) {
free(people[i]->email);
free(people[i]->phone);
free(people[i]->name);
free(people[i]);
}
free(people);
return EXIT_SUCCESS;
}
Комментарии:
1.
pch
не инициализируется, но вы пытаетесьstrcpy()
это сделать. Вы проверяли сбой с помощью какого-либо отладчика, напримерgdb
? Также вместоpeople[line_count-1] = malloc(sizeof (people[line_count-1]));
того, чтобы пытатьсяpeople[line_count-1] = malloc(sizeof (struct person));
2. @яно Вупс, вот что я хотел сказать, извините, неправильно набрал в отправке вопроса, отредактирую это.
3. Пожалуйста, разделите это на две отдельные проблемы «Как читать из текстового файла?» и «Как хранить в массиве?». Затем сосредоточьте этот вопрос только на одном из них. Разделение проблем-полезный инструмент для разработки, тестирования, отладки и для того, чтобы задавать здесь вопросы.
4. @kuro Потрясающе, я пробовал это, и все заканчивается тем, что я распечатываю двух человек, спасибо. Я не очень хорошо разбираюсь в C, Java-мой обычный язык выбора, указатели и структуры все еще немного сбивают с толку.
Ответ №1:
В общем, при отладке я бы рекомендовал компилировать без оптимизации и с флагом отладки (-g). Затем просмотрите свою программу в GDB и посмотрите, где она ломается.
Большинство исправлений уже упоминались в комментариях. Смотрите код ниже для пошагового объяснения исправлений.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { // now you can use "person" type rather than "struct person"
char *name;
char *phone;
char *email;
} person;
int main(void) {
int i;
int peopleSize = 0;
char * pch = malloc(30); // Must be initialized before use
FILE *f = fopen("input.txt", "r");
if (f == NULL) return EXIT_FAILURE;
person** people = malloc(100 * (sizeof(person*))); //This is an array of 100 pointers to person so you want sizeof(person*)
/* Create 100 people */
char *nameTmp = malloc(30); // These are char arrays. Each char occupys a byte and malloc allocates byte by default.
char *phoneTmp = malloc(30);
char *emailTmp = malloc(30);
/* Open the file for reading */
char *line_buf = malloc(30); // MUst be initialized before use;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
/* Get the first line of the file. */
line_size = getline(amp;line_buf, amp;line_buf_size, f);
while (line_size >= 1) {
line_count = 1;
people[line_count-1] = malloc(sizeof(person)); // You are allocating memory for a single person, so you want sizeof(person)
/* if fgets returns an empty space or new line, no more people to add, break loop */
/* Within str, use strtok to divide strings up into name, phone and email */
strcpy(pch, line_buf);
pch = strtok (pch, " ");
strcpy(nameTmp, pch);
printf("%sn", nameTmp);
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(phoneTmp, pch);
}
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(emailTmp, pch);
}
/* Allocate enough memory to person->name and person->phone and person->email as required */
people[line_count-1]->name = malloc(strlen(nameTmp) 1); // As above these are char arrays so there is no need for sizeof
people[line_count-1]->phone = malloc(strlen(phoneTmp) 1);
people[line_count-1]->email = malloc(strlen(emailTmp) 1);
/* Now copy values from temporary variables into actual person */
strcpy(people[line_count-1]->name, nameTmp);
strcpy(people[line_count-1]->phone, phoneTmp);
strcpy(people[line_count-1]->email, emailTmp);
/* Get the next line */
line_size = getline(amp;line_buf, amp;line_buf_size, f);
}
peopleSize = line_count;
/* Printing all the people out */
for (i = 0; i < peopleSize; i ) {
printf("%st", people[i]->name);
printf("%st", people[i]->phone);
printf("%s", people[i]->email);
printf("n");
}
/* Freeing all of the memory */
for (i = 0; i < peopleSize; i ) {
free(people[i]->email);
free(people[i]->phone);
free(people[i]->name);
free(people[i]);
}
free(people);
return EXIT_SUCCESS;
}