Leyendo un archivo de texto al revés y ponlo en C

Quiero saber cómo leer un archivo de texto al revés en C.

Frozen_snowman.txt es

Do you wanna build a snowman? Come on lets go and play I never see you anymore Come out the door It's like you've gone away- We used to be best buddies And now we're not I wish you would tell me why!- Do you wanna build a snowman? It doesn't have to be a snowman. 

Código

 #include int main() { int i; char buffer[100]; char *a[100]; FILE *f,*p; f=fopen("Frozen_snowman.txt","r"); p=fopen("Reverse.txt","w"); for(i=0;i-1;i--) { fputs(a[i],p); } return 0; } 

El resultado es

 It doesn't have to be a snowman. It doesn't have to be a snowman. It doesn't have to be a snowman. It doesn't have to be a snowman. It doesn't have to be a snowman. It doesn't have to be a snowman. It doesn't have to be a snowman. It doesn't have to be a snowman. It doesn't have to be a snowman. It doesn't have to be a snowman. 

¿Porqué es eso?

La razon es esta

 fgets(buffer,100,f); // check return of fgets a[i]=buffer; // Note - buffer is modified in each iteration 

Se apunta a la cadena que se almacena en el buffer en la última iteración . Cada puntero apunta a la última cadena leída . Y cada vez que imprima la misma cadena se imprime.

Lo que debe hacer es asignar memoria para apuntar a[i] y usar strcpy para copiar la cadena.

Si sabes que siempre son 10 líneas, podrías declarar como una matriz 2d.

Algo como esto debería ser mejor.

 #include #include int main() { int i; char buffer[100]; char a[10][100]; FILE *f,*p; f=fopen("Frozen_snowman.txt","r"); p=fopen("Reverse.txt","w"); for(i=0;i<10;i++) { fgets(buffer,100,f); strcpy (a[i], buffer); } for(i=9;i>-1;i--) { fputs(a[i],p); } return 0; } 

El siguiente código funciona, comstack limpiamente, realiza la comprobación de errores, invierte el orden de las líneas en el archivo de entrada y siempre se limpia después de sí mismo.

 #define _GNU_SOURCE #include  #include  #define MAX_LINES (100) int main( void ) { int i; char *a[MAX_LINES] = {NULL}; // initialize pointers for up to 100 lines FILE *fin = NULL; // input file pointer FILE *fout = NULL; // output file pointer if( NULL ==(fin=fopen("Frozen_snowman.txt","r") ) ) { // then fopen failed perror( "fopen for input file: Frozen Snowman.txt failed"); exit( EXIT_FAILURE ); } // implied else, fopen for input successful if( NULL == (fout = fopen("Reverse.txt","w") ) ) { // then fopen failed perror( "fopen for output file Reverse.txt failed"); fclose( fin ); // close the file opened above exit( EXIT_FAILURE ); } // implied else, fopen for output successful // read each line into allocated memory // and place allocated memory pointer in array i = 0; while( i < MAX_LINES && getline(&(a[i]), NULL, fin) ) { i++; } // count backwards through saved lines, printing them, then // returning the associated memory to the 'heap' for(i--; i>=0; i--) { fputs( a[i],fout); free( a[i] ); // no longer need this line } // close open files before exiting fclose( fin ); fclose( fout ); return 0; } // end function: main