Моя задача — написать файл, отображающий неизвестное количество записей, введенных пользователем. Каждая запись имеет следующие поля: Имя, Фамилия, Адрес, Город, Штат, Почтовый индекс и Номер телефона.
Я предположил, что лучший способ сделать это — определить структуру Record с указанными выше полями, а затем объявить массив Record
, который будет содержать столько записей, сколько ввел пользователь. Для этого я бы использовал цикл для получения входных данных для каждого поля для каждой записи, а затем, если пользователь хочет продолжить, динамически выделять дополнительное пространство в массиве Record
и продолжать до тех пор, пока пользователь не введет no. Я столкнулся с ошибкой записи местоположения нарушения прав доступа в строке:
scanf("%s", records[i]->fname);
Что не так с моим кодом?
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct Record;
struct Record
{
char fname[51];
char lname[51];
char address[51];
char city[51];
char state[51];
int zipcode;
int phoneNumber;
};
int main()
{
FILE *fileWriter;
const char filename[] = "data.txt";
char answer = 'y';
int size = 1;
int i = 0;
struct Record **records;
records = malloc(sizeof(*records)*(size));
while(answer == 'y' || answer == 'Y')
{
printf("First Name: \n");
scanf("%s", records[i]->fname);
printf("Last Name: \n");
scanf("%s", records[i]->lname);
printf("Address: \n");
scanf("%s", records[i]->address);
printf("City: \n");
scanf("%s", records[i]->city);
printf("State: \n");
scanf("%s", records[i]->state);
printf("Zipcode: \n");
scanf("%d", records[i]->zipcode);
printf("Phone Number: \n");
scanf("%d", records[i]->phoneNumber);
//stores all record info
printf("Are there anymore records? [y/n] ");
answer = getchar();
if(answer == 'y' || answer == 'Y')
{
size++;
records[i++];
printf("\n");
}
records = realloc(records,sizeof(*records)*(size));
}
//open file
fileWriter = fopen(filename,"wb");
if(fileWriter != NULL)
{
if(fwrite(records,sizeof(*records),size,fileWriter) != 1)
{
fprintf(stderr, "Failed to write to %s\n", filename);
exit(1);
}
fclose(fileWriter);
}
else
{
printf("Error opening file.");
}
}
ОТРЕДАКТИРОВАННАЯ ВЕРСИЯ
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct Record
{
char fname[51];
char lname[51];
char address[51];
char city[51];
char state[51];
int zipcode;
int phoneNumber;
};
int main()
{
FILE *fileWriter;
const char filename[] = "data.txt";
char answer = 'y';
int size = 1;
int i = 0;
struct Record *records = NULL;
struct Record *records_temp;
while(answer == 'y' || answer == 'Y')
{
struct Record *records_temp = realloc(records,(size)*sizeof(*records));
if(records_temp == NULL)
{
free(records);
}
records = records_temp;
printf("First Name: \n");
scanf("%s", records[i].fname);
printf("Last Name: \n");
scanf("%s", records[i].lname);
printf("Address: \n");
scanf(" %[^\n]", records[i].address);
printf("City: \n");
scanf("%s", records[i].city);
printf("State: \n");
scanf("%s", records[i].state);
printf("Zipcode: \n");
scanf("%d", &records[i].zipcode);
printf("Phone Number: \n");
scanf("%d", &records[i].phoneNumber);
//stores all record info
printf("Are there anymore records? [y/n] ");
answer = getchar();
if(answer == 'y' || answer == 'Y')
{
size++;
records[i++];
printf("\n");
}
//open file
fileWriter = fopen(filename,"wb");
if(fileWriter != NULL)
{
if(fwrite(records,sizeof(*records),size,fileWriter) != 1)
{
fprintf(stderr, "Failed to write to %s\n", filename);
exit(1);
}
fclose(fileWriter);
}
else
{
printf("Error opening file.");
}
}
}
records[i++];
увеличиваетi
и не делает больше ничего полезного. - person Jonathan Leffler   schedule 26.05.2015struct Record;
на самом деле не нужна. Единственный раз, когда это может иметь значение, - это если вы определяете взаимно рекурсивные структуры в области действия функции, а не в области файла (и это использование находится в области файла). Как бы то ни было, строка говорит, что существует типstruct Record
, а следующий блок кода говорит, что существует типstruct Record
, и вот как он определен. - person Jonathan Leffler   schedule 26.05.2015records[i]->fname
означает(*records[i]).fname
, что означает(*(*(records + i))).fname
. На что указываетrecords + i
? На что указывает*(records + i)
? - person user253751   schedule 26.05.2015&
перед именем переменной при сканировании%d
. - person Spikatrix   schedule 26.05.2015struct A{ … }; void f(void) { struct A; struct B { …; struct A *a_ref; … }; struct A { …; struct B *b_ref; … }; … }
— безstruct A;
элементa_ref
указывал бы на структуру внешне определенного типа, а не на взаимно рекурсивную пару типов структур. Сообщения об ошибках тоже могут быть довольно запутанными! - person Jonathan Leffler   schedule 26.05.2015%s
не будет сканировать пространство и прекратит сканирование, когда увидит одно из них. Используйте%[^\n]
вместо%s
, если вы хотите получить линейный ввод. - person Spikatrix   schedule 27.05.2015%[^\n]
. - person Spikatrix   schedule 27.05.2015fwrite
. Вы можете опубликовать новый вопрос, указав необходимые детали. Надеюсь, кто-нибудь на него ответит. - person Spikatrix   schedule 27.05.2015