Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: m@o_614 en 30 Enero 2014, 21:55 pm



Título: problemas con fseeks
Publicado por: m@o_614 en 30 Enero 2014, 21:55 pm
Saludos, tengo problemas con unos fseeks que tengo dentro de un ciclo while que me lee un archivo, pero a la hora de imprimir el archivo no lo hace correctamente

este es el codigo:

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #define MAX 8
  5.  
  6. typedef enum {INS,OP,DIR,MAQ,CALCULADO,CALCULAR,TOTAL} tabla;
  7.  
  8. void buscarFinLinea(FILE *hc12);
  9. void listaTABOP();
  10. char *Tabla_Operandos(FILE *hc12,int tabla);
  11. void ignorarEspacios(FILE *hc12);
  12. void quitarSaltosLinea(char *cadena);
  13.  
  14. int main()
  15. {
  16.    listaTABOP();
  17.    return 0;
  18. }
  19.  
  20. void buscarFinLinea(FILE *hc12)
  21. {
  22.    int car;
  23.    while((car = fgetc(hc12))!= '\n')
  24.        ;
  25. }
  26.  
  27. void quitarSaltosLinea(char *c)
  28. {
  29.    char *ptr;
  30.    if(((ptr = strchr(c,'\n'))!= NULL)||((ptr = strchr(c,'\t'))!= NULL)||((ptr = strchr(c,' '))!= NULL))
  31.       *ptr = '\0';
  32. }
  33.  
  34. void listaTABOP()
  35. {
  36.    int car,i,pos,n;
  37.    FILE *hc12;
  38.    COD *ultimo = NULL;
  39.    char *ins,*op,**dir,**maq,**cal,**x_cal,**sum;
  40.    if((hc12 = fopen("Tabla_OP.txt","r"))!= NULL)
  41.    {
  42.        while((car = fgetc(hc12))!= EOF)
  43.        {
  44.            i = 0;
  45.            fseek(hc12,-1,SEEK_CUR);
  46.            ins = Tabla_Operandos(hc12,INS);
  47.            printf("[%s]\t",ins);
  48.            ignorarEspacios(hc12);
  49.            op = Tabla_Operandos(hc12,OP);
  50.            printf("[%s]",op);
  51.            pos = ftell(hc12);
  52.            buscarFinLinea(hc12);
  53.            if((car = fgetc(hc12)) != '\t')
  54.            {
  55.                n = 0;
  56.                fseek(hc12,pos,SEEK_SET);
  57.                ignorarEspacios(hc12);
  58.                dir = (char**)malloc(sizeof(char*));
  59.                dir[i] = Tabla_Operandos(hc12,DIR);
  60.                printf("\t[%s]\t",dir[i]);
  61.                ignorarEspacios(hc12);
  62.                maq = (char**)malloc(sizeof(char*));
  63.                maq[i] = Tabla_Operandos(hc12,MAQ);
  64.                printf("[%s]\t",maq[i]);
  65.                ignorarEspacios(hc12);
  66.                cal = (char**)malloc(sizeof(char*));
  67.                cal[i] = Tabla_Operandos(hc12,CALCULADO);
  68.                printf("[%s]\t",cal[i]);
  69.                ignorarEspacios(hc12);
  70.                x_cal = (char**)malloc(sizeof(char*));
  71.                x_cal[i] = Tabla_Operandos(hc12,CALCULAR);
  72.                printf("[%s]\t",x_cal[i]);
  73.                ignorarEspacios(hc12);
  74.                sum = (char**)malloc(sizeof(char*));
  75.                sum[i] = Tabla_Operandos(hc12,TOTAL);
  76.                printf("[%s]\n",sum[i]);
  77.                buscarFinLinea(hc12);
  78.            }
  79.            else
  80.            {
  81.                n = 1;
  82.                fseek(hc12,pos,SEEK_SET);
  83.                dir = (char**)malloc(MAX*sizeof(char*));
  84.                maq = (char**)malloc(MAX*sizeof(char*));
  85.                cal = (char**)malloc(MAX*sizeof(char*));
  86.                x_cal = (char**)malloc(MAX*sizeof(char*));
  87.                sum = (char**)malloc(MAX*sizeof(char*));
  88.                do
  89.                {
  90.                    ignorarEspacios(hc12);
  91.                    dir[i] = Tabla_Operandos(hc12,DIR);
  92.                    printf("\t[%s]\t",dir[i]);
  93.                    ignorarEspacios(hc12);
  94.                    maq[i] = Tabla_Operandos(hc12,MAQ);
  95.                    printf("[%s]\t",maq[i]);
  96.                    ignorarEspacios(hc12);
  97.                    cal[i] = Tabla_Operandos(hc12,CALCULADO);
  98.                    printf("[%s]\t",cal[i]);
  99.                    ignorarEspacios(hc12);
  100.                    x_cal[i] = Tabla_Operandos(hc12,CALCULAR);
  101.                    printf("[%s]\t",x_cal[i]);
  102.                    ignorarEspacios(hc12);
  103.                    sum[i] = Tabla_Operandos(hc12,TOTAL);
  104.                    printf("[%s]\n",sum[i]);
  105.                    buscarFinLinea(hc12);
  106.                    i++;
  107.                    printf("\t");
  108.                }while((car = fgetc(hc12)) == '\t');
  109.            }
  110.        }
  111.    }
  112.    else
  113.       printf("No se pudo abrir el archivo");
  114. }
  115.  
  116. void ignorarEspacios(FILE *hc12)
  117. {
  118.    int car;
  119.    do
  120.    {
  121.        car = fgetc(hc12);
  122.    }while(car == '\t' || car == ' ');
  123. }
  124.  
  125. char *Tabla_Operandos(FILE *hc12,int tabla)
  126. {
  127.    int car,lon = 0,pos;
  128.    char *c;
  129.    fseek(hc12,-1,SEEK_CUR);
  130.    pos = ftell(hc12);
  131.    if((tabla==INS)||(tabla==OP)||(tabla==DIR)||(tabla==MAQ)||(tabla==CALCULADO)||(tabla==CALCULAR))
  132.    {
  133.        do
  134.        {
  135.            car = fgetc(hc12);
  136.            lon++;
  137.        }while(car != '\t' && car != EOF);
  138.    }
  139.    else
  140.    {
  141.        do
  142.        {
  143.            car = fgetc(hc12);
  144.            lon++;
  145.        }while(car != '\n' && car != EOF);
  146.        lon--;
  147.    }
  148.    fseek(hc12,pos,SEEK_SET);
  149.    c = (char*)calloc((lon+1),sizeof(char));
  150.    fgets(c,lon+1,hc12);
  151.    quitarSaltosLinea(c);
  152.    return c;
  153. }
  154.  
