2010-02-09 6 views
10

Pourquoi le code ci-dessous ne fonctionne pas? Je veux dire, il montre toutes sortes de caractères étranges sur la sortie de la console.Pourquoi ai-je besoin de vider mon flux d'E/S pour obtenir le résultat correct?

#include <stdio.h> 
char mybuffer[80]; 
int main() 
{ 
    FILE * pFile; 
    pFile = fopen ("example.txt","r+"); 
    if (pFile == NULL) perror ("Error opening file"); 

    else { 
     fputs ("test",pFile); 

     fgets (mybuffer,80,pFile); 
     puts (mybuffer); 
     fclose (pFile); 
     return 0; 
    } 
} 

Cependant, le code ci-dessous fonctionne bien.

#include <stdio.h> 
char mybuffer[80]; 
int main() 
{ 
    FILE * pFile; 
    pFile = fopen ("example.txt","r+"); 
    if (pFile == NULL) perror ("Error opening file"); 

    else { 
     fputs ("test",pFile); 
     fflush (pFile);  
     fgets (mybuffer,80,pFile); 
     puts (mybuffer); 
     fclose (pFile); 
     return 0; 
    } 
} 

Pourquoi ai-je besoin de vider le flux pour obtenir le résultat correct?

Répondre

12

Comme la norme le dit (§7.19.5.3/5):

Lorsqu'un fichier est ouvert avec le mode de mise à jour ('+' comme deuxième ou troisième caractère dans la liste ci-dessus de l'argument de mode valeurs), entrée et sortie peuvent être effectuées sur le flux associé. Toutefois, la production ne doit pas être directement suivi par l'entrée sans appel intervenant à la fflush fonction ou à un fichier positionnement fonction (fseek, fsetpos ou retour rapide), et entrée ne doivent pas être directement suivi par la sortie sans un appel intervenant dans une fonction de positionnement de fichier , sauf si l'opération d'entrée rencontre une fin de fichier.

Il y a une raison à cela: la sortie et l'entrée sont normalement mises en mémoire tampon séparément. Quand il y a un flush ou un seek, il synchronise les buffers avec le fichier, mais sinon il peut les laisser désynchronisés. Cela améliore généralement les performances (par exemple, lorsque vous faites une lecture, il n'est pas nécessaire de vérifier si la position que vous lisez a été écrite depuis que les données ont été lues dans le tampon).

+0

Thx beaucoup !!!!!! – Jaebum

+0

Mais pourquoi la sortie de la deuxième source n'est pas "test"? – Jaebum

+1

@Lee: Simple, vous l'avez lu du point où vous avez cessé d'écrire, vous devez revenir au début pour que cela fonctionne – falstro

2

parce que le fichier Cio fonctionne avec un tampon. Ceci est seulement écrit sur le disque lorsque vous le videz, vous écrivez un caractère n/n ou vous remplissez le tampon.

Donc dans le premier cas, votre fichier ne contient rien quand vous venez de le lire. Lorsque vous utilisez un fichier avec un mode de lecture/écriture, vous devez appeler fseek/fflush avant les opérations d'E/S différentes.

+0

Mais cela ne fonctionne toujours pas même si j'utilise "test \ n" au lieu de "test". – Jaebum

+0

La réponse est fausse à cet égard: écrire '\ n' dans le fichier n'a aucun effet; Vous devez vider le fichier ou écrire autant de données que la bibliothèque C va se vider de lui-même (généralement 4 Ko). –

+0

Je pense que le bit \ n dépend de l'implémentation - MS le fait, au moins pour le code C++. – gbjbaanb