Cristhian Boujon
Cristhian Boujon

Reputation: 4190

Passing opened file as argument in C

I get the error

Segmentation fault (core dumped)

in line fread(&libro, sizeof(struct Libro), 1, archivo);

When I run the following code:

#include <stdio.h>

void abrirArchivo(FILE *archivo);
void cerrarArchivo(FILE *archivo);
void listar(FILE *archivo);

struct Libro {
   char isbn[ 13 ];     /* número de libro */
   char nombre[ 30 ];   /* nombre de libro */
   char autor[ 30 ];    /* nombre del autos */
   int edicion;         /* edicion */ 
};

FILE *archivo;     /* archivo = puntero al archivo clientes.dat */

int main()
{
    abrirArchivo(archivo);
    listar(archivo);
    cerrarArchivo(archivo);

    return 0; /* indica terminación exitosa */
}

void abrirArchivo(FILE *archivo){
    if ( ( archivo = fopen( "libros.dat", "rb" ) ) == NULL ) {
       printf( "El archivo no pudo abrirse" );
    }
}

void cerrarArchivo(FILE *archivo){
    fclose(archivo);
}

void listar(FILE *archivo){
    struct Libro libro;

    printf("ISBN\tNombre\tAutor\tEdicion\n");

    fread(&libro, sizeof(struct Libro), 1, archivo);

    while(!feof(archivo)){
        printf("%s\t\t%s\t\t%s\t%d\n", libro.isbn, libro.nombre, libro.autor, libro.edicion);
        fread(&libro, sizeof(struct Libro), 1, archivo);
    }

}

What am I doing wrong?

Upvotes: 0

Views: 125

Answers (3)

asio_guy
asio_guy

Reputation: 3767

your program is suffering with shadowing global pointers. try this move the global file pointer to main. change the abrirArchivo( FILE *) function a little. one option is as below.

//    FILE *archivo;     /* archivo = puntero al archivo clientes.dat */

int main()
{
    FILE *archivo = abrirArchivo( );
    if( arvhivo )
    {
        listar(archivo);
        cerrarArchivo(archivo);
    }
    return 0; /* indica terminación exitosa */
}

FILE *abrirArchivo(){
    FILE *archivo = NULL
    if ( ( archivo = fopen( "libros.dat", "rb" ) ) == NULL ) {
       printf( "El archivo no pudo abrirse" );
    }
    return archivo ;
}

Upvotes: 0

user2371524
user2371524

Reputation:

FILE *archivo;     /* archivo = puntero al archivo clientes.dat */

[...]

void abrirArchivo(FILE *archivo){
    if ( ( archivo = fopen( "libros.dat", "rb" ) ) == NULL ) {
       printf( "El archivo no pudo abrirse" );
    }
}

In this function, the parameter archivo shadows the variable archivo in file scope, it's a different variable. When calling this, you pass the global archivo, but the function receives a copy of it and assigns to the copy (the local archivo) which doesn't exist any more when the function exits.

Simple solution: remove the argument from that function altogether. Slightly better: Make it return the FILE * it opened and don't take a parameter.


Side notes:

  • Compile with enough warnings enabled (e.g. for gcc use -std=c11 -Wall -Wextra -pedantic). A good compiler should warn you about shadowing of variables.

  • Write your code in english. Sooner or later, you'll show it someone who doesn't speak your language (like you do here) and understanding the semantics of identifiers helps a lot with understanding the code.

Upvotes: 7

Jabberwocky
Jabberwocky

Reputation: 50775

You need this:

...
FILE *archivo;     /* archivo = puntero al archivo clientes.dat */    
abrirArchivo(&archivo);
...

void abrirArchivo(FILE **archivo)
{
  if ( ( *archivo = fopen( "libros.dat", "rb" ) ) == NULL ) {
    ...
}

With your solution archivo will not be modified after the call to abrirArchivo(archivo).

Upvotes: 1

Related Questions