[
y el archivo es
quote]ABA         NO   INH      1806      2   0   2
          ADCA   SI   IMM      89ii      1   1   2
                            DIR      99dd      1   1   2
                            EXT      B9hhll   1   2   3
                            IDX      A9xb      1   1   2
                            IDX1      A9xbff   1   2   3
                            IDX2      A9xbeeff   1   3   4
                            [D,IDX]   A9xb      1   1   2
                            [IDX2]   A9xbeeff   1   3   4[/quote]
el problema es que  cuando llega al codop ADCA no me imprime toda la linea solo me imprime

[]....[ADCA]...[SI]...[IMM]...[89ii]....[1]...[1]

 esto se arregla si le quito el primer fseek() que aparece en el while() de la funcion listaTABOP, pero si se lo quito ahora los codops siguientes al ADCA los imprime sin la primer letra, se la come,entonces como puedo arreglar este problema

gracias


Título: Re: problemas con fseeks
Publicado por: x64core en 31 Enero 2014, 05:21 am
¿Has depurado la aplicación?


Título: Re: problemas con fseeks
Publicado por: m@o_614 en 31 Enero 2014, 18:32 pm
Saludos x64Core el problema es que no se usar el depurador de codeblocks :S lo intente con un tutorial pero no pude


Título: Re: problemas con fseeks
Publicado por: x64core en 31 Enero 2014, 19:31 pm
Saludos x64Core el problema es que no se usar el depurador de codeblocks :S lo intente con un tutorial pero no pude
Pues te recomiendo que empieces a aprender a usarlo usar los depuradores para encontrar errores en tus programas es tan
indispensable y realmente no es nada dificil.


Título: Re: problemas con fseeks
Publicado por: Yoel Alejandro en 5 Febrero 2014, 01:57 am
Bueno x64Core particularmente no soy partidario de usar depuradores o cosas por es estilo, prefiero ir "a manita limpia", y me ha funcionado bien porque así ejercitas más el cerebro, jeje :laugh:

El problema al parecer es que te mueves para adelante y para atrás en el archivo, abusando de fseek. Un buen programador debe ser cauto, debe simplemente evitar andar por terrenos peligrosos, y el estilo de tu programación está siendo definitivamente muy vulnerable. Cualquier error o descuido y tienes un comportamiento completamente impredecible.

