Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: NOB2014 en 26 Agosto 2016, 14:51 pm



Título: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 26 Agosto 2016, 14:51 pm
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



Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef struct{
  5. int  orden;
  6. char nombre[50], direccion[50], ciudad[50], correo[50];
  7. char telefono[20], celular[20];
  8. char otros[200];
  9. }Recordatorio;
  10.  
  11. void limpiar( void );
  12. void menu( void );
  13. void agregar( void );
  14.  
  15. int main ( int argc, char **argv ){
  16.  
  17. menu();
  18.  
  19. return 0;
  20. }
  21.  
  22. void limpiar( void ){
  23. system("cls||clear");
  24. }
  25.  
  26. void menu( void ){
  27. int opc, ok, ch;
  28.  
  29. do{
  30. do{
  31. limpiar( );
  32. printf( "\n =============== Menu principal ===============\n"
  33. "\n 1 - Primero"
  34. "\n 2 - Ultimo"
  35. "\n 3 - Buscar"
  36. "\n 4 - Todos"
  37. "\n 5 - Agregar"
  38. "\n 6 - Modificar"
  39. "\n 7 - Borrar"
  40. "\n 8 - Finalizar\n"
  41. "\n ingrese opcion.....:" );
  42.  
  43. ok = scanf( "%d", &opc ) == 1 && opc > 0 && opc <= 8;
  44. while ((ch = getchar()) != EOF && ch != '\n');
  45. }while( !ok );
  46.  
  47.  
  48. switch ( opc ){
  49. case 1: printf( "\n Primero" );
  50. break;
  51. case 2: printf( "\n Ultimo" );
  52. break;
  53. case 3: printf( "\n Buscar" );
  54. break;
  55. case 4: printf( "\n Todos" );
  56. break;
  57. case 5: agregar( );
  58. break;
  59. case 6: printf( "\n Modificar" );
  60. break;
  61. case 7: printf( "\n Borrar" );
  62. break;
  63. }
  64. }while( opc != 8 );
  65.  
  66. }
  67.  
  68. void agregar( void ){
  69. Recordatorio *recordatorio = NULL;
  70. FILE *fptr = fopen ( "fichero.txt", "a" );
  71.  
  72. limpiar( );
  73.  
  74.    if( fptr == NULL ){  
  75. perror(" \n\n Error en la creacion/apertura del archivo" );
  76. }else{
  77. printf( "\n\n Ingrese NOMBRE completo del contacto........: " );
  78. fgets( recordatorio->nombre, 50, stdin );
  79. printf( "\n\n Ingrese DIRECCION del contacto..............: " );
  80. fgets( recordatorio->direccion, 50, stdin );
  81. printf( "\n\n Ingrese CIUDAD donde reside el contacto.....: " );
  82. fgets( recordatorio->ciudad, 50, stdin );
  83. printf( "\n\n Ingrese CORREO del contacto.................: " );
  84. fgets( recordatorio->correo, 50, stdin );
  85. printf( "\n\n Ingrese TELEFONO FIJO del contacto..........: " );
  86. fgets( recordatorio->telefono, 50, stdin );
  87. printf( "\n\n Ingrese CELULAR del contacto................: " );
  88. fgets( recordatorio->celular, 50, stdin );
  89. printf( "\n\n Ingrese OTROS DATOS (200 caracteres)........: " );
  90. fgets( recordatorio->otros, 50, stdin );
  91.  
  92.        fprintf(fptr, "%s", recordatorio->nombre);
  93.        fprintf(fptr, "%s", recordatorio->direccion);
  94.        fprintf(fptr, "%s", recordatorio->ciudad);
  95.        fprintf(fptr, "%s", recordatorio->correo);
  96.        fprintf(fptr, "%s", recordatorio->telefono);
  97.        fprintf(fptr, "%s", recordatorio->celular);
  98.        fprintf(fptr, "%s", recordatorio->otros);
  99.  
  100. fclose ( fptr );
  101. }    
  102. }
  103.  
Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: ivancea96 en 26 Agosto 2016, 15:55 pm
En esa función, recordatorio es un puntero a estructura, inicializado a NULL.
Nunca le asignas una estructura

Código
  1. recordatorio = (Recordatorio*)malloc(sizeof(Recordatorio));


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 26 Agosto 2016, 16:07 pm
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. 


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: ivancea96 en 26 Agosto 2016, 16:11 pm
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.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: 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:

Código
  1. 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!


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: ivancea96 en 26 Agosto 2016, 16:28 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:

Código
  1. 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.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 26 Agosto 2016, 16:41 pm
Tienes toda la razon mi estimado :)  ;-)


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 26 Agosto 2016, 18:06 pm
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.

