Tutorial de archivos en lenguaje C. -

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

0 Miembros y 2 Visitantes están viendo este tema.

NOB2014

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. -

#include <stdio.h>
#include <string.h>

int main(void){
int numeros[10] = {0}, ordenar[10] = {0}, ingreso = 0;
int i, j;

for( i=0; i<10; i++ ){
printf(" \n Ingrese un entero (cero para finalizar)....: ");
scanf("%d", &ingreso);

if( ingreso == 0 ){
break;
}

numeros[i] = ingreso;
ordenar[i] = 1;

if( i > 0 ){
j=0;
while( j < i ){
if( ingreso < numeros[j] ){
ordenar[j] += 1;
}else{
ordenar[i] += 1;
}
j++;
}
}
}

printf("\n\n  Numeros ==> ");
for( i=0; i<10; i++ ){
printf("%2d ", numeros[i]);
}
printf("\n  Ordenar ==> ");
for( i=0; i<10; i++ ){
printf("%2d ", ordenar[i]);
}

return 0;
}

     
     

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

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.-

crack81

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

#include <stdio.h>
#include<windows.h>
#include <time.h>

double performancecounter_diff(LARGE_INTEGER *a, LARGE_INTEGER *b){
    LARGE_INTEGER freq;
    QueryPerformanceFrequency(&freq);
    return (double)(a->QuadPart - b->QuadPart) / (double)freq.QuadPart;
}



void rellenarOrdenarDatos(int numeros[],int ordenar[],int tamano){
    int i,j,ingreso;
    srand(time(NULL));

    for( i=0; i<tamano; i++){

        ingreso = rand()%100;
        numeros[i]=ingreso;
        ordenar[i] = 1;

        if(i>0){
            j=0;
            while(j<i){
                if( ingreso < numeros[j] ){
                    ordenar[j] += 1;
                }
                else{
                    ordenar[i] += 1;
                }
                j++;
            }
        }
    }
}

int main()
{
    const int TAMANO=15000;
    int *arreglo=malloc(sizeof(int)*TAMANO);
    int *ordenar=malloc(sizeof(int)*TAMANO);

    LARGE_INTEGER t_ini, t_fin;
    double secs;

    QueryPerformanceCounter(&t_ini);

    rellenarOrdenarDatos(arreglo,ordenar,TAMANO);

    QueryPerformanceCounter(&t_fin);

    secs = performancecounter_diff(&t_fin, &t_ini);
    printf("%.16g milliseconds\n", secs * 1000.0);

    free(arreglo);
    free(ordenar);

    return 0;
}


Entre las muestras que obtuve fueron estos tiempos en milisegundos
Citar937.9348
1006.7837
984.6807
917.7779
1013.7831
993.5917

Ahora la prueba con BubbleSort

#include <stdio.h>
#include<windows.h>
#include <time.h>

double performancecounter_diff(LARGE_INTEGER *a, LARGE_INTEGER *b){
    LARGE_INTEGER freq;
    QueryPerformanceFrequency(&freq);
    return (double)(a->QuadPart - b->QuadPart) / (double)freq.QuadPart;
}




void rellenarArreglo(int numeros[],unsigned int tamano){
    srand(time(NULL));
    int i=0;

    for(i=0; i<tamano; i++)
    {
        int r = rand()%100+1;
        numeros[i]=r;
    }
}

void bubbleSort(int numeros[],int tamano){
    int i,j,temp;
    for (i=1; i<tamano; i++){
      for(j=0 ; j<tamano - 1; j++){
         if (numeros[j] > numeros[j+1]){
            temp = numeros[j];
            numeros[j] = numeros[j+1];
            numeros[j+1] = temp;
         }
      }
    }
}



int main()
{
    const int TAMANO=15000;
    int *arreglo=malloc(sizeof(int)*TAMANO);


    LARGE_INTEGER t_ini, t_fin;
    double secs;

    QueryPerformanceCounter(&t_ini);

    rellenarArreglo(arreglo,TAMANO);
    bubbleSort(arreglo,TAMANO);

    QueryPerformanceCounter(&t_fin);

    secs = performancecounter_diff(&t_fin, &t_ini);
    printf("%.16g milliseconds\n", secs * 1000.0);

    free(arreglo);


    return 0;
}


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

