Foros del Web » Programación para mayores de 30 ;) » C/C++ »

insertar palabra por palabra a una Matriz

Estas en el tema de insertar palabra por palabra a una Matriz en el foro de C/C++ en Foros del Web. Buenas, quería leer desde un archivo y almacenar palabra por palabra en una matriz, por lo que cada uno de los vectores almacenaré una palabra. ...
  #1 (permalink)  
Antiguo 19/10/2012, 20:37
 
Fecha de Ingreso: junio-2009
Mensajes: 84
Antigüedad: 14 años, 9 meses
Puntos: 2
insertar palabra por palabra a una Matriz

Buenas, quería leer desde un archivo y almacenar palabra por palabra en una matriz, por lo que cada uno de los vectores almacenaré una palabra.

He intentado hacerlo, pero sin éxito, en que me estaré confundiendo??

Código C:
Ver original
  1. char** matriz = (char**)malloc(sizeof(char*)*512);
  2.     leer("texto.txt", matriz, 10);

Código C:
Ver original
  1. #include <stdio.h>
  2.  
  3. void leer(char *archivoTexto, char** matriz, int palabras){
  4.  
  5.     FILE* archivo;
  6.     int i = 1;
  7.     char linea [sizeof(matriz)];
  8.    
  9.     if((archivo = fopen(archivoTexto, "r")) == NULL){
  10.         perror("error al abrir el fichero texto.txt\n");
  11.     }
  12.     else{
  13.         while(fgets(linea, sizeof(linea), archivo)){
  14.             matriz[0] = strtok(linea, " ");
  15.             printf("%s ", matriz[0]);
  16.             for( ;(matriz[i] = strtok( NULL, " ")) != NULL && i < palabras; i++){
  17.                 printf("%s ", matriz[i]);
  18.             }
  19.         }
  20.     }
  21. }
PD:
1º argumento: nombre del archivo que quiero leer
2º argumento: la matriz donde quiero insertar las palabras (1 en cada vector)
3º argumento: las cantidad de palabras que quiero insertar a la matriz

Pero justo cuando se imprime las palabras desde la matriz, lo único que me imprime es (null)

Última edición por Gaudy; 19/10/2012 a las 20:51
  #2 (permalink)  
Antiguo 20/10/2012, 07:33
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: insertar palabra por palabra a una Matriz

Suponiendo que funcione tal cual está, como accedes a cada elemento? Sobre un tipo char haciendo matriz[i] te mostrará solo el caracter que haya en la posicion 'i' en vez de la palabra guardada bajo el indice 'i'

De todas formas tienes algun que otro error de interpretacion: p.ej. que tamaño esperas que tendrá la variable 'linea' cuando 'matriz' apunte a un bloque de memoria de 5000 gigas? Tendra solamante 4 bytes porque el sizeof de un puntero es 4 bytes independientemente del bloque de memoria al que esté referenciado ok?

Me parece (puede que haya otra solucion, no se) que deberias usar una lista enlazada, donde los elementos sean estructuras con un puntero a la siguiente estructura y un bloque para la palabra (lo que sería una tipica linked list), seguramente puedes encontrar alguna librería para usar listas, pero por si quieres hacerta la tuya propia aquí de tejo un ejemplo de una solucion a tu problema - que conste que ya se que no debería hacer esto de colgar codigo completo :)

Primero la estructura de datos global accesible desde todas las funciones:

Código:
struct PALABRA {
    char *data;
    struct PALABRA *siguiente;
};
Ahora la funcion leer, que basicamente lo que hace es cargar los datos linea por linea, parsear por espacios y crear dinamicamente los elementos de la lista:

Código:
void leer(char *archivoTexto, struct PALABRA **lista){
    FILE* archivo;
    char *linea, *pch;
    unsigned long int dw;
    struct PALABRA *palabra, *rec;
   
    if((archivo = fopen(archivoTexto, "r")) == NULL){
        perror("error al abrir el fichero texto.txt\n");
    }
    else{
        fseek(archivo, 0L, SEEK_END);
        dw = ftell(archivo);
        fseek(archivo, 0L, SEEK_SET);
        linea = malloc(dw);
        memset(linea, 0, dw);
        
        while(fgets(linea, dw, archivo)){
            pch = strtok (linea," ");
            while(pch) {
                
                palabra = malloc(sizeof(struct PALABRA));
                palabra->siguiente = NULL;
                palabra->data = malloc(strlen(pch)+1);
                memcpy(palabra->data, pch, strlen(pch));
                palabra->data[strlen(pch)] = '\0';
                
                if(!*lista) {
                    *lista = palabra;
                }
                else {
                    rec = *lista;
                    while(rec->siguiente) {
                        rec = rec->siguiente;
                    }
                    rec->siguiente = palabra;
                }
                
                pch = strtok(0, " ");
            }
        }
        free(linea);
    }
}
Cosas importantes: el tamaño de linea es necesariamente el tamaño del archivo por si acaso solo hubiera una sola linea muy larga. La forma de implementar una linked list es estandar: creas un elemento y luego lo guardas en la lista de forma que si la lista es nula, le asignarás el nuevo elemento, si no es nula buscarás el ultimo elemento de la lista y al puntero 'siguiente' le asignaras el nuevo elemento. Ten en cuenta que toda esta memoria tiene que ser liberada al finalizar la aplicacion. Normalmente no se implementa un manipulador de linked list dentro de la funcion, sino que se crean nuevas funciones para ello, mas que nada por lo de la claridad de codigo y todo eso.

Y ahora la llamada desde el main:

Código:
    struct PALABRA *lista_palabras, *rec;
    
    lista_palabras = NULL;
    leer("archivo.txt", &lista_palabras);
    while(lista_palabras) {
        
        printf("%s\n", lista_palabras->data);
        
        rec = lista_palabras->siguiente;
        free(lista_palabras->data);
        free(lista_palabras);
        lista_palabras = rec;
    }
El bucle simplemente muestra los datos cargados y a la vez libera la memoria de la lista; como te he comentado antes lo normal sería crear a parte una funcion para liberar la memoria, pero para el ejemplo esto ya sirve.

Puedes encontrar por ahi mas informacion acerca de las listas enlazadas, aquí solo te he puesto un ejemplo simple.

Saludos
vosk
  #3 (permalink)  
Antiguo 20/10/2012, 09:55
 
Fecha de Ingreso: junio-2009
Mensajes: 84
Antigüedad: 14 años, 9 meses
Puntos: 2
Respuesta: insertar palabra por palabra a una Matriz

Cita:
Iniciado por vosk Ver Mensaje
Suponiendo que funcione tal cual está, como accedes a cada elemento? Sobre un tipo char haciendo matriz[i] te mostrará solo el caracter que haya en la posicion 'i' en vez de la palabra guardada bajo el indice 'i'
Tenía entendido que si especifico matriz [i] hago referencia al vector que almaceno la palabra, en cambio, con matriz [i][j], ahí haría referencia a la letra de alguna palabra, ¿o estoy confundido?

Cita:
Iniciado por vosk Ver Mensaje
De todas formas tienes algun que otro error de interpretacion: p.ej. que tamaño esperas que tendrá la variable 'linea' cuando 'matriz' apunte a un bloque de memoria de 5000 gigas?
Pensaba hacerlo así, puesto que en el peor de los casos, si tuviera en el archivo "texto.txt" un párrafo, lo ingresara todo en el String linea. Esto porque un párrafo no está compuesto por varias lineas, sino por una única linea hasta que llega a un punto aparte, y ahí recién hacen el salto de linea "\n". Por ello mismo le quice ingresar a linea el mismo tamaño de la matriz (como en el peor de los casos), es así como fue que lo pensé.

Cita:
Iniciado por vosk Ver Mensaje
Tendra solamante 4 bytes porque el sizeof de un puntero es 4 bytes independientemente del bloque de memoria al que esté referenciado ok?
Es verdad, matriz es solo un puntero, no me había percatado de lo que hacía, pero y entonces... ¿cómo se especificaría el tamaño de la memoria reservada que apunta matriz?

También recién me enteré de que debía reservar memoria a cada uno de los vectores también, pensaba que con reservar la matriz ya podía escribir los vectores en él.



Con el resto me mataste, me creerías si te dijera que he aprobado todos los ramos hasta Sistema Operativo sin saber estructura de datos? Es lo que más me ha costado entender. Lo estudiaré a ver que onda.

Cualquier otra duda relacionada lo posteo acá, gracias.
  #4 (permalink)  
Antiguo 20/10/2012, 10:17
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: insertar palabra por palabra a una Matriz

"...Tenía entendido que si especifico matriz [i] hago referencia al vector que almaceno la palabra, en cambio, con matriz [i][j], ahí haría referencia a la letra de alguna palabra, ¿o estoy confundido?..."

Si pero no, me explico: en tu codigo tienes una sola llamada a malloc para bloquear sizeof(char*)*512 que son 2048 byes (recuerda que 'char*' es un puntero y como tal ocupa 4 bytes); traducido significa que tienes 2048 punteros de tipo char no referenciados (no tienen asignada ninguna direccion de memoria), o lo que es lo mismo tienes una lista de 2048 elementos de tipo char* sin contenido y sin memoria para guardar nada; para cada uno de ellos deberías llamar otra vez a malloc para asignarle un bloque de memoria que será donde guardarás cada palabra ok?

De esta forma si que se cumpliría el echo de que matriz[i] sea una palabra independiente de 'j' caracteres de longitud y estando 'i' dentro de la condicion 0 <= i < 2048

Saludos
vosk

Etiquetas: int, matriz, palabra
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 06:55.