(http://i68.tinypic.com/fum711.png)

Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 26 Agosto 2016, 18:18 pm
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!


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 26 Agosto 2016, 18:26 pm
¿Seria algo como esto?
Código
  1. fgets( recordatorio->nombre, 50, stdin );
  2.  
luego contar la cantidad de caracteres +1 y remplazar el '\0' por '|', por ej.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: MCKSys Argentina en 26 Agosto 2016, 18:49 pm
Creo que sera evidente que no soy experto en C/C++, pero no seria valido reemplazar esto:

Código
  1. ...
  2. fprintf(fptr, "%s", recordatorio->nombre);
  3. fprintf(fptr, "%s", recordatorio->direccion);
  4. fprintf(fptr, "%s", recordatorio->ciudad);
  5. fprintf(fptr, "%s", recordatorio->correo);
  6. fprintf(fptr, "%s", recordatorio->telefono);
  7. fprintf(fptr, "%s", recordatorio->celular);
  8. fprintf(fptr, "%s", recordatorio->otros);
  9. ...
  10.  

por algo como esto?

Código
  1. ...
  2. fprintf(fptr, "%s,%s,%s,%s,%s,%s,%s", (recordatorio->nombre, recordatorio->direccion, recordatorio->ciudad, recordatorio->correo, recordatorio->telefono, recordatorio->celular, recordatorio->otros));
  3. ...
  4.  

Desconozco si fprintf se puede usar de esa forma, pero imagino que debe existir algo como para hacer eso y separar los valores usando comas (como en el ejemplo) o usando ";" o el separador que sea...

Saludos!


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 26 Agosto 2016, 19:16 pm
Hola, coterráneo.
Parece que igual toma el salto de linea '\n', me da el mismo resultado, tu código tiene 2 paréntesis de más. -
Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 26 Agosto 2016, 20:43 pm
Ya lo solucione, dejo el código por si a alguien le pasa algo parecido. -


Código
  1. void reemplazar( Recordatorio *recordatorio ){
  2. char *p=NULL;
  3. if((p=strchr(recordatorio->nombre, '\n'))){
  4. *p='|';
  5. }
  6. if((p=strchr(recordatorio->direccion, '\n'))){
  7. *p='|';
  8. }
  9. if((p=strchr(recordatorio->ciudad, '\n'))){
  10. *p='|';
  11. }
  12. if((p=strchr(recordatorio->correo, '\n'))){
  13. *p='|';
  14. }
  15. if((p=strchr(recordatorio->telefono, '\n'))){
  16. *p='|';
  17. }
  18. if((p=strchr(recordatorio->celular, '\n'))){
  19. *p='|';
  20. }
  21. if((p=strchr(recordatorio->otros, '\n'))){
  22. *p='|';
  23. }
  24. }
Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 26 Agosto 2016, 23:35 pm
3 - Posicionarse en el último registro.  

Si tengo lo siguiente en el archivo. -

Citar
1 - xxxxxxxx|xxxxxxxxxxxx|xxxxx
2 - xxxxxxxx|xxxxxxxxxxxx|xxxxx
3 - xxxxxxxx|xxxxxxxxxxxx|xxxxx
4 - xxxxxxxx|xxxxxxxxxxxx|xxxxx
5 - xxxxxxxx|xxxxxxxxxxxx|xxxxx
6 - xxxxxxxx|xxxxxxxxxxxx|xxxxx
7 - xxxxxxxx|xxxxxxxxxxxx|xxxxx
Lo que quiero es recuperar el número 7 para agregarle 1 y así tener un orden de ingreso, me podrían dar alguna idea de como intentarlo. -
Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 26 Agosto 2016, 23:57 pm
Cuando se tiene registros de longitud dinamica, y no tienes los datos cargados en memoria tienes que leerlos todos y reescribir todo el archivo o solo desde la parte que cambio.

Segun se te facilite si lo reescribe todo solo haces un ciclo y escribes desde 0 todo.

Si solo quieres modificar la parte modificada, tienes que situarte donde finaliza el ultimo registro no afectado fseek() y empezar a escribir apartir de ahi

Saludos


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 27 Agosto 2016, 04:32 am
Hola.
Al fin parece que lo conseguí. -
Una consultita, hay otra manera para hacer lo mismo sin utilizar '\n'. -
Código
  1. FILE *fptr = fopen( "fichero.txt", "r+" );
  2.  
  3. orden = cantCampos( fptr, orden );
  4.  
  5. int cantCampos( FILE *fptr, int orden ){
  6. char caracter;
  7. while ( !feof ( fptr ) ){
  8. caracter = getc( fptr );
  9. if( caracter == '\n' )
  10. orden++;
  11. }
  12.  
  13. return orden;
  14. }
Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 6 Septiembre 2016, 02:48 am
Hola, gente. -
Tengo un inconveniente con el siguiente código, como se muestra en la captura hace como un enter en el último campo antes de tiempo, hice unos cambios para solucionarlo y nada, los primeros 7 registros los alinee a mano. -


4 - Salto de línea anticipado en el último campo.


(http://i65.tinypic.com/14ne9uf.png)

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void limpiar( void );
  5.  
  6. int main( void ){
  7. int n = 1, ch, orden=-1;
  8. char nombre[80], caracter;
  9. double salario;
  10. FILE *pArchivo = fopen( "pruebaE.txt", "a+" );
  11. if( pArchivo != NULL ){
  12. while ( !feof ( pArchivo ) ){
  13. caracter = getc( pArchivo );
  14. if( caracter == '\n' )
  15. orden++;
  16. }
  17. do{
  18. limpiar();
  19. orden++;
  20. printf( "\n\n El proximo empleado es el numero..: %d", orden );
  21. printf( "\n\n Introduzca 0 para finalizar mayor para continuar.....:" );
  22. scanf( "%d", &n );
  23. while ((ch = getchar()) != EOF && ch != '\n');
  24. if( n > 0 ){
  25. printf( "\n Introduzca el NOMBRE del empleado.....:" );
  26. fgets( nombre, 80, stdin );
  27. printf( "\n Introduzca el SALARIO del empleado....:" );
  28. scanf( "%lf", &salario );
  29. while ((ch = getchar()) != EOF && ch != '\n');
  30.  
  31. fprintf( pArchivo, "%d\t%s\t%lf \n", orden, nombre, salario );
  32. }
  33. }while( n > 0 );
  34.  
  35. fclose( pArchivo );
  36. }else{
  37. printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", "pruebaE" );
  38. }
  39.  
  40.  
  41. return 0;
  42.  
  43. }
  44.  
  45. void limpiar( void ){
  46. system("cls||clear");
  47. }
  48.  


Desde ya muchas gracias, saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 6 Septiembre 2016, 16:29 pm
Es raro que te de ese error si es el mismo codigo que se uso no deberia de agregar ese enter de mas...

Sanitiza la entrada del nombre quitandole el \n o \r que quede atorado ahi:

Código
  1. char *busqueda = NULL;
  2. fgets( nombre, 80, stdin );
  3. busqueda = strstr(nombre,"\n");
  4. *busqueda = '\0';
  5.  


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 6 Septiembre 2016, 16:46 pm
Hola, Alberto, buen día. -
No es el mismo código y cometí 2 veces el mismo error ,  fgets en casi todos los casos al final de la cadena pone el salto de línea y eso hacia que el último campo se escribiera mal en el archivo. -
Tengo otra consulta para hacerles, lo que ocurre es que tengo el programa para escribir y leer el archivo en distintas carpetas ¿alguien sabe cómo abrir archivo en Linux que estén en una carpeta distinta a la que se encuentraa el programa? -

Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 6 Septiembre 2016, 17:50 pm
Hay varias formas para hacer esto.

Hay que usar la ruta absoluta o la ruta relativa.

Esto es con ruta absoluta:

Código
  1. archivo = fopen("/usr/home/usuario/directorioX/archivo.txt","r");

O con ruta relativa (relativa al directorio actual de trabajo), suponiendo que estemos ya en el directorio usuario y asumiendo que el directorioX exita:
Código
  1. archivo = fopen("./directorioX/archivo.txt","r");

Saludos!


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 6 Septiembre 2016, 18:34 pm
Estoy probando un montón de maneras y no me funciona, te dejo algunos datos para ver si me podes dar la solución. -

Esto es lo que sale al abrir un terminal
Citar
daniel@daniel-H81M-S1 ~ $

Y esta es la ruta(carpetas) completa...
.../Escritorio/Prueba/Archivos Daniel/Escribir/pruebaE.txt

Y donde esta el programa con el que estoy trabajando es:
.../Escritorio/Prueba/Archivos Daniel/Leer

Saludos.

Bueno ya lo logre con el comando locate.
Código
  1. FILE *pArchivo = fopen( "/home/daniel/Escritorio/Prueba/Archivos Daniel/Escribir/pruebaE.txt", "r" ); //Comando locate

pero vaya sorpresa me imprime solo el primer registro (todos los campos) pero no salta al segundo, como que se quedaría en un bucle infinito, practico un poco y si no lo logro les consulto. -

Buen día. -


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: MAFUS en 6 Septiembre 2016, 19:28 pm
Usa la ruta completa:
Código:
"/home/daniel/Escritorio/Prueba/Archivos Daniel/Escribir/pruebaE.txt"
O la ruta relativa:
Código:
"../Escribir/pruebaE.txt"

La ruta completa empieza en el directorio raíz /, después pasas al directorio que guarda los archivos de usuarios home, el nombre de usuario del sistema daniel y a partir de allí moverte por árbol de directorios hasta el archivo.

Las rutas relativas parten desde donde se encuentra el programa y para subir al directorio padre debes usar los dos puntos ..; una vez llegues al directorio común escribe el resto de la ruta a donde quieras llegar. Nota: para ir retrocediendo en el árbol, usa ../../ tantas veces como sea necesario.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 6 Septiembre 2016, 22:54 pm
5 - Leer/escribir

Hola.
Hoy estoy un poco cargoso, espero sepan comprender mi ansiedad por resolver esto. -
Les dejo los 2 códigos para escribir en archivos y leer desde un archivo, quisieran que lo revisen con tiempo y me digan que estoy asiendo mal, en realidad escribir me parece que funciona bien, en cuanto a leer lee solamente la primer linea y se produce un bucle infinito. -  
Una cosita mas, la línea 39 del archivo leer no me place para nada, ¿con que otra función la puedo reemplazar?. -
MAFUS, gracias por el aporte y que agrado da leerte nuevamente. -

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. void limpiar( void );
  6. void leer( FILE *pArchivo );
  7.  
  8. int main( void ){
  9.  
  10. // FILE *pArchivo = fopen( "/home/daniel/Escritorio/Prueba/Archivos Daniel/Escribir/pruebaE.txt", "r" ); //Comando locate
  11. FILE *pArchivo = fopen( "../Escribir/pruebaE.txt", "r" );
  12.  
  13. if( pArchivo != NULL ){
  14. leer( pArchivo );
  15.  
  16. fclose( pArchivo );
  17. }else{
  18. printf( "\n Error al abrir %s para lectura. Finaliza el programa.", "pruebaE.txt" );
  19. }
  20.  
  21.  
  22. return 0;
  23.  
  24. }
  25.  
  26. void limpiar( void ){
  27. system("cls||clear");
  28. }
  29.  
  30.  
  31. void leer( FILE *pArchivo ){
  32. int orden=0;
  33. char nombre[30];
  34. double salario;
  35.  
  36. printf( "\n\n Orden  Nombre          Salario\n\n" );
  37.  
  38. while( !feof(pArchivo) ){
  39. fscanf(pArchivo,"%d\t%[^\n]\t%lf",&orden,nombre,&salario);
  40. printf(" %d\t%-10s\t%lf",orden,nombre,salario);
  41. }
  42. }
  43.  

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define MAX_CAR 30
  6.  
  7. void limpiar( void );
  8. void agregar( FILE *pArchivo );
  9.  
  10. int main( void ){
  11.  
  12. FILE *pArchivo = fopen( "pruebaE.txt", "a+" );
  13.  
  14. if( pArchivo != NULL ){
  15. agregar( pArchivo );
  16.  
  17. fclose( pArchivo );
  18. }else{
  19. printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", "pruebaE.txt" );
  20. }
  21.  
  22.  
  23. return 0;
  24.  
  25. }
  26.  
  27. void limpiar( void ){
  28. system("cls||clear");
  29. }
  30.  
  31.  
  32. void agregar( FILE *pArchivo ){
  33. int n = 1, ch, orden=0, escrito;
  34. char nombre[MAX_CAR], caracter, *p=NULL;
  35. double salario;
  36.  
  37. while ( !feof ( pArchivo ) ){
  38. caracter = getc( pArchivo );
  39. if( caracter == '\n' )
  40. orden++;
  41. }
  42.  
  43. do{
  44. limpiar();
  45. orden++;
  46. printf( "\n\n El proximo empleado es el numero..: %d", orden );
  47. printf( "\n\n Introduzca 0 para finalizar mayor para continuar.....:" );
  48. scanf( "%d", &n );
  49. while ((ch = getchar()) != EOF && ch != '\n');
  50. if( n > 0 ){
  51. printf( "\n Introduzca el NOMBRE del empleado.....:" );
  52. fgets( nombre, MAX_CAR, stdin );
  53. if(( p=strchr(nombre, '\n' ))){
  54. *p='\0';
  55. }
  56. printf( "\n Introduzca el SALARIO del empleado....:" );
  57. scanf( "%lf", &salario );
  58. while ((ch = getchar()) != EOF && ch != '\n');
  59.  
  60. escrito = fprintf( pArchivo, "%d\t%s\t%lf\n", orden, nombre, salario );
  61. }
  62. if( escrito < 1 ){
  63. printf( "\n ERROR!!! No se pudieron guardar los datos en el archivo."
  64. "\n Pulse una tecla para continuar..."); getchar();
  65. }
  66. }while( n > 0 );
  67. }
  68.  

Un abrazso.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: MAFUS en 7 Septiembre 2016, 00:08 am
En el primer código cambia:
Código
  1. while( !feof(pArchivo) ){
  2.    fscanf(pArchivo,"%d\t%[^\n]\t%lf",&orden,nombre,&salario);
  3.    printf(" %d\t%-10s\t%lf",orden,nombre,salario);
  4. }

por
Código
  1. fscanf(pArchivo,"%d\t%30[^\t]\t%lf",&orden,nombre,&salario);
  2. while( !feof(pArchivo) ){
  3.    printf(" %d\t%-10s\t%0.2lf\n",orden,nombre,salario);
  4.    fscanf(pArchivo,"%d\t%30[^\t]\t%lf",&orden,nombre,&salario);
  5. }

La cadena de control de fscanf ha cambiado nombre ahora recibirá un máximo de 30 caracteres, además se detendrá la lectura de nombre cuándo encuentre una tabulación (que es tu separador), no el carácter de nueva línea (que no puede existir en esa posición. También se cambia el orden de las lecturas en el buche, así no imprimirás por duplicado la última lectura.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 7 Septiembre 2016, 18:51 pm
6 - Buscar

Hola, muy buen día para todos. -
Tengo algo mal echo en la función strcmp que no logro discernir, estuve consultando en un montón de páginas y tal vez tenga que ver con cadena constantes y no pero no logro hacer que funcione, si lo pongo a mano por Ej.:
Código
  1. encontrado = strcmp( espaniol, "hogar" );
el resultado es correcto. -
MAFUS, maravilloso lo tuyo, funciona a la perfección. -

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. #define MAX_CAR 30
  5.  
  6. void buscarCampo( FILE *pArchivo );
  7.  
  8.  
  9. int main( void ){
  10.  
  11. FILE *pArchivo = fopen( "../Escribir/pruebaE.txt", "r" );
  12.  
  13. if( pArchivo != NULL ){
  14. buscarCampo( pArchivo );
  15.  
  16. fclose( pArchivo );
  17. }else{
  18. printf( "\n Error al abrir %s para lectura. Finaliza el programa.", "pruebaE.txt" );
  19. }
  20.  
  21.  
  22. return 0;
  23. }
  24.  
  25. void buscarCampo( FILE *pArchivo ){
  26. int encontrado=0, orden;
  27. char ingles[MAX_CAR], espaniol[MAX_CAR], buscar[MAX_CAR], *p=NULL;
  28.  
  29. printf( "\n Intoduzca la palabra a buscar.....: " );
  30. fgets( buscar, MAX_CAR, stdin );
  31. if(( p=strchr(ingles, '\n' ))){
  32. *p='\0';
  33. }
  34.  
  35. while( !feof(pArchivo) ){
  36. fscanf(pArchivo,"%d\t%30[^\t]\t%30[^\n]",&orden, ingles, espaniol);
  37. encontrado = strcmp( espaniol, buscar );
  38. if( encontrado != 0 ){
  39. encontrado = strcmp( ingles, buscar );
  40. }
  41. if( encontrado == 0){
  42. printf( "\n\n Orden  Ingles                          Espaniol\n\n" );
  43. printf(" %d\t%-30s\t%-30s\n",orden, ingles, espaniol);
  44. break;
  45. }
  46. }
  47. if( encontrado != 0 ){
  48. printf( "\n No existe..." );
  49. }
  50. }
  51.  

Saludos y muchas gracias. -


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: MAFUS en 7 Septiembre 2016, 19:04 pm
Línea 31:
Te has equivocado de puntero. En vez de ingles, debe ser buscar.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 7 Septiembre 2016, 21:52 pm
 7 - Borrar registro


Hola, que tengan un muy buen día. -
El tema pasa ahora por borrar un registro del archivo y me gustaría que me den su criterio para hacer esta operación, yo he leído que hay 2 maneras de hacerlo, la primera consiste en tener un campo para indicar si el registro está borrado o no y en algún momento borrar todos los marcados para dicho fin, la segunda es hacer un bucle e ir copiando cada registro en un archivo temporal (salteando el elegido para borrar) y luego re nombrarlo con el nombre original, . -
Si tengo unos 15.000 registros cual de los 2 métodos utilizarían, o tal vez haya alguna otra manera más eficiente que desconozco. -
Una pregunta más, cual lejos está un archivo de transformarse en una tabla o base de datos. -

Saludos


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 8 Septiembre 2016, 17:55 pm
Citar
Si tengo unos 15.000 registros cual de los 2 métodos utilizarían, o tal vez haya alguna otra manera más eficiente que desconozco

Si tienes esa cantidad de registros yo utilizaria la primera opcion que dijiste, tener un campo donde este marcado si es registro activo, o eliminado.

El detalle esta en que dado que estas usando registros de longitud variable (Modo texto) y no modo binario es la opcion mas adecuada.

Tendrías que tener un programa adiconal que haga el trabajo pesado (Optimizar la base de datos) quitando los registros marcados como eliminados para NO ocupar mas espacio del necesario.

Con registros binarios (DE LONGITUD FIJA) es mas facil ya que es mas rapido dejar un segmento de X tamaño en ceros (NULL) y posteriormente ocuparlo con alguno de los registros nuevos.

Saludos!


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 13 Septiembre 2016, 02:27 am
8 - Ordenar

Hola, gente. -
Una vez más con una duda sobre archivos ahora binario, lo que quiero hacer es por cada ingreso que quede ordenado, también podría ser ordenar todo el archivo cada vez que sea necesario, en definitiva, lo que necesito es que me den alguna idea de como hacerlo y que tengan en cuenta que aproximadamente puede contener unos 15.000 registros. -  
muchas gracias Alberto por las ideas del post anterior.

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. typedef struct {
  6. int  habilitado;
  7. char ingles[30];
  8. char espaniol[30];
  9. }Idiomas;
  10.  
  11. #define MAX_CAR 30
  12.  
  13. void menu( char *nombreArchivo );
  14. long contar( char *nombreArchivo );
  15. int contarMarcados( char *nombreArchivo );
  16. Idiomas agregar( void );
  17. void guardar( Idiomas idiomas, char *nombreArchivo );
  18. void mostrar( char *nombreArchivo );
  19. void buscar( char *nombreArchivo );
  20. void modificarBorrar( FILE *file, Idiomas idiomas );
  21. void limpiar( void );
  22. void dibujo( void );
  23.  
  24. int main( void ){
  25. char nombreArchivo[] = "traductor.bin";
  26.  
  27. menu( nombreArchivo );
  28.  
  29. return 0;
  30. }
  31.  
  32. void limpiar( void ){
  33. system("cls||clear");
  34. }
  35.  
  36. long contar( char *nombreArchivo ){
  37.  
  38. FILE *file = fopen( nombreArchivo, "r" );
  39. long numeroRegistros;
  40.  
  41. fseek(file, 0, SEEK_END);  /* Nos situamos al final del mismo */
  42.  
  43. /* ftell devuelve el numero de bytes desde el principio del fichero
  44. hasta la posicion actual que es el final del fichero */
  45.  
  46. numeroRegistros = ftell( file )/sizeof( Idiomas );
  47. fclose( file );
  48.  
  49. return numeroRegistros;
  50. }
  51.  
  52. int contarMarcados( char *nombreArchivo ){
  53. int marcados = 0;
  54.  
  55. FILE *file = fopen( nombreArchivo, "rb" );
  56.  
  57. if( file != NULL ){
  58. Idiomas idiomas;
  59. rewind( file );
  60. while( fread( &idiomas, sizeof(Idiomas), 1, file )){
  61. if( idiomas.habilitado == 0 ){
  62. marcados++;
  63. }
  64. }
  65. }else{
  66. printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", nombreArchivo );
  67. }
  68.  
  69. fclose( file );
  70.  
  71. return marcados;
  72. }
  73.  
  74. void menu( char *nombreArchivo ){
  75. int opc, ok, ch, marcados;
  76. long numeroRegistros = 0;
  77.  
  78. do{
  79. do{
  80. limpiar( );
  81. numeroRegistros = contar( nombreArchivo );
  82. marcados = contarMarcados( nombreArchivo );
  83. dibujo();
  84. printf( "\n Cuenta hasta el momento con [%ld] palabra(s) traducida(s).", numeroRegistros );
  85. printf( "\n Tiene [%d] registro(s) marcado(s) para borrar.", marcados);
  86. dibujo();
  87. printf( "\n =============== Menu principal ===============\n"
  88. "\n [1] - Agregar"
  89. "\n [2] - Listar"
  90. "\n [3] - Buscar (-> Modificar -> Borrar)"
  91. "\n [4] - Empaquetar"
  92. "\n [5] - Finalizar"
  93. "\n\n ingrese opcion.....:" );
  94.  
  95. ok = scanf( "%d", &opc ) == 1 && opc > 0 && opc <= 5;
  96. while ((ch = getchar()) != EOF && ch != '\n');
  97. }while( !ok );
  98.  
  99.  
  100. switch ( opc ){
  101. case 1: guardar( agregar(), nombreArchivo );
  102. break;
  103. case 2: mostrar( nombreArchivo );
  104. break;
  105. case 3: buscar( nombreArchivo );
  106. break;
  107. }
  108. }while( opc != 5 );
  109. }
  110.  
  111. Idiomas agregar( void ){
  112. Idiomas idiomas;
  113. char *p=NULL;
  114.  
  115. idiomas.habilitado = 1;
  116.  
  117. limpiar();
  118.  
  119. printf( "\n Introduzca palabra en ingles......:" );
  120. fgets( idiomas.ingles, MAX_CAR, stdin );
  121. if(( p=strchr( idiomas.ingles, '\n' )) ){ *p='\0'; }
  122.  
  123. printf( "\n Introduzca traduccion al español..:" );
  124. fgets( idiomas.espaniol, MAX_CAR, stdin );
  125. if(( p=strchr( idiomas.espaniol, '\n' )) ){ *p='\0'; }
  126.  
  127. return idiomas;
  128. }
  129.  
  130. void guardar( Idiomas idiomas, char *nombreArchivo ){
  131. FILE *file = fopen( nombreArchivo, "ab" );
  132.  
  133. if( file != NULL ){
  134. fwrite( &idiomas, sizeof(Idiomas), 1, file );
  135. }else{
  136. printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", nombreArchivo );
  137. }
  138.  
  139. fclose( file );
  140. }
  141.  
  142. void mostrar( char *nombreArchivo ){
  143. FILE *file = fopen( nombreArchivo, "rb" );
  144.  
  145. limpiar();
  146.  
  147. if( file != NULL ){
  148. Idiomas idiomas;
  149. dibujo();
  150. printf( "\n %-30s %-30s\n", "Ingles", "Espaniol" );
  151. while( fread( &idiomas, sizeof(Idiomas), 1, file )){
  152. printf( "\n %-30s %-30s", idiomas.ingles, idiomas.espaniol );
  153. }
  154. dibujo();
  155. }else{
  156. printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", nombreArchivo );
  157. }
  158. printf( "\n\n Pulse una tecla para continuar..." ); getchar();
  159. fclose( file );
  160. }
  161.  
  162. void buscar( char *nombreArchivo ){
  163. FILE *file = fopen( nombreArchivo, "rb" );
  164. Idiomas idiomas;
  165. char buscar[MAX_CAR], *p=NULL;
  166. int encontrado;
  167.  
  168. limpiar();
  169.  
  170. if( file != NULL ){
  171. printf( "\n Ingrese la palabra a buscar....: " );
  172. fgets( buscar, MAX_CAR, stdin );
  173.  
  174. if(( p=strchr(buscar, '\n' )) ) { *p='\0';}
  175.  
  176. while( fread( &idiomas, sizeof(Idiomas), 1, file )){
  177. encontrado = strcmp( idiomas.espaniol, buscar );
  178. if( encontrado != 0 ){
  179. encontrado = strcmp( idiomas.ingles, buscar );
  180. }
  181. if( encontrado == 0){
  182. break;
  183. }
  184. }
  185. if( encontrado != 0 ){
  186. printf( "\n No existe..." );
  187. printf( "\n\n Pulse una tecla para volver al menu..." ); getchar();
  188. }else{
  189. modificarBorrar( file, idiomas );
  190. }
  191.  
  192. fclose( file );
  193. }
  194. else{
  195. printf( "\n Error al abrir %s para lectura. Finaliza el programa.", nombreArchivo );
  196. }
  197.  
  198. }
  199.  
  200. void modificarBorrar( FILE *file, Idiomas idiomas ){
  201. int opc=0, ok, ch;
  202.  
  203. do{
  204. limpiar( );
  205.  
  206. dibujo();
  207. printf( "\n %-30s %-30s\n", "Ingles", "Espaniol" );
  208. printf( "\n %-30s %-30s", idiomas.ingles, idiomas.espaniol );
  209. dibujo();
  210.  
  211. printf( "\n\n ========== Modificar/borrar registro ==========\n"
  212. "\n 1 - Modificar"
  213. "\n 2 - Borrar"
  214. "\n 3 - Continuar"
  215. "\n\n ingrese opcion.....:" );
  216.  
  217. ok = scanf( "%d", &opc ) == 1 && opc > 0 && opc <= 3;
  218. while ((ch = getchar()) != EOF && ch != '\n');
  219. }while( !ok );
  220.  
  221.  
  222. switch ( opc ){
  223. case 1: ;
  224. break;
  225. case 2: ;
  226. break;
  227. case 3: break;
  228. }
  229. }
  230.  
  231. void dibujo( void ){
  232. int con = 0;
  233. printf( "\n" );
  234. while( con <= 75 ){
  235. printf( "-" ); con++;
  236. }
  237. }
  238.  

Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 13 Septiembre 2016, 17:44 pm
Si lo que quieres es ordenarlos mientras lo vas guardando de uno en uno, tendrias que modifciar tu funcion guardar, hay algunos algoritmos de ordenamientos excelentes para tu aplicacion. El mas recomendado es el de biblioteca...

La idea basica es abstraer el sistema de Estantes usados en las bibliotecas para acomodar libros, algunos estantes estan llenos y otros a media capacidad Imaginemos que tenemos un sistema de registro (Donde esta el libro con X autor, donde empiezan las palabras con Z etc...)

La idea es por ejemplo, si vas a manejar un unico archivo, (ahorita vacio por el moemento) y llega una registro con la letra A o lo que sea... lo guardas en la posición 0, pero dejas libre la posición 1, esto es:
Tu archivo tendrá actualmente espacio para 2 registros (Posición 0 y posicion 1).

Llega un nuevo registro con la letra B, este lo colocas en la posición 2 y dejas la posicion 3 libre.

Entonces si en algun punto  llega un nuevo registro con la letra A lo agregas en la posición 1, agregas un registro blanco al final y  mueves los demás 1 registro hacia adelante cantidad de posiciones hacia adelante, y asi sucesivamente.

Tambien tendrias que tener un registro que te diga que la letra A empieza en X posicion y la B en tal posicion.

Lo anterior es la idea vaga

Mas info
https://es.wikipedia.org/wiki/Algoritmo_de_ordenamiento

https://es.wikipedia.org/wiki/Library_sort
Citar
Supón que un bibliotecario almacene sus libros alfabéticamente en una estante, empezando por la A desde la izquierda, y continuando a la derecha a lo largo del estante sin espacios entre los libros hasta que termine por la Z. Si el bibliotecario adquiere un libro nuevo que pertenece a la sección B, una vez que encuentra el espacio correcto en la sección B, tiene que mover cada libro a partir de ese hasta el último libro en la sección Z para abrir espacio al libro nuevo. Esto es ordenación por inserción. Sin embargo, si dejara un espacio vacío después de cada letra, mientras hubiese un espacio vacío después de B, sólo tuviera que mover unos cuantos libros para poder hubicar el nuevo libro. Esto es el principio básico de Library Sort.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 15 Septiembre 2016, 00:21 am
Hola, a todos.
Alberto, muy interesante lo que propones lo voy a llevar a la práctica para ver si lo logro, en realidad muy interesante. -
A continuación, dejo una manera que me vino a la mente y parece que puede dar resultado, lo dejo a su consideración para que me digan si lo puedo mejorar y que les parece la velocidad que se puede obtener al ordenar de esta manera. -

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. int main(void){
  5. int numeros[10] = {0}, ordenar[10] = {0}, ingreso = 0;
  6. int i, j;
  7.  
  8. for( i=0; i<10; i++ ){
  9. printf(" \n Ingrese un entero (cero para finalizar)....: ");
  10. scanf("%d", &ingreso);
  11.  
  12. if( ingreso == 0 ){
  13. break;
  14. }
  15.  
  16. numeros[i] = ingreso;
  17. ordenar[i] = 1;
  18.  
  19. if( i > 0 ){
  20. j=0;
  21. while( j < i ){
  22. if( ingreso < numeros[j] ){
  23. ordenar[j] += 1;
  24. }else{
  25. ordenar[i] += 1;
  26. }
  27. j++;
  28. }
  29. }
  30. }
  31.  
  32. printf("\n\n  Numeros ==> ");
  33. for( i=0; i<10; i++ ){
  34. printf("%2d ", numeros[i]);
  35. }
  36. printf("\n  Ordenar ==> ");
  37. for( i=0; i<10; i++ ){
  38. printf("%2d ", ordenar[i]);
  39. }
  40.  
  41. return 0;
  42. }
     
     (http://i65.tinypic.com/2yw9z03.png)

Como comprenderán es solo una practica luego tengo que insertarlo en el programa de archivo binario. -

Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: crack81 en 15 Septiembre 2016, 02:42 am
Hola esta bien tu código pero me pregunto, necesitas un arreglo para almacenar los registro y otro del mismo tamaño para saber en que posición se encontrarían ordenados? siendo muy estrictos realmente no es un método de ordenamiento ya que los datos siguen como en su estado original.

Pero bueno tomemos tu algoritmo como valido y comparemoslo frente a otros algoritmos amplia-mente documentados y como serian bubble sort y Quick sort como se comporta

Para ello necesitamos algunas subrutinas que nos midan el tiempo de procesamiento de nuestros algoritmos lamentablemente hacer esto no siempre es muy preciso y depende del sistema operativo y arquitectura de la computadora donde se ejecuten estas pruebas.

La primera prueba que vamos a hacer es con tu algoritmo para ello lo encapsule en una función y decidí tomar algunas muestras

Código
  1. #include <stdio.h>
  2. #include<windows.h>
  3. #include <time.h>
  4.  
  5. double performancecounter_diff(LARGE_INTEGER *a, LARGE_INTEGER *b){
  6.    LARGE_INTEGER freq;
  7.    QueryPerformanceFrequency(&freq);
  8.    return (double)(a->QuadPart - b->QuadPart) / (double)freq.QuadPart;
  9. }
  10.  
  11.  
  12.  
  13. void rellenarOrdenarDatos(int numeros[],int ordenar[],int tamano){
  14.    int i,j,ingreso;
  15.    srand(time(NULL));
  16.  
  17.    for( i=0; i<tamano; i++){
  18.  
  19.        ingreso = rand()%100;
  20.        numeros[i]=ingreso;
  21.        ordenar[i] = 1;
  22.  
  23.        if(i>0){
  24.            j=0;
  25.            while(j<i){
  26.                if( ingreso < numeros[j] ){
  27.                    ordenar[j] += 1;
  28.                }
  29.                else{
  30.                    ordenar[i] += 1;
  31.                }
  32.                j++;
  33.            }
  34.        }
  35.    }
  36. }
  37.  
  38. int main()
  39. {
  40.    const int TAMANO=15000;
  41.    int *arreglo=malloc(sizeof(int)*TAMANO);
  42.    int *ordenar=malloc(sizeof(int)*TAMANO);
  43.  
  44.    LARGE_INTEGER t_ini, t_fin;
  45.    double secs;
  46.  
  47.    QueryPerformanceCounter(&t_ini);
  48.  
  49.    rellenarOrdenarDatos(arreglo,ordenar,TAMANO);
  50.  
  51.    QueryPerformanceCounter(&t_fin);
  52.  
  53.    secs = performancecounter_diff(&t_fin, &t_ini);
  54.    printf("%.16g milliseconds\n", secs * 1000.0);
  55.  
  56.    free(arreglo);
  57.    free(ordenar);
  58.  
  59.    return 0;
  60. }

Entre las muestras que obtuve fueron estos tiempos en milisegundos
Citar
937.9348
1006.7837
984.6807
917.7779
1013.7831
993.5917

Ahora la prueba con BubbleSort

Código
  1. #include <stdio.h>
  2. #include<windows.h>
  3. #include <time.h>
  4.  
  5. double performancecounter_diff(LARGE_INTEGER *a, LARGE_INTEGER *b){
  6.    LARGE_INTEGER freq;
  7.    QueryPerformanceFrequency(&freq);
  8.    return (double)(a->QuadPart - b->QuadPart) / (double)freq.QuadPart;
  9. }
  10.  
  11.  
  12.  
  13.  
  14. void rellenarArreglo(int numeros[],unsigned int tamano){
  15.    srand(time(NULL));
  16.    int i=0;
  17.  
  18.    for(i=0; i<tamano; i++)
  19.    {
  20.        int r = rand()%100+1;
  21.        numeros[i]=r;
  22.    }
  23. }
  24.  
  25. void bubbleSort(int numeros[],int tamano){
  26.    int i,j,temp;
  27.    for (i=1; i<tamano; i++){
  28.      for(j=0 ; j<tamano - 1; j++){
  29.         if (numeros[j] > numeros[j+1]){
  30.            temp = numeros[j];
  31.            numeros[j] = numeros[j+1];
  32.            numeros[j+1] = temp;
  33.         }
  34.      }
  35.    }
  36. }
  37.  
  38.  
  39.  
  40. int main()
  41. {
  42.    const int TAMANO=15000;
  43.    int *arreglo=malloc(sizeof(int)*TAMANO);
  44.  
  45.  
  46.    LARGE_INTEGER t_ini, t_fin;
  47.    double secs;
  48.  
  49.    QueryPerformanceCounter(&t_ini);
  50.  
  51.    rellenarArreglo(arreglo,TAMANO);
  52.    bubbleSort(arreglo,TAMANO);
  53.  
  54.    QueryPerformanceCounter(&t_fin);
  55.  
  56.    secs = performancecounter_diff(&t_fin, &t_ini);
  57.    printf("%.16g milliseconds\n", secs * 1000.0);
  58.  
  59.    free(arreglo);
  60.  
  61.  
  62.    return 0;
  63. }

Utilizando el algoritmo bubble sort el tiempo de procesamiento fue mas alto por ende menos optimo aproximadamente 1500 milsegundos en promedio, en este caso te debo los tiempos exactos

Por ultimo utilize el algoritmo Quick Sort y la diferencia fue abismal
El siguiente codigo es similar al anterior salvo por el metodo de ordenamiento

Código
  1. void qs(int lista[],int limite_izq,int limite_der)
  2. {
  3.    int izq,der,temporal,pivote;
  4.  
  5.    izq=limite_izq;
  6.    der = limite_der;
  7.    pivote = lista[(izq+der)/2];
  8.  
  9.    do{
  10.        while(lista[izq]<pivote && izq<limite_der)izq++;
  11.        while(pivote<lista[der] && der > limite_izq)der--;
  12.        if(izq <=der)
  13.        {
  14.            temporal= lista[izq];
  15.            lista[izq]=lista[der];
  16.            lista[der]=temporal;
  17.            izq++;
  18.            der--;
  19.  
  20.        }
  21.  
  22.    }while(izq<=der);
  23.    if(limite_izq<der){qs(lista,limite_izq,der);}
  24.    if(limite_der>izq){qs(lista,izq,limite_der);}
  25.  
  26. }
  27.  
  28. void quicksort(int lista[],int n)
  29. {
  30.    qs(lista,0,n-1);
  31. }
  32.  
  33.  
  34.  
  35. int main()
  36. {
  37.    const int TAMANO=15000;
  38.    int *arreglo=malloc(sizeof(int)*TAMANO);
  39.  
  40.  
  41.    LARGE_INTEGER t_ini, t_fin;
  42.    double secs;
  43.  
  44.    QueryPerformanceCounter(&t_ini);
  45.  
  46.    rellenarArreglo(arreglo,TAMANO);
  47.    quicksort(arreglo,TAMANO);
  48.  
  49.    QueryPerformanceCounter(&t_fin);
  50.  
  51.    secs = performancecounter_diff(&t_fin, &t_ini);
  52.    printf("%.16g milliseconds\n", secs * 1000.0);
  53.  
  54.    free(arreglo);
  55.  
  56.  
  57.    return 0;
  58. }

Aqui una lista de tiempos obtenidos
Citar
2.1082
2.2769
2.1349
2.1203
2.0972
2.1325

En promedio 2 mili-segundos el tiempo de procesamiento

En conclusion yo te recomendaria usar une metodo de ordenamiento ya que ademas de que evitas reservar memoria inecesaria el performance es mejor.

SI hay dudas o no estas de acuerdo con algo no dudes en hacermelo saber.
Saludos.... :silbar:






Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 15 Septiembre 2016, 15:52 pm
Hola, crack81, como estas.
Tal vez no leíste por donde venia el tema o no me supe explicar en el post anterior. -

Citar
Hola esta bien tu código pero me pregunto, necesitas un arreglo para almacenar los registro y otro del mismo tamaño para saber en que posición se encontrarían ordenados? siendo muy estrictos realmente no es un método de ordenamiento ya que los datos siguen como en su estado original.
Lo que quiero lo vas a entender mejor en la imagen que dejo a continuación, es para un traductor inglés/español y ordenándolo de esta manera por Ej. no necesito hacer un archivo temporal o en memoria para hacer que se muestre en un determinado orden, puedo ordenar el archivo por las palabras en inglés, en español y de forma natural, como se ingresaron los datos. -
Ahora desconozco si esto es más lento o rápido que tener los datos ordenados físicamente, lo que estoy seguro es que no necesito 5 archivos por si hay 5 campos por ordenar, simplemente se agregan tantas columnas como sea necesarias y listo. -
De cualquier manera por el momento no deseo competir con creadores de bases de datos, aunque debo reconocer que es mi fuerte. -

(http://i63.tinypic.com/2i1nx1f.png)

Saludos, un abrazo.



Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 15 Septiembre 2016, 16:57 pm
Tu idea esta bien, te sirve bastante si no quieres estar moviendo los registros "fisicamente" en su posicion del archivo.

Asi solo guardas en un arreglo externo que el registro X del archivo esta en el orden TAL.

Y podrias implementar una busqueda casi binaria por ejemplo tienes 1000 Registros y buscas por la letra T o no se la palabra tocar, vez quien es el registro 500 y si la palabra tocar es mayor te desplazas 250 registros mas adelante y buscas en el registro 750 y si es mayor o menor te desplazas 125 registros adelante o atras y asi sucesivamente. Para buscar rapidamente la palabra tal....

Saludos!



Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 17 Septiembre 2016, 14:39 pm
Hola, a todos. -
Créanme que probé de muchas maneras pero no me funciona, el error lo tengo en el último campo, no puedo hacer que se modifique, les dejo solamente la función guardar para no hacerlo tan largo, descarto que alguien de Uds. me podrá dar la solución sin tener que correr el programa. - 
Alberto me interesa lo de la búsqueda casi binaria, lo voy a practicar. -

Código
  1. void guardar( Idiomas idiomas, char *nombreArchivo, long numeroRegistros ){
  2. FILE *file = fopen( nombreArchivo, "ab" );
  3. Idiomas tmp;
  4. tmp.habilitado = idiomas.habilitado;
  5. strcpy( tmp.ingles, idiomas.ingles );
  6. strcpy( tmp.espaniol, idiomas.espaniol);
  7. tmp.orden = 1;
  8.  
  9.  
  10. if( file != NULL ){
  11. numeroRegistros += 1;
  12.  
  13. if( numeroRegistros > 1 ){
  14. fseek( file, 0, SEEK_SET );
  15. while( fread( &idiomas, sizeof(Idiomas), 1, file )){
  16. if( strcmp( tmp.ingles, idiomas.ingles ) < 0 ) {
  17. idiomas.orden += 1;
  18. fwrite( &idiomas, sizeof(Idiomas), 1, file );
  19. }else{
  20. tmp.orden += 1;
  21. }
  22. }
  23. }
  24. fwrite( &tmp, sizeof(Idiomas), 1, file );
  25. }else{
  26. printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", nombreArchivo );
  27. }
  28.  
  29. fclose( file );
  30. }
  31.  

(http://i65.tinypic.com/2j3qvsm.png)

Saludos y desde ya muchas gracias. -


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 17 Septiembre 2016, 22:23 pm
No estoy seguro de cuales son los datos ingresados pero el problema puede ser el strcmp, ya que solo lo tienes mejor que cero y strcmp puede devolver -1, 0 o 1 segun sea menor, igual o mayor deberias de cambiarlo por !=

Código
  1. strcmp( tmp.ingles, idiomas.ingles ) != 0

Saludos!


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 18 Septiembre 2016, 14:58 pm
Hola. -
alberto creo que el problema era la apertura del archivo y en realidad nunca se ejecutaba el bucle, después de tanta práctica logre hacer que funcionara pero o sorpresa cada vez que tenia que modificar el orden de la palabra grabada en el archivo se duplicaba y en realidad lo que necesitaba era modificarla, ahora el problema que tengo es que no logro regresar el puntero file al comienzo de la  linea donde está parado para modificarla/sobre escribirla. -

Código
  1. file -= sizeof( Idiomas ); //es algo que se me antojo de tanto practicar, pero no me funciono. -

¿Me podrían decir porque la siguiente línea no mueve el cursor del archivo al comienzo de la misma?

Código
  1. fseek(file, -1L*sizeof(Idiomas), SEEK_CUR);

Código
  1. void guardar( Idiomas idiomas, char *nombreArchivo, long numeroRegistros ){
  2. FILE *file = fopen( nombreArchivo, "a+b" );
  3. int i=0;
  4.  
  5. if( file != NULL ){
  6. numeroRegistros += 1;
  7.  
  8. if( numeroRegistros > 1 ){
  9. Idiomas tmp;
  10. tmp.habilitado = idiomas.habilitado;
  11. strcpy( tmp.ingles, idiomas.ingles );
  12. strcpy( tmp.espaniol, idiomas.espaniol);
  13. tmp.orden = 1;
  14.  
  15. fseek (file, 0L, SEEK_SET);
  16. while( fread( &idiomas, sizeof(Idiomas), 1, file) ){
  17. i = strcmp( tmp.ingles, idiomas.ingles );
  18. if( i < 0 ){
  19. idiomas.orden += 1;
  20. printf("\n antes...: %p", file);
  21. file -= sizeof( Idiomas );
  22. // fseek(file, -1L*sizeof(Idiomas), SEEK_CUR);
  23. printf("\n despues.: %p", file); getchar();
  24. fwrite( &idiomas, sizeof(Idiomas), 1, file );
  25. }else{
  26. tmp.orden += 1;
  27. }
  28. }
  29. fwrite( &tmp, sizeof(Idiomas), 1, file );
  30. }else{
  31. idiomas.orden = 1;
  32. fwrite( &idiomas, sizeof(Idiomas), 1, file );
  33. }
  34. }else{
  35. printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", nombreArchivo );
  36. }
  37.  
  38. fclose( file );
  39. }
  40.  
Saludos.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 18 Septiembre 2016, 16:52 pm
Nunca lo he provado de esa forma prefiero manejarlo desde el SEEK_SET para hacerlo desde el inicio del archivo. lo que me gusta hacer es tener un contador para saber cual es el numero de registro actual y si quiero regrersar al que previamente lei lo que hago es

Código
  1. fseek(file, (contador-1)*sizeof(Idiomas), SEEK_SET);

Tendria que probar con la posición SEEK_CUR como lo mencionas.

Saludos!


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: NOB2014 en 21 Septiembre 2016, 00:47 am
Hola. -
una consulta, si tengo un archivo con palabras desordenadas y luego las ordeno en un arreglo de estructura, como debo hacer para escribir en el archivo nuevamente, tengo que borrarlo primero o puedo sobrescribir registro por registro. - 


desde ya muchas gracias.


Título: Re: Tutorial de archivos en lenguaje C. -
Publicado por: AlbertoBSD en 21 Septiembre 2016, 16:19 pm
De las 2 formas es valido.

Si es la misma cantidad de registros no hay por que preocuparse...

Se mueve a la posicion 0 con fseek y se escribe registro por registro.

En caso de que quieraa reescribir (borrar y escribir)

Solo hay que cerrar el archivo actual y abrir uno nuevo con el mismo nombre y en modo "w" o "wb" segun sea de texto o binario y asi escribir registro por registro en el archivo nuevo.

Saludos