Usa el principio de "divide y vencerás". Ve, hazlo así. Coje una línea del archivo txt, y la pasas a una función que analice sintácticamente para detectar sus divisiones en columnas con el carácter tabulador, es decir, lo que hace tablaOperandos. Pero que tablaOperandos y listaTABOP NO SE MUEVAN juntas por el mismo archivo. Eso NUNCA se hace, cada función debe tener su espacio de trabajo "privado". ¿Entiendes la filosofía subyacente?

Entonces, vamos a hacer una función que vaya cogiendo una línea del archivo, y la copie a un arreglo tipo búfer, y se la pase a tablaOperandos, así esta última lee del búfer y no se mete para nada con el archivo original (reduciendo el riesgo de conflictos).

En tu código original tenías un problema porque tablaOperandos al leer la línea avanzaba el indicador de posición de archivo, luego tenías que devolverlo a su posición original con [ttfseek[/tt], etc ....  muy engorroso. Con esta solución no tienes que hacer nada de eso:

Código:

#define CR 13
#define LF 10

void readLine ( FILE* hc12, char *buffer ) {

cchar c;
int i;

i = 0;
while ( !feof(hc12) && (c = fgetc(hc12)) != CR && c != LF )  
buffer[i++] = c;

buffer[i] = '\0';

/* avanzamos hasta que no haya CR ni LF */
while ( ( c = fgetc(hc12) ) == CR || c == LF )
;
/* devolvemos el último carácter leído */
if ( !feof(hc12) ) ungetc(c, hc12);
}

y listo, agarras ese buffer y se lo pasas a tablaOperandos. Claro, antes debes haber definido el buffer como un arreglo con la suficiente longitud para contener cualquier posible línea del archivo (no se, 100 caracteres quizás). Ahora acomoda tablaOperandos para que trabaje sobre un arreglo y no sobre un fichero.

Te explico la última parte del código antes mostrado. En ficheros de texto el fin de línea se hace con una sucesión de dos caracteres, generalmente el <i>carriage return</i> CR seguido de <i>linefeed</i> LF. Entonces, si alcanzas digamos el CR, pues cierras el búfer. Pero al invocar el nuevo la función, leerá el LF y cerrará el búfer ... ¡vacío! O sea, que después de una llamada exitosa a readLinea la próxima llamada que ejecutes devolverá un búfer vacío. Para evitar eso, se bede avanzar el indicador de posición de archivo hasta no encontrar ni CR ni LF, luego de cerrar el búfer de línea. Es lo que hace el:

Código:
	/* avanzamos hasta que no haya CR ni LF */
while ( ( c = fgetc(hc12) ) == CR || c == LF )
;
/* devolvemos el último carácter leído */
if ( !feof(hc12) ) ungetc(c, hc12);

Te voy a explicar algo, el uso de ungetc(). Supón que tienes un fichero así:

Código:
Pedro
Maria

entonces empieza a leer la línea Pedro, hasta que haya la secuencia CR + LF. Primero lee CR, entonces sabe que debe continuar hasta que no haya ni CR ni LF. Así leee CR, luego LF, luego la M inicial de "Maria". Ahí sabe que se terminó la primera línea. Pero hemos agarrado la 'M', luego tenemos que "devolverla" al fichero, por eso usamos ungetc. Es algo parecido a lo que hacías con fseek( hc12, -1, SEEK_CUR ).
    


Título: Re: problemas con fseeks
Publicado por: Yoel Alejandro en 5 Febrero 2014, 03:34 am
Continuando con el tema, ahora queremos una función que tome un búfer de línea del archivo, y sepa encontrar los distintos campos separados por espacios. Aquí la tienes, su código es breve pero maneja unos conceptos un poquito complicados de apuntadores, como por ejemplo el apuntador pasado por referencia o puntero-a-puntero del tipo char **. Si no lo entiendes me lo preguntas luego y te lo explico bien.:

Código
  1. /* Lee un campo del búfer, considerando un campo como toda sucesión de
  2.    caracteres de no espacio. Devuelve NULL si no hay más campos que leer */
  3. char * readField( char ** buffer_ptr ) {
  4.  
  5. int i;
  6. char c;
  7. char * buffer = *buffer_ptr;
  8.  
  9. if ( *buffer == '\0' ) return NULL;
  10.  
  11. /* elimina los espacios iniciales */
  12. while ( *buffer == ' ' || *buffer == '\t' )
  13. buffer++;
  14.  
  15. /* ahora toma la porción inicial de la cadena hasta encontrar
  16.   espacio o tabulador */
  17. i = 0;
  18. while ( (c = buffer[i]) != '\0' && c != ' ' && c != '\t' )
  19. i++;
  20.  
  21. /* finaliza la sub-cadena donde halló el carácter espacio o tabulador */
  22. buffer[i] = '\0';
  23.  
  24. /* y si hay más sub-cadenas que leer, avanza el búfer */
  25. if ( c != '\0' )
  26. *buffer_ptr = buffer + i + 1;
  27. else
  28. *buffer_ptr = buffer + i;
  29.  
  30. if ( i > 0 )
  31. return buffer; /* leyó al menos un carácter */
  32. else
  33. return NULL; /* no leyó nada */
  34. }
  35.  


Título: Re: problemas con fseeks
Publicado por: Yoel Alejandro en 5 Febrero 2014, 03:49 am
Ok, ahora vamos a poner todo junto, a mí me salió en apenas 89 líneas de código. Y creé un fichero de texto de prueba con el mismo contenido que tú dices, y me imprimió la tabla perfecta ;D

Es cuestión de ser hábil combinando las cosas, así puedes lograr mucho con poco ... Bueno, espero te sirva, aquí tienes el fuente completo con el main() y todo, sólo de copiar, pegar, compilar y probar.

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. #define CR 10
  5. #define LF 13
  6.  
  7. typedef enum {INS, OP, DIR, MAQ, CALCULADO, CALCULAR, TOTAL} tabla;
  8.  
  9. void readLine ( FILE *, char * );
  10. char * readField( char ** );
  11.  
  12. int main()
  13. {
  14. char * buffer, * old_buffer;
  15. char * field;
  16. FILE * hc12;
  17.  
  18. if ( ( buffer = (char *) malloc( 101 * sizeof(char) ) ) == NULL ) return -1;
  19. if ( ( field = (char *) malloc( 101 * sizeof(char) ) ) == NULL ) return -1;
  20.  
  21. if ( ( hc12 = fopen( "file1.txt", "r") ) == NULL ) return -1;
  22.  
  23. while ( !feof( hc12) ) {
  24. readLine( hc12, buffer);
  25. old_buffer = buffer;
  26. while ( ( field = readField( &buffer ) ) != NULL ) {
  27. printf("%s\t", field);
  28. }
  29. printf("\n");
  30. buffer = old_buffer;
  31. }
  32.  
  33. fclose( hc12 );
  34.  
  35. return 0;
  36. }
  37.  
  38. void readLine ( FILE *hc12, char *buffer ) {
  39.  
  40. char c;
  41. int i;
  42.  
  43. i = 0;
  44. while ( !feof(hc12) && (c = fgetc(hc12)) != CR && c != LF )  
  45. buffer[i++] = c;
  46.  
  47. buffer[i] = '\0';
  48.  
  49. /* avanzamos hasta que no haya CR ni LF */
  50. while ( ( c = fgetc(hc12) ) == CR || c == LF )
  51. ;
  52. /* devolvemos el último carácter leído */
  53. if ( !feof(hc12) ) ungetc(c, hc12);
  54. }
  55.  
  56. /* Lee un campo del búfer, considerando un campo como toda sucesión de
  57.    caracteres de no espacio. Devuelve NULL si no hay más campos que leer */
  58. char * readField( char ** buffer_ptr ) {
  59.  
  60. int i;
  61. char c;
  62. char * buffer = *buffer_ptr;
  63.  
  64. if ( *buffer == '\0' ) return NULL;
  65.  
  66. /* elimina los espacios iniciales */
  67. while ( *buffer == ' ' || *buffer == '\t' )
  68. buffer++;
  69.  
  70. /* ahora toma la porción inicial de la cadena hasta encontrar
  71.   espacio o tabulador */
  72. i = 0;
  73. while ( (c = buffer[i]) != '\0' && c != ' ' && c != '\t' )
  74. i++;
  75.  
  76. /* finaliza la sub-cadena donde halló el carácter espacio o tabulador */
  77. buffer[i] = '\0';
  78.  
  79. /* y si hay más sub-cadenas que leer, avanza el búfer */
  80. if ( c != '\0' )
  81. *buffer_ptr = buffer + i + 1;
  82. else
  83. *buffer_ptr = buffer + i;
  84.  
  85. if ( i > 0 )
  86. return buffer; /* leyó al menos un carácter */
  87. else
  88. return NULL; /* no leyó nada */
  89. }
  90.  

Pruébalo y me dices!!

==========================================
Por cierto y aparte, noté que tienes en el código original una sentencia que no entiendo bien:
Código
  1. dir = (char**)malloc(sizeof(char*));
  2. dir[i] = Tabla_Operandos(hc12,DIR);
  3.  
Ok, ve. Con el malloc defines un arreglo dir de UN único elemento del tipo puntero a char, que luego rellenas con el string que produce la función Tabla_Operandos. Ahora, dos preguntas: ¿Dónde reservas el espacio de la memoria para los restantes elementos del arreglo dir, aparte del primero?
Además, si dir contendrá un string, ¿dónde reservas la memoria para dicho arreglo de caracteres? Eso tiene que hacerse de la siguiente manera:

Código
  1. /* Reservando el arreglo dir como arreglo de cadenas */
  2. / *  (dir_length es la longitud que esperas para dir ) */
  3. dir = (char **) malloc( dir_length * sizeof (char *) );
  4.  
  5. /* ahora se reserva memoria para cada string dentro del arreglo */
  6. for ( i = 0; i < dir_length; i++ )
  7.    dir[i] = (char *) malloc( s_length * sizeof(char) );
  8. /* donde s_length es la longitud deseada para cada string */
  9.  

De hecho, no se cómo el programa no te produjo un error de "violación de segmento" en tiempo de ejecución ... :o

De, hecho, cada vez que se usa malloc uno tiene que comprobar si la asignación de memoria se produjo con éxito (casi siempre así sucede, pero no se puede dar por sentado). Si no se pudo asignar memoria, se debe salir del programa:

Código
  1. /* Reservando el arreglo dir como arreglo de cadenas */
  2. / *  (dir_length es la longitud que esperas para dir ) */
  3. dir = (char **) malloc( dir_length * sizeof (char *) );
  4. if ( dir == NULL ) return -1;
  5.  
  6. /* ahora se reserva memoria para cada string dentro del arreglo */
  7. for ( i = 0; i < dir_length; i++ ) {
  8.    dir[i] = (char *) malloc( s_length * sizeof(char) );
  9.    if ( dir[i] == NULL ) return -1;
  10. }
  11.  
y esto te evitará cualquier "comportamiento inesperado" del programa, para que no te pase como a Windows que se cuelga a cada rato jeje.

Saludos, y quedo a la orden para cualquier cosa .... Yoel



Título: Re: problemas con fseeks
Publicado por: rir3760 en 6 Febrero 2014, 03:13 am
El problema al parecer es que te mueves para adelante y para atrás en el archivo, abusando de fseek.
Eso es algo que ya se recomendó a m@o_614 en otros temas pero por alguna razón (valida o no, no lo se) simplemente no la sigue.

Te explico la última parte del código antes mostrado. En ficheros de texto el fin de línea se hace con una sucesión de dos caracteres, generalmente el <i>carriage return</i> CR seguido de <i>linefeed</i> LF. Entonces, si alcanzas digamos el CR, pues cierras el búfer. Pero al invocar el nuevo la función, leerá el LF y cerrará el búfer ... ¡vacío! O sea, que después de una llamada exitosa a readLinea la próxima llamada que ejecutes devolverá un búfer vacío. Para evitar eso, se bede avanzar el indicador de posición de archivo hasta no encontrar ni CR ni LF, luego de cerrar el búfer de línea.
No es necesario. Cuando se abre un archivo en modo texto (como es nuestro caso) las funciones de la biblioteca estándar convierten el carácter (o caracteres) que indican un avance de linea a '\n' de forma transparente. El proceso opuesto (convertir '\n' a lo que sea indique un avance de linea) también aplica.

Esa es una de las razones por las cuales no se recomienda el uso de fseek con streams en modo texto: no se puede garantizar que el numero de bytes coincida con el numero de caracteres.

Ya que la aproximación es leer la linea descartando el carácter '\n' la función se puede reducir a:
Código
  1. void readLine(FILE *in, char *line)
  2. {
  3.   int ch;
  4.  
  5.   while ((ch = fgetc(in)) != EOF && ch != '\n')
  6.      *line++ = ch;
  7.   *line = '\0';
  8. }
Se puede mejorar bastante pasando como argumento la capacidad del array y retornando un valor útil (el numero de caracteres almacenados).

Un saludo


Título: Re: problemas con fseeks
Publicado por: x64core en 6 Febrero 2014, 05:30 am
@yoel_alejandro:
En proyectos simples es facil, pero en proyectos considerablemente grandes no podes esperar que has manipulado todos los posibles errores.
Pero con ese comentario luces de las personas que tiene poca experiencia en eso. de todos modos espero verte
más seguido por aquí ya vamos a ver si realmente sabes como dices.


Título: Re: problemas con fseeks
Publicado por: Yoel Alejandro en 7 Febrero 2014, 03:04 am
A ver, rir3760, explícame bien lo del problema con el avance de línea, porque según recuerdo una vez tuve problemas con eso. De ahí que siempre le pongo dicha prevención en el código. Tengo entendido además que por lo general los sistemas Windows codifican el fin de línea con dos caracteres (0x0D + 0x0A, o en decimal 13 + 10), mientras los UNIX usan simplemente el 0x0A.

Vamos por partes: Me tratas de decir que si por ejemplo fgetc() encuentra una sucesión CR + LF , entonces lee un sólo '\n' y avanza el indicador de posición de archivo en dos bytes, de modo que la próxima llamada a fgect() leerá el siguiente carácter después del LF. ¿¿Es eso así??

==============
Ah, y x64Core, no ingresé a este foro para pelear con nadie, sino para ayudar a los demás. Simplemente tengo una filosofía de que me gusta hacer las cosas a mano, en lugar de recurrir a recursos o softwares sofisticados.

Por ejemplo, uso la IDE más sencilla y sólo como editor, pues rara vez compilo usando los íconos de la barra de herramientas. Yo compilo desde la terminal y le meto yo mismo las directivas de "include" y de "lib" en la orden de compilación.

Hasta ahora me ha funcionado y he creado aplicaciones de cierta complejidad. Por supuesto me lleva más tiempo pero estoy seguro de que he construido y verificado POR MÍ MISMO cada línea de mi código, por eso confío en él.

De nuevo, no es por polemizar, simplemente es mi filosofía de trabajo. Cada quién tiene la suya y se le respeta  :)


Título: Re: problemas con fseeks
Publicado por: rir3760 en 7 Febrero 2014, 03:41 am
Tengo entendido además que por lo general los sistemas Windows codifican el fin de línea con dos caracteres (0x0D + 0x0A, o en decimal 13 + 10), mientras los UNIX usan simplemente el 0x0A.
Correcto, en MS-DOS (QEPD) y MS Windows el avance de linea se indica con '\r' + '\n', en Linux con '\n'.

Me tratas de decir que si por ejemplo fgetc() encuentra una sucesión CR + LF , entonces lee un sólo '\n' y avanza el indicador de posición de archivo en dos bytes, de modo que la próxima llamada a fgect() leerá el siguiente carácter después del LF. ¿¿Es eso así??
Exacto siempre y cuando el modo del stream sea texto, si el modo es binario (por ejemplo cuando se abre un archivo indicando el modo "rb") se presenta el problema que mencionas (cada carácter se retorna tal cual sin importar su valor).

Un saludo


Título: Re: problemas con fseeks
Publicado por: x64core en 7 Febrero 2014, 05:00 am

==============
Ah, y x64Core, no ingresé a este foro para pelear con nadie, sino para ayudar a los demás. Simplemente tengo una filosofía de que me gusta hacer las cosas a mano, en lugar de recurrir a recursos o softwares sofisticados.

