Почему моя программа читает дополнительную структуру? - PullRequest
2 голосов
/ 04 августа 2010

Я делаю небольшую консольную RPG, чтобы освежить свои навыки программирования.Я использую структуры для хранения символьных данных.Такие вещи, как их HP, Сила, возможно, Инвентарь в будущем.Одна из ключевых вещей, которые я должен уметь делать - это загружать и сохранять символы.Что означает чтение и сохранение структур.

Сейчас я просто сохраняю и загружаю структуру с именем и фамилией и пытаюсь правильно ее прочитать.

Вот мой код для создания символа:

void createCharacter()
{
    char namebuf[20];

    printf("First Name:");

    if (NULL != fgets(namebuf, 20, stdin))
    {
        char *nlptr = strchr(namebuf, '\n');
        if (nlptr) *nlptr = '\0';
    }
    strcpy(party[nMember].fname,namebuf);


    printf("Last Name:");
    if (NULL != fgets(namebuf, 20, stdin))
    {
        char *nlptr = strchr(namebuf, '\n');
        if (nlptr) *nlptr = '\0';
    }
    strcpy(party[nMember].lname,namebuf);

    /*Character created, now save */
    saveCharacter(party[nMember]);
    printf("\n\n");
    loadCharacter();

}

А вот и функция saveCharacter:

void saveCharacter(character party)
{
    FILE *fp;
    fp = fopen("data","a");
    fwrite(&party,sizeof(party),1,fp);
    fclose(fp);

}

и функция loadCharacter

void loadCharacter()
{
    FILE *fp;

    character tempParty[50];
    int loop = 0;
    int count = 1;
    int read = 2;

    fp= fopen("data","r");

    while(read != 0)
    {
        read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
        printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
        loop++;
        count++;
    }
    fclose(fp);
}

Таким образом, ожидаемый результат программы - ввод имени и фамилиинапример, «Джон Доу», и он добавляется в файл данных.Затем он читается, может быть, что-то вроде

1. Jane Doe
2. John Doe

, и программа заканчивается.

Однако, мой вывод добавляет еще одну пустую структуру в конец.

1. Jane Doe
2. John Doe
3. 

Я хотел бы знать, почему это так.Имейте в виду, что я читаю файл, пока fread не возвращает 0, чтобы показать, что он достиг EOF.

Спасибо :)

Ответы [ 5 ]

3 голосов
/ 04 августа 2010

Измени свой цикл:

while( fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp) )
{
    // other stuff
}

Всякий раз, когда вы пишете код для чтения файла, задайте себе вопрос: «Что произойдет, если я прочту пустой файл?»

2 голосов
/ 04 августа 2010

У вас есть алгоритмическая проблема в цикле, замените ее на:

 read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
 while(read != 0)
 {
        //read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
        printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
        loop++;
        count++;
        read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
 }

Есть способы избавиться от двойного фреда, но сначала запустите его и убедитесь, что вы понимаете поток.

1 голос
/ 05 августа 2010
while( 1==fread(&tempParty[loop],sizeof*tempParty,1,fp) )
{
/* do anything */
}

- правильный путь.

использовать fopen("data","rb") вместо fopen("data","r"), что эквивалентно fopen("data","rt")

1 голос
/ 04 августа 2010

Здесь:

    read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
    printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);

Вы не проверяете, было ли чтение успешным (возвращаемое значение fread()).

0 голосов
/ 04 августа 2010

У вас есть ответ на ваш ближайший вопрос, но стоит отметить, что слепое написание и чтение целых структур не является хорошим планом.

Структурные макеты могут изменяться и изменяются в зависимости от используемого вами компилятора, версии этого компилятора и даже от точных используемых флагов компилятора. Любое изменение здесь нарушит вашу способность читать файлы, сохраненные в другой версии.

Если у вас есть амбиции по поддержке нескольких платформ, такие проблемы, как endianness, также вступают в игру.

И вот что происходит, если вы добавляете элементы в свою структуру в более поздних версиях ...

Для надежности вам нужно подумать об определении формата файла независимо от кода и о том, чтобы функции сохранения и загрузки обрабатывали сериализацию и десериализацию в этот формат и из него.

...