2010-08-04 5 views
2

Je fais un petit RPG sur console, pour parfaire mes compétences en programmation. J'utilise des structures pour stocker des données de caractères. Des choses comme leur HP, la force, peut-être l'inventaire sur la route. L'une des principales choses que je dois pouvoir faire est de charger et d'enregistrer des caractères. Ce qui signifie lire et sauver des structures.Pourquoi mon programme lit-il une structure supplémentaire?

Actuellement, je ne fais que sauvegarder et charger une structure avec le prénom et le nom de famille et essayer de la lire correctement.

Voici mon code pour créer un personnage:

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(); 

} 

Et voici la fonction saveCharacter:

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

} 

et la fonction 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); 
} 

Ainsi, le résultat attendu le programme est que je saisis un nom et un nom de famille comme "John Doe", et il est ajouté à le fichier de données. Ensuite, il est lu, peut-être quelque chose comme

1. Jane Doe 
2. John Doe 

et le programme se termine.

Cependant, ma sortie semble ajouter une structure vierge à la fin.

1. Jane Doe 
2. John Doe 
3. 

Je voudrais savoir pourquoi cela est. Gardez à l'esprit que je suis en train de lire le fichier jusqu'à ce que fread renvoie un 0 pour signifier qu'il a frappé l'EOF.

Merci :)

+0

Pour la postérité, la solution que je fini par aller avec était de garder mon code même, avec le petit ajout d'un imbriquée si à l'intérieur du temps, la vérification lire avant qu'il arrive à printf. – Blackbinary

Répondre

3

Changer votre boucle:

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

Chaque fois que vous écrivez du code de lecture du fichier, posez-vous cette question - « ce qui se passe si je lis un fichier vide? »

+0

Merci, et cela va à toutes les réponses. Je comprends maintenant mon erreur, et comme votre solution me semble la plus élégante et la plus facile à mettre en œuvre, je vais vous donner la réponse acceptée. – Blackbinary

1

ici:

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

Vous n'êtes pas vérifier si la lecture a réussi (la valeur de retour de fread()).

2

Vous avez un problème algorithmique dans votre boucle, changer à:

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

Il y a plusieurs façons de ged débarrasser de la double fread mais d'abord le faire fonctionner et assurez-vous de comprendre le flux.

0

Vous avez la réponse à votre question immédiate, mais il vaut la peine de souligner qu'écrire et lire aveuglément des structures entières n'est pas un bon plan.

Les dispositions de structure peuvent changer et changent en fonction du compilateur que vous utilisez, de la version de ce compilateur et même des indicateurs de compilation utilisés. Toute modification ici va casser votre capacité à lire les fichiers enregistrés avec une version différente.

Si vous avez l'ambition de prendre en charge plusieurs plates-formes, des problèmes tels que l'endianness entrent également en ligne de compte.

Et puis il y a ce qui se passe si vous ajoutez des éléments à votre structure dans les versions ultérieures ...

Pour robustesse, vous devez penser à la définition de votre format de fichier indépendamment de votre code et avoir votre sauvegarde et les fonctions de charge manipuler de sérialisation et dé-sérialisation vers et depuis ce format.

+0

Je suis d'accord, mais ce n'est rien de sérieux. Comme je l'ai mentionné, il est vraiment juste pratique de rafraîchir mes compétences en programmation avant le début des cours. – Blackbinary

1
while(1==fread(&tempParty[loop],sizeof*tempParty,1,fp)) 
{ 
/* do anything */ 
} 

est le bon moyen.

utilisation fopen("data","rb") au lieu de fopen("data","r") qui équivaut à fopen("data","rt")

Questions connexes