Por ejemplo, uso la IDE más sencilla y sólo como editor, pues rara vez compilo usando los íconos de la barra de herramientas. Yo compilo desde la terminal y le meto yo mismo las directivas de "include" y de "lib" en la orden de compilación.

Hasta ahora me ha funcionado y he creado aplicaciones de cierta complejidad. Por supuesto me lleva más tiempo pero estoy seguro de que he construido y verificado POR MÍ MISMO cada línea de mi código, por eso confío en él.

De nuevo, no es por polemizar, simplemente es mi filosofía de trabajo. Cada quién tiene la suya y se le respeta  :)
Escribir los include's y lib's siempre no te parece que es simplemente una perdida de tiempo?, Yp sé que al inicio es una forma para
saber como realmente funciona el proceso de compilación, qué tipo de archivos y como son procesados por el compilador y el linker
esta bien, pero escribirlos por toda la vida, en todos tus programas simplemente lo veo una perdida de tiempo, al menos se debe crear
un script que lo haga por ti. Y lo digo para que la gente no lo haga, lo cual no es necesario, yo sé que estaría cuestionando la manera
en que cada persona lo hace pero es simplemente una recomendación y si a pesar de eso yoel_alejandro, crees que es siempre
conveniente escribir siempre los include's y lib's talvez nos puedes explicar el ¿porqué?





Título: Re: problemas con fseeks
Publicado por: Yoel Alejandro en 8 Febrero 2014, 04:26 am
Escribir los include's y lib's siempre no te parece que es simplemente una perdida de tiempo?, Yp sé que al inicio es una forma para
saber como realmente funciona el proceso de compilación, qué tipo de archivos y como son procesados por el compilador y el linker
esta bien, pero escribirlos por toda la vida, en todos tus programas simplemente lo veo una perdida de tiempo (...) crees que es siempre
conveniente escribir siempre los include's y lib's talvez nos puedes explicar el ¿porqué?

Bueno, una razón es básicamente para saber. Otra es porque generalmente cuando se está desarrollando un trabajo grande, uno crea clases que llevan ficheros include personalizados, y si lo vuelves una biblioteca, tendrás directorios de lib. Estos claro no son los de la biblioteca estándar de C que los incluye el compilador sino los directorios personalizados que uno crea.

En mi caso, normalmente paso por fases experimentales de prueba donde las bibliotecas van a un directorio "temporal" donde son probadas y luego a su lugar definitivo. Así que estoy creado, moviendo y eliminando directorios todo el tiempo  :)

Con una IDE de desarrollo de C++ se puede "editar" el proyecto para añadir o eliminar estos ficheros, pero como es una interfaz gráfica que se maneja con ratón, en lo personal siento que me manejo mucho más rápido con el teclado que con el ratón (me gusta usar puro Alt+Tab, Alt+Repag, Ctrl+AvPag, Shitf+F10 y cosas por el estilo). Por eso es que todo lo hago por la cónsola y por supuesto compilar mis proyectos de C es una de esas actividades.

Por otra parte, ¿qué son las IDE's gráficas sino una interfaz con un script o conjunto de comandos corriendo detrás? Siendo así, prefiero ir de una vez a los comandos y saltarme lo visual, jeje :laugh:

Aquí mismo para meter texto en negrita, o hacer los codes, prefiero escribir las etiquetas a mano (\[ b \], \[i\], etc) que pulsar el iconito, no se ... me parece maś rápido ....

Ahora, en lo de hacer scripts de compilación tienes razón, últimamente he estado preparando ficheros Make para facilitar la tarea ...

Pero hasta para compilar un ejemplo pequeñito (como problemas pequeños que plantean usuarios de aquí y quiero probar compilando en realidad) apelo a mi gcc/g++ y cónsola, no se ..... es un hábito que se me ha quedado.

Es la ventaja de Linux, que todo lo puedes hacer con el teclado, incluso configurar tu fichero fstab para montar y desmontar las unidades externas usb manualmente. La última vez le quité los permisos de ejecución al nautilus para obligarme a navegar por directorios usando exclusivamente la consola y dejar de usar el explorador gráfico que ya me fastidia (jeje), ...... Quién sabe, a lo mejor un día te quedas sin escritorio gráfico (una vez me pasó) y luego ¿cómo vas a hacer?  :o

Bueno pero como decimos son cosas de gustos y filosofías, cada quién tiene la suya  :)

Creo haber explicado la razón por la que hago las cosas de ese modo, y al mismo tiempo he tomado tiempo para describir una parte de mí, no se si en este foro hay una sección para los usuarios hablar de sí mismos, sus gustos, formas de trabajo, etc ...


Título: Re: problemas con fseeks
Publicado por: x64core en 8 Febrero 2014, 05:49 am
Interesante, Programador C/C++,Scripting y como no, amante de Unix/Linux. Cómo es que no me extraña que un recién
usuario creado tenga tal conocimiento ( No por que sea un usuario de pocos 'posts' ), esa manera para desenvolverse
aquí en el foro, etc. Pero es bueno mirarte por aquí...

Y sí, ya esto es gusto de cada quien, yo en lo personal, mi entorno es Windows y dependiendo del proyecto que quiero
compilar uso el IDE, sino para proyectos pequeños ( pruebas de códigos, pequeñas clases, snippets, códigos de usuarios
del foro, etc. ) llamo a un pequeño programa que programé, el cual recibe como comando la ruta de archivo(s) fuentes,
cabeceras, archivos de recursos, [Liberarías adicionales] y crea un script en cual contiene las rutas relativas de los archivos.
sí, es un tipo de make pero me facilita más el trabajo a tan solo un click. La creación de este script además me permite
modificar/agregar/elimar parámetros hacia el compilador y linker ( Tipo de generación de código, Modificar valores de la cabera
del ejecutable generado, Tipo de optimización, conjunto de instrucciones, etc ).

Y bueno, mucho de que hablar.


Título: Re: problemas con fseeks
Publicado por: Yoel Alejandro en 8 Febrero 2014, 14:52 pm
Jaja, la verdad es que tengo tiempo programando (varios años), y no sólo en C, también he hecho scripts en Matlab, Assembler, VisualBasic y aplicaciones en el mini-VB que viene integrado con el Excel (estos últimos los dejé por lo limitado que eran).

Pero recién ahora fue que decidí ingresar a un foro para interacturar con otros miembros de la comunidad.

Respecto a los proyectos en C ¿te has animado a hacer alguna biblioteca/librería COMPLETA y lista para usar, y liberarla en la comunidad? Los fuentes por supuesto, más las instrucciones para su compilación e integración al sistema del usuario.

Yo estoy trabajando en una sencilla biblioteca de matrices bidimensionales numéricas, con clases y métodos predefinidas, donde el usuario declare el tamaño y ya se cree la matriz, además pueda redimensionarla en tiempo de ejecución (no que sea estática). Y de regalo, las operaciones algebraicas de sumar y multiplicar matrices, y quizás ....... resolver sistemas de ecuaciones jeje.

Yo doy por sentado que eso ya debe existir, y quizá muchas versiones de lo mismo, pero yo quiero hacer la mía y además con fines didácticos, liberar el código a la comunidad y explicar por qué se escribe esto y lo otro, etc  :)


Título: Re: problemas con fseeks
Publicado por: Yoel Alejandro en 8 Febrero 2014, 14:59 pm
rir3760, gracias por la explicación. Se me ocurre también otra forma en que la verificación manual sería necesaria (aparte de si el fichero se abre en binario), si por ejemplo el usuario que creó el txt dejó dos saltos de línea sucesivos (o sea, con una línea en blanco), entonces el programa lee '\n' y se detiene. La otra línea será sólo '\n' por lo que devolverá búfer vacío.

Si verificamos con CR-LF no pasa esto porque al encontrar la secuencia CR+LF+CR+LF él recorrerá hasta el último LF antes de salir.

Claro, otra forma de hacerlo sería incorporar la instrucción *buffer = '\0'; al inicio de la función readLine, de modo esté programado para devuelver un búfer vacío por defecto. Entonces, si devuelve vacío sabemos que había una línea en blanco (o saltos de línea repetidos), e invocamos otra vez a readLine

No se ..... tengo la sensación de que preguntar por '\n' y que fgetc se encargue de la conversión en cada tipo de sistema hará el programa más portable, pero por otra parte decodificar a mano hará el programa más seguro ...

¿Qué tal si alguien llenó el txt manualmente y puso una secuencia extraña tal como CR + LF + CR (o sea, una cantidad impar, ni dos ni cuatro)? ¿Qué me garantiza que fgetc() sabrá hacer "lo correcto" en este caso?


Título: Re: problemas con fseeks
Publicado por: rir3760 en 8 Febrero 2014, 18:03 pm
si por ejemplo el usuario que creó el txt dejó dos saltos de línea sucesivos (o sea, con una línea en blanco), entonces el programa lee '\n' y se detiene. La otra línea será sólo '\n' por lo que devolverá búfer vacío.

Si verificamos con CR-LF no pasa esto porque al encontrar la secuencia CR+LF+CR+LF él recorrerá hasta el último LF antes de salir.
Entonces entras en un problema de diseño: tienes una función que se llama "ReadLine" pero esta no lee una sino un numero variable dependiendo de las lineas en blanco.

Si tomamos la biblioteca estándar de C como ejemplo estas solo leen lo necesario, nada mas. De no hacerlo habría problemas para procesar un stream ya que, a criterio de las funciones, se descartarían caracteres.

¿Qué tal si alguien llenó el txt manualmente y puso una secuencia extraña tal como CR + LF + CR (o sea, una cantidad impar, ni dos ni cuatro)? ¿Qué me garantiza que fgetc() sabrá hacer "lo correcto" en este caso?
Nada pero en ese escenario tendrás problemas no solo con tu programa sino con cualquier aplicación que espere los avances de linea de una forma mientras que en el archivo se indican con otra (si tienes Linux debes conocer aplicaciones como unix2dos y dos2unix que se encargan de la conversión).

Un saludo