Tutorial de archivos en lenguaje C. -

Iniciado por NOB2014, 26 Agosto 2016, 14:51 PM

0 Miembros y 1 Visitante están viendo este tema.

NOB2014

Hola, gente.
Estoy muy feliz porque llegue al capítulo archivos, muy esperado por mi porqué es lo que mas necesito aprender en c dado me dará la posibilidad de desarrollar algo que todavía no les puedo decir porque las 2 veces que lo hice en foros me criticaron mucho (mucha energía negativa). -
Como notaran en el menú el programa es un tanto ambicioso para ser el primero, pero de entrada quiero ir a fondo. -
La primer consulta es un segmentation fault que me da en la línea 78 y por supuesto hasta la 90 me podrían decir en que estoy fallando, créanme que consulté páginas, videos (incluso los 3 de Alberto) pero no hallo la solución . -

Errores/dudas/etc.

1 - Segmentation fault
2 - Grabar en archivo linealmente y no en renglones.
3 - Posicionarse en el último registro.  
4 - Salto de línea anticipado en el último campo.
5 - Leer/escribir
6 - Buscar
7 - Borrar
8 - Ordenar



#include <stdio.h>
#include <stdlib.h>

typedef struct{
int  orden;
char nombre[50], direccion[50], ciudad[50], correo[50];
char telefono[20], celular[20];
char otros[200];
}Recordatorio;

void limpiar( void );
void menu( void );
void agregar( void );

int main ( int argc, char **argv ){

menu();
       
return 0;
}

void limpiar( void ){
system("cls||clear");
}

void menu( void ){
int opc, ok, ch;

do{
do{
limpiar( );
printf( "\n =============== Menu principal ===============\n"
"\n 1 - Primero"
"\n 2 - Ultimo"
"\n 3 - Buscar"
"\n 4 - Todos"
"\n 5 - Agregar"
"\n 6 - Modificar"
"\n 7 - Borrar"
"\n 8 - Finalizar\n"
"\n ingrese opcion.....:" );

ok = scanf( "%d", &opc ) == 1 && opc > 0 && opc <= 8;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );


switch ( opc ){
case 1: printf( "\n Primero" );
break;
case 2: printf( "\n Ultimo" );
break;
case 3: printf( "\n Buscar" );
break;
case 4: printf( "\n Todos" );
break;
case 5: agregar( );
break;
case 6: printf( "\n Modificar" );
break;
case 7: printf( "\n Borrar" );
break;
}
}while( opc != 8 );

}

void agregar( void ){
Recordatorio *recordatorio = NULL;
FILE *fptr = fopen ( "fichero.txt", "a" );
   
limpiar( );

   if( fptr == NULL ){  
perror(" \n\n Error en la creacion/apertura del archivo" );
}else{
printf( "\n\n Ingrese NOMBRE completo del contacto........: " );
fgets( recordatorio->nombre, 50, stdin );
printf( "\n\n Ingrese DIRECCION del contacto..............: " );
fgets( recordatorio->direccion, 50, stdin );
printf( "\n\n Ingrese CIUDAD donde reside el contacto.....: " );
fgets( recordatorio->ciudad, 50, stdin );
printf( "\n\n Ingrese CORREO del contacto.................: " );
fgets( recordatorio->correo, 50, stdin );
printf( "\n\n Ingrese TELEFONO FIJO del contacto..........: " );
fgets( recordatorio->telefono, 50, stdin );
printf( "\n\n Ingrese CELULAR del contacto................: " );
fgets( recordatorio->celular, 50, stdin );
printf( "\n\n Ingrese OTROS DATOS (200 caracteres)........: " );
fgets( recordatorio->otros, 50, stdin );
       
       fprintf(fptr, "%s", recordatorio->nombre);
       fprintf(fptr, "%s", recordatorio->direccion);
       fprintf(fptr, "%s", recordatorio->ciudad);
       fprintf(fptr, "%s", recordatorio->correo);
       fprintf(fptr, "%s", recordatorio->telefono);
       fprintf(fptr, "%s", recordatorio->celular);
       fprintf(fptr, "%s", recordatorio->otros);
       
fclose ( fptr );
}    
}

Saludos.
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

ivancea96

En esa función, recordatorio es un puntero a estructura, inicializado a NULL.
Nunca le asignas una estructura

recordatorio = (Recordatorio*)malloc(sizeof(Recordatorio));

NOB2014

Muchas gracias, todo correcto, te preguntaría como se podría hacer sin utilizar memoria dinámica (me parece haberlo visto) pero como voy a encerrar el código en un bucle para que se pueda ingresar los contactos que el operador desee, me viene al pelo para no tener que hacer un array de estructuras. -
Saludos. 
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

ivancea96

Sin memoria dinámica, tendrías que guardar los recordatorios en un array en algún lugar, como el main, o en el ámbito global (fuera de funciones/estructuras).
Depende de lo que quieras hacer.

AlbertoBSD

Una buena idea para depurar el código y encontrar el error seria imprimir las direcciones y/o valores de las variables por ejemplo en tu caso:

fprintf("%p\n",recordatorio);

Si ya sabemos que el error esta en X linea ponemos el printf justo antes del error

Eso  os imprime la dirección a la cual esta apuntado, y si vemos que son puros 000000 sabremos que no lo hemos inicializado.

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

ivancea96

Cita de: AlbertoBSD en 26 Agosto 2016, 16:15 PM
Una buena idea para depurar el código y encontrar el error seria imprimir las direcciones y/o valores de las variables por ejemplo en tu caso:

fprintf("%p\n",recordatorio);

Si ya sabemos que el error esta en X linea ponemos el printf justo antes del error

Eso  os imprime la dirección a la cual esta apuntado, y si vemos que son puros 000000 sabremos que no lo hemos inicializado.

Saludos!

Ten en cuenta que para eso hay que saber que el error es un problemacon la memoria. Para cuando supones eso, ya no necesitas debuguear así xD
Y es más, es posible que simplemente no esté inicializada, lo que podría resultar en basura diferente de 0.

AlbertoBSD

Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

NOB2014

#7
Hola y muchas gracias a los dos.
Segunda pregunta, en la imagen se muestra como el programa guarda en un archivo (en primer lugar), pero lo que quiero es que se grabe en forma lineal, como yo lo puse a mano. -  

2 - Grabar en archivo linealmente y no en renglones.



Saludos.
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

AlbertoBSD

El primer paso seria sanitizar la entrada (Limpiarla) y quitarle el \n del fin de linea para que no de el enter.

El segundo paso si lo quieres asi en forma Lineal es determinar como saber cuando empieza y termina cada registro. Se puede hacer de 2 formas,

Forma variable (Seperando con ',' o ';' o '.' o cual quier otro valor)
Forma estatica (Guardar una cantidad determinada de bytes en el archivo, rellenando los bytes restantes con valore NULL '\0')

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

NOB2014

¿Seria algo como esto?
fgets( recordatorio->nombre, 50, stdin );

luego contar la cantidad de caracteres +1 y remplazar el '\0' por '|', por ej.
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-