void qs(int lista[],int limite_izq,int limite_der)
{
    int izq,der,temporal,pivote;

    izq=limite_izq;
    der = limite_der;
    pivote = lista[(izq+der)/2];

    do{
        while(lista[izq]<pivote && izq<limite_der)izq++;
        while(pivote<lista[der] && der > limite_izq)der--;
        if(izq <=der)
        {
            temporal= lista[izq];
            lista[izq]=lista[der];
            lista[der]=temporal;
            izq++;
            der--;

        }

    }while(izq<=der);
    if(limite_izq<der){qs(lista,limite_izq,der);}
    if(limite_der>izq){qs(lista,izq,limite_der);}

}

void quicksort(int lista[],int n)
{
    qs(lista,0,n-1);
}



int main()
{
    const int TAMANO=15000;
    int *arreglo=malloc(sizeof(int)*TAMANO);


    LARGE_INTEGER t_ini, t_fin;
    double secs;

    QueryPerformanceCounter(&t_ini);

    rellenarArreglo(arreglo,TAMANO);
    quicksort(arreglo,TAMANO);

    QueryPerformanceCounter(&t_fin);

    secs = performancecounter_diff(&t_fin, &t_ini);
    printf("%.16g milliseconds\n", secs * 1000.0);

    free(arreglo);


    return 0;
}


Aqui una lista de tiempos obtenidos
Citar2.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:




Si C/C++ es el padre de los lenguajes entonces ASM es dios.

NOB2014

Hola, crack81, como estas.
Tal vez no leíste por donde venia el tema o no me supe explicar en el post anterior. -

CitarHola 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. -



Saludos, un abrazo.

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

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!

Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

NOB2014

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. -

void guardar( Idiomas idiomas, char *nombreArchivo, long numeroRegistros ){
FILE *file = fopen( nombreArchivo, "ab" );
Idiomas tmp;
tmp.habilitado = idiomas.habilitado;
strcpy( tmp.ingles, idiomas.ingles );
strcpy( tmp.espaniol, idiomas.espaniol);
tmp.orden = 1;


if( file != NULL ){
numeroRegistros += 1;

if( numeroRegistros > 1 ){
fseek( file, 0, SEEK_SET );
while( fread( &idiomas, sizeof(Idiomas), 1, file )){
if( strcmp( tmp.ingles, idiomas.ingles ) < 0 ) {
idiomas.orden += 1;
fwrite( &idiomas, sizeof(Idiomas), 1, file );
}else{
tmp.orden += 1;
}
}
}
fwrite( &tmp, sizeof(Idiomas), 1, file );
}else{
printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", nombreArchivo );
}

fclose( file );
}




Saludos y desde ya muchas gracias. -
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

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 !=

strcmp( tmp.ingles, idiomas.ingles ) != 0

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

NOB2014

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. -

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?

fseek(file, -1L*sizeof(Idiomas), SEEK_CUR);

void guardar( Idiomas idiomas, char *nombreArchivo, long numeroRegistros ){
FILE *file = fopen( nombreArchivo, "a+b" );
int i=0;

if( file != NULL ){
numeroRegistros += 1;

if( numeroRegistros > 1 ){
Idiomas tmp;
tmp.habilitado = idiomas.habilitado;
strcpy( tmp.ingles, idiomas.ingles );
strcpy( tmp.espaniol, idiomas.espaniol);
tmp.orden = 1;

fseek (file, 0L, SEEK_SET);
while( fread( &idiomas, sizeof(Idiomas), 1, file) ){
i = strcmp( tmp.ingles, idiomas.ingles );
if( i < 0 ){
idiomas.orden += 1;
printf("\n antes...: %p", file);
file -= sizeof( Idiomas );
// fseek(file, -1L*sizeof(Idiomas), SEEK_CUR);
printf("\n despues.: %p", file); getchar();
fwrite( &idiomas, sizeof(Idiomas), 1, file );
}else{
tmp.orden += 1;
}
}
fwrite( &tmp, sizeof(Idiomas), 1, file );
}else{
idiomas.orden = 1;
fwrite( &idiomas, sizeof(Idiomas), 1, file );
}
}else{
printf( "\n Error al abrir %s para escritura/lectura. Finaliza el programa.", nombreArchivo );
}

fclose( file );
}

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

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

fseek(file, (contador-1)*sizeof(Idiomas), SEEK_SET);

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

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

NOB2014

#38
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.
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

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
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW