elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Únete al Grupo Steam elhacker.NET


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Extraer palabras de un texto leido en un archivo (en C)
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Extraer palabras de un texto leido en un archivo (en C)  (Leído 3,664 veces)
Locura_23

Desconectado Desconectado

Mensajes: 162



Ver Perfil
Extraer palabras de un texto leido en un archivo (en C)
« en: 21 Noviembre 2022, 14:42 pm »

Buenas a todos,
resulta que estoy teniendo un error con este codigo, tal vez no estoy viendo algo o me falta un concepto.
La idea seria leer un texto por usuario y guardarlo en un archivo binario,
segundo,  mostrarlo por consola,
y lo mas importante extraer todas y cada una de las palabras del texto ingresado por usuario.

Ahora bien, tengo entendido que los archivos binarios son mejores para guardar registros ( estructuras) y los archivos txt para texto. Lamentablemente, me piden que sean archivos binarios... Cosa que no le veo mucho sentido.
El error es que si ingreso un texto de mas de 3 o 4 palabras aveces algunas palabras se muestran con basura. Por ejemplo si ingreso  "la casa roja y el perro blanco" no hay problema.
Si ingreso "la raiz cuadrada de una potencia" entonces la palabra "cuadrada" muestra basura tambien. Esto por poner algunos ejemplos.
Este el codigo, (por cierto mucho que mejorar)
gracias, saludos.

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5.  
  6. #define ARCH0 "arch0.bin"
  7. #define TAM_MAX 1000
  8.  
  9. void crearArchivo()
  10. {
  11.    FILE* pfile = fopen(ARCH0, "wb");
  12.    char texto[TAM_MAX];
  13.  
  14.    if( pfile )
  15.    {
  16.        printf("\nIngrese el texto:\n");
  17.        gets(texto);
  18.  
  19.        fwrite(&texto,sizeof(texto),1,pfile);
  20.  
  21.        fclose(pfile);
  22.    }
  23. }
  24.  
  25. void mostrarArchivo()
  26. {
  27.    FILE* pfile = fopen(ARCH0, "rb");
  28.    char texto[TAM_MAX];
  29.  
  30.    if( pfile )
  31.    {
  32.        fread(&texto, sizeof(texto),1,pfile);
  33.  
  34.        puts(texto);
  35.  
  36.        fclose(pfile);
  37.    }
  38. }
  39.  
  40. void limpiarArreglo(char a[],int j)
  41. {
  42.    while( j - 1 >= 0 )
  43.    {
  44.        a[j] = 0;
  45.        j--;
  46.    }
  47. }
  48.  
  49. void archivoToDic()
  50. {
  51.    FILE* pfile = fopen(ARCH0,"rb");
  52.    char texto[TAM_MAX];
  53.    int i = 0; /**contador texto*/
  54.    char aux[30]; /**para guardar cada termino del texto*/
  55.    int j = 0; /**contador string aux*/
  56.  
  57.    if( pfile )
  58.    {
  59.        fread(&texto, sizeof(texto),1,pfile);
  60.  
  61.        while( i < strlen(texto) )
  62.        {
  63.            while( isalpha(texto[i]) )
  64.            {
  65.                /*copia cada letra leida distinta de espacio a la cadena auxiliar*/
  66.                aux[j] = texto[i];
  67.                j++;
  68.                i++;
  69.            }
  70.  
  71.            /*tras salir del while, aux contiene 1 palabra del texto, es decir, los caracteres hasta
  72.             el primer espacio encontrado*/
  73.            printf("\n%s\n",aux);
  74.  
  75.            system("pause");
  76.  
  77.            /*limpiar el arreglo y volver el contador j a 0*/
  78.            while( j - 1 >= 0 )
  79.            {
  80.                aux[j] = 0;
  81.                j--;
  82.            }
  83.            j = 0;
  84.  
  85.            /*el proceso sigue con todos los terminos*/
  86.            i++;
  87.        }
  88.  
  89.        fclose(pfile);
  90.    }
  91.  
  92. }
  93.  
  94. int main()
  95. {
  96.    crearArchivo();
  97.  
  98.    printf("\nContenido Archivo:\n");
  99.    mostrarArchivo();
  100.  
  101.    archivoToDic();
  102.  
  103.    return 0;
  104. }
  105.  

Por ultimo decir que pense como solucion utilizar memoria dinamica de manera que solo se guarden en el archivo estrictamente los caracteres del texto ingresado y no otra basura que me pueda estar guardando. qué opinan al respecto?


« Última modificación: 21 Noviembre 2022, 14:46 pm por Locura_23 » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Extraer palabras de un texto leido en un archivo (en C)
« Respuesta #1 en: 21 Noviembre 2022, 18:07 pm »

Tras un par de pruebas, todo parece indicar que a partir de palabras con 8 caracteres, se muestra basura al final.
De todas formas, aunque en alguna ocasión no se vea basura, no significa que el funcionamiento sea correcto. Por lo tanto, vamos a verlo...

Respondiendo a tu pregunta final: Se podría usar memoria dinámica? Sí. Es necesario? No. Ahora lo vas a ver...  :o


Parte 1: Crear fichero (a partir de aquí vamos a suponer que introduzco "hola")

Aquí ya podemos hacer varias mejoras:
  • Por un lado, vamos a reemplazar la función gets() por fgets(). Es la versión "segura" de gets() para evitar problemas si nos pasamos del tamaño máximo de la variable: fgets(texto, TAM_MAX, stdin)
    Con esto le estamos diciendo: guarda en <texto> los primeros TAM_MAX-1 (como mucho) caracteres obtenidos de stdin (entrada estándar). Si hay menos, guardará los que haya y si hay más, los ignorará y los dejará en el buffer (he aquí la magia mejorada en contra de gets())
    • Y por qué guarda TAM_MAX-1 caracteres si la capacidad es TAM_MAX? Porque al final siempre va a incluir "a terminating null character" (\0) que indica el fin de la cadena. En C siempre se indica el fin de una cadena de chars con un '\0'. Se nos habrá guardado en <texto> = {'h', 'o', 'l', 'a', '\0', ...}
    • fgets() almacena el carácter '\n' al pulsar Enter. Antes te engañé, en 'texto' se guardó = {'h', 'o', 'l', 'a', '\n', '\0', ...} Esto se puede solucionar de la siguiente manera:
Código
  1. fgets(texto, SIZE, stdin);
  2. // En mi opinion, este fragmento deberia ir practicamente siempre despues de un fgets() usando stdin como entrada
  3. if(texto[strlen(texto) - 1] == '\n')  // Si el ultimo caracter guardado (strlen devuelve el numero de chars hasta encontrar un '\0') es un Enter, significa que no queda nada en el buffer
  4.    texto[strlen(texto) - 1] = '\0';  // Adelanta el '\0' y sobreescribe el Enter (da igual todo lo que haya despues)
  5. else                                  // Y si no es Enter, significa que nos hemos pasado de longitud y han quedado cosas en el buffer, entre ellas el Enter
  6.    while(getchar() != '\n');         // entonces consumimos el buffer para dejarlo limpio y evitar errores futuros.
  7.  


  • Por otro lado, cuando escribimos el contenido en el fichero, tenemos que indicar el número de bytes que queremos escribir.
    En lugar de indicar sizeof(texto) que escribiría 1000 bytes en el fichero, vamos a indicar strlen(texto) para escribir sólo 4. Ves, no hacía falta usar memoria dinámica  ;-)
    Escribiendo strlen(texto) estaremos escribiendo EXACTAMENTE lo que el usuario introdujo, ni un carácter más ni uno menos. (Puedes usar un editor hexadecimal o un editor que muestre caracteres no imprimibles para ver el contenido exacto del fichero)
    Ahora tenemos esto:
Código
  1. void crearArchivo()
  2. {
  3.    FILE* pfile = fopen(ARCH0, "wb");
  4.    char texto[TAM_MAX];
  5.  
  6.    if( pfile ) {
  7.        printf("\nIngrese el texto:\n");
  8.        fgets(texto, TAM_MAX, stdin);
  9.  
  10.        if(texto[strlen(texto) - 1] == '\n') texto[strlen(texto) - 1] = '\0';
  11.        else while(getchar() != '\n');
  12.  
  13.        fwrite(texto, strlen(texto), 1, pfile);
  14.        fclose(pfile);
  15.    }
  16. }


Parte 2: Mostrar fichero

Aquí tenemos que leer el contenido del fichero. Lo importante es que no se nos cuele basura después del texto que hay dentro del fichero.
La solución más sencilla es inicializar el array de chars con 0s. 0 es el valor numérico del carácter nulo (0 = '\0')
De esta manera, con fread leeremos el contenido del fichero y el resto de espacio que sobre en el array ya estará rellenada con 0s por lo que no mostraremos ninguna basura.
Código
  1. char texto[TAM_MAX] = {0};
  2. if(pfile) {
  3.    fread(texto, TAM_MAX, 1, pfile);
  4.    puts(texto);
  5.    fclose(pfile);
  6. }


Parte 3... Está es para ti que sino menudo aburrimiento si no puedes probarlo tú mismo  :-X


En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
Locura_23

Desconectado Desconectado

Mensajes: 162



Ver Perfil
Re: Extraer palabras de un texto leido en un archivo (en C)
« Respuesta #2 en: 22 Noviembre 2022, 01:47 am »

Qué crack ! Gracias maestro, la verdad me ayudaste un monton. Continué programando igual el sistema porque con parrafos omitia la basura al parecer, pero era un poco incierto el funcionamiento jaja, pero ahora parece más estable.

Lo de inicializar el arreglo con ceros fue clave, y reescribi el programa con memoria estatica, y de momento no me esta mostrando basura como antes. Lo que sí se me volvio a romper en la parte donde reemplacé sizeof() por strlen() tanto en fwrite() como en fread(), pero voy a ver bien qué puede ser. (Te referias de usar: fwrite(&texto, sizeof(char)* strlen(texto), 1, pfile) ) ?
Lo del fgets() sí voy a reemplazarla en cuanto antes, justamente por este foro me enteré de que gets() no era recomendable jaja.

Lo de la parte 3 supongo que te refieres a la funcion archivoToDic()?
En esa parte también inicialize el arreglo
Código
  1. aux[20] = { 0 };
que este arreglo se utilizaba para guardar una palabra del texto general.
« Última modificación: 22 Noviembre 2022, 17:25 pm por Locura_23 » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Extraer palabras de un texto leido en un archivo (en C)
« Respuesta #3 en: 22 Noviembre 2022, 18:56 pm »


Lo que sí se me volvio a romper en la parte donde reemplacé sizeof() por strlen() tanto en fwrite() como en fread(), pero voy a ver bien qué puede ser. (Te referias de usar: fwrite(&texto, sizeof(char)* strlen(texto), 1, pfile) ) ?
Si te fijas bien en el código, en fread() no utilicé strlen(). Por qué? Porque strlen(texto) = 0 ya que está vacío en ese momento.
Cuando lees del archivo no sabes cuántos bytes tienes que leer por eso se intenta leer el máximo disponible: TAM_MAX.

Por otro lado, no hace falta multiplicar strlen(texto) por sizeof(char). Sí sería la forma correcta pero como un char ocupa 1 byte, sizeof(char) = 1.
Por eso se puede omitir esa multiplicación y hacer el código un poco más sencillo. Si la pones no está mal, estaría bien porque si el tamaño de un char cambiase seguiría funcionando bien.


Lo de la parte 3 supongo que te refieres a la funcion archivoToDic()?
En esa parte también inicialize el arreglo
Código
  1. aux[20] = { 0 };
que este arreglo se utilizaba para guardar una palabra del texto general.
Sí, con la parte 3 me refería a la última función, que intentarás sacarla tú solo aplicando lo visto en las otras funciones.
Si no lo consigues vuelve a dejar la parte que te da problemas con los avances y así poder echarle un ojo  :o
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
extraer el texto de un archivo de word en java
Java
evatking 1 6,249 Último mensaje 10 Diciembre 2009, 23:42 pm
por Leyer
extraer el texto de un archivo de PDF en java
Java
evatking 0 3,230 Último mensaje 11 Diciembre 2009, 01:11 am
por evatking
Como extraer multiples datos de un archivo de texto[AYUDA]
Programación C/C++
Rastreator1010 0 1,862 Último mensaje 16 Octubre 2014, 20:17 pm
por Rastreator1010
Problema con clase Tokenizer (contar palabras de un archivo de texto)
Java
jamatbar 2 2,776 Último mensaje 27 Enero 2016, 09:33 am
por jamatbar
Extraer variable de un archivo de texto (BATCH)
Scripting
rafaeljoseyepez 5 11,736 Último mensaje 15 Diciembre 2020, 00:18 am
por rafaeljoseyepez
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines