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

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  [Consulta] Programa para parsear .csv
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [Consulta] Programa para parsear .csv  (Leído 4,922 veces)
astinx

Desconectado Desconectado

Mensajes: 111



Ver Perfil
[Consulta] Programa para parsear .csv
« en: 27 Junio 2012, 07:14 am »

Hola, estoy haciendo un programita que parsea unos templates en base a un .csv y genera unos archivos de texto. Por ejemplo:
Si mi .csv es:
"hola#mundo#alegría"
y mi template es:
"[$1] [$2] hoy estoy lleno de [$3]"
el resultado seria:
"hola mundo hoy estoy lleno de alegría"
Mi problema es como encarar el procesamiento de los tokens. Bien yo podría encarar dos soluciones:

1) Hacerlo con un bucle while ((c=fgetc(archivo))!=EOF) y dentro preguntar si me tope con un '[', luego con un '$', luego con un numero y luego con un ']'. Esto claramente es una chanchada.

2) Otra solución seria leer el contenido del archivo de a trozos almacenandolo en un char* y luego usar alguna de las funciones de la librería string.h para encontrar mi token y reemplazarlo. Esta opción es mas prolija, pero si se diera que elegí leer de a 100 caracteres y en el 99vo carácter esta el carácter '[', y luego al principio del próximo string esta "$3] y ese día blablabla....". No me parsearia correctamente el token, ¡se lo saltearía!.

¿Se les ocurre una solución mejor?

Saludos y gracias por detenerse a leer.


En línea

La programación hoy en día es una carrera entre los ingenieros de software intentando construir mejores y más eficientes programas a prueba de idiotas y el Universo intentando producir mejores y más grandes idiotas. De momento, el Universo está ganando
durasno


Desconectado Desconectado

Mensajes: 373


Ver Perfil
Re: [Consulta] Programa para parsear .csv
« Respuesta #1 en: 27 Junio 2012, 18:58 pm »

Hola! creo q mejores soluciones a las q das vos no hay(o al menos no se me ocurre en este momento)... Lo que podes hacer es usar strstr para saber cuando hay un "[$" en la cadena y strtok para separar en tokens el .csv. Igual creo que el gran problema es generar la cadena final "hola mundo hoy estoy lleno de alegría", ya q por lo que veo vas a necesitar un buen manejo de punteros


Saludos


PD: strtok y strstr ambas funciones de string.h


En línea

Ahorrate una pregunta, lee el man
do-while


Desconectado Desconectado

Mensajes: 1.276


¿Habra que sacarla de paseo?


Ver Perfil
Re: [Consulta] Programa para parsear .csv
« Respuesta #2 en: 28 Junio 2012, 00:07 am »

¡Buenas!

Tienes otra solucion posible. Leer el tamaño del fichero con los parametros, asignar dinamicamente memoria para almacenar los datos y leer el bloque entero del fichero. Haces lo mismo con el fichero en el que va a haber sustituciones, y ya te olvidas de cadenas que pueden estar o no cortadas. Luego como bien te han dicho, con strchr, strstr y strtok te vas apañando.

¡Saludos!
En línea

- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!
BlackZeroX
Wiki

Desconectado Desconectado

Mensajes: 3.158


I'Love...!¡.


Ver Perfil WWW
Re: [Consulta] Programa para parsear .csv
« Respuesta #3 en: 28 Junio 2012, 01:49 am »

Ammm te cree el código ya que no tengo nada que hacer... malditas vacaciones.

crea un archivo llamado "c:\a.txt" y dentro escribe las palabras separadas con espacios...

Código
  1.  
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6.  
  7. #define PARSETHIS "[$2] [$2] [$3] [$4] [$300] [$030]"
  8.  
  9. typedef struct acumstrings
  10. {
  11.    char **ptr;
  12.    size_t count;
  13. } acumstrings;
  14.  
  15. acumstrings acum;
  16.  
  17. inline const char* getTokenIndex(const char *str, long *Index)
  18. {
  19.    if (!str) return NULL;
  20.    char *ptr = strstr(str, "[$");
  21.    char *end = NULL;
  22.  
  23.    if (ptr) {
  24.        ptr += strlen("[$");
  25.        (*Index) = strtol(ptr, &end, 10);
  26.    }
  27.  
  28.    return ptr;
  29. }
  30.  
  31. inline char* replace(const char *str, const char *find, const char *rep)
  32. {
  33.    char *ret = NULL;
  34.    size_t strOln;
  35.    size_t strFln;
  36.    size_t strRln;
  37.    const char *end[2];
  38.    size_t sizeL;
  39.    size_t sizeR;
  40.  
  41.  
  42.    if (!str) return NULL;
  43.  
  44.    strOln = strlen(str);
  45.  
  46.    if (!find || (end[0] = strstr(str, find)) == NULL) {
  47.        ret = (char*)malloc(strOln + 1);
  48.        memcpy(ret, str, strOln + 1);
  49.        return ret;
  50.    }
  51.  
  52.    strRln = strlen(rep);
  53.    strFln = strlen(find);
  54.  
  55.    end[1] = (char*)((size_t)end[0] + strFln);
  56.  
  57.    sizeL = (size_t)end[0] - (size_t)str;
  58.    sizeR = ((size_t)str + strOln) - (size_t)end[1];
  59.  
  60.    ret = (char*)malloc(sizeL + strRln + sizeR + 1);
  61.  
  62.    memcpy(ret, str, sizeL);
  63.    memcpy((void*)((int)ret + sizeL), rep, strRln);
  64.    memcpy((void*)((int)ret + sizeL + strRln), end[1], sizeR);
  65.  
  66.    ret[sizeL + strRln + sizeR] = '\0';
  67.  
  68.    return ret;
  69. }
  70.  
  71. int main ()
  72. {
  73.    FILE* file;
  74.    size_t ret;
  75.    char* strLast = NULL;
  76.    char* strNew = NULL;
  77.    char* strNewFind = NULL;
  78.    char strToken[20];
  79.    long index;
  80.  
  81.    file = fopen("C:\\a.txt", "rb+");
  82.  
  83.    //  Obtenemos cada palabra.
  84.    while (!feof(file))
  85.    {
  86.        acum.ptr = (char**)realloc(acum.ptr, (acum.count + 1) * sizeof(char**));
  87.        acum.ptr[acum.count] = (char*)calloc(256, 1);
  88.        ret = fscanf(file, "%s", acum.ptr[acum.count]);
  89.        puts(acum.ptr[acum.count]);
  90.        ++acum.count;
  91.    }
  92.  
  93.    fclose(file);
  94.  
  95.    strNew = (char*)malloc(strlen(PARSETHIS) + 1);
  96.    strcpy(strNew, PARSETHIS);
  97.    strNewFind = strNew;
  98.  
  99.    //  reemplazamos cada token por cada una de las palabras respectivas.
  100.    while(strNewFind = getTokenIndex(strNewFind, &index))
  101.    {
  102.        sprintf(strToken, "[%$%d]\0", index);
  103.        if (acum.count > index) {
  104.            strLast = strNew;
  105.            strNew = replace(strLast, strToken, acum.ptr[index - 1]);
  106.            free(strLast);
  107.            strNewFind = strNew;
  108.        } else {
  109.            ++strNewFind;
  110.        }
  111.    }
  112.  
  113.    while(acum.count--)
  114.        free(acum.ptr[acum.count]);
  115.    free(acum.ptr);
  116.  
  117.    puts(strNew);
  118.  
  119.    free(strNew);
  120.  
  121.    getchar();
  122.  
  123.    return 0;
  124. }
  125.  
  126.  

Dulces Lunas!¡.
« Última modificación: 28 Junio 2012, 02:08 am por BlackZeroX (Astaroth) » En línea

The Dark Shadow is my passion.
astinx

Desconectado Desconectado

Mensajes: 111



Ver Perfil
Re: [Consulta] Programa para parsear .csv
« Respuesta #4 en: 28 Junio 2012, 07:48 am »

Buenisimo, muchas gracias Black, tu solución me sirvió bastante para darme una idea.
Saludos!
En línea

La programación hoy en día es una carrera entre los ingenieros de software intentando construir mejores y más eficientes programas a prueba de idiotas y el Universo intentando producir mejores y más grandes idiotas. De momento, el Universo está ganando
Foxy Rider


Desconectado Desconectado

Mensajes: 2.407


Deprecated


Ver Perfil WWW
Re: [Consulta] Programa para parsear .csv
« Respuesta #5 en: 28 Junio 2012, 09:14 am »

Ejem ... no era más fácil leer línea a línea (no se agarren la *mala* costumbre de leer todo de un saque), pasar todo por strtok() y tomar los 3 valores y encajarlos en un printf como el ejercicio lo pide?

Saludos.
« Última modificación: 28 Junio 2012, 09:19 am por vertexSymphony » En línea

durasno


Desconectado Desconectado

Mensajes: 373


Ver Perfil
Re: [Consulta] Programa para parsear .csv
« Respuesta #6 en: 29 Junio 2012, 02:43 am »

Hola! una pregunta BlackZeroX (Astaroth) ¿el codigo q hiciste es en C no?? si es asi podrias explicarme cual es la funcion de inline?? que no lo conocia


Saludos
En línea

Ahorrate una pregunta, lee el man
astinx

Desconectado Desconectado

Mensajes: 111



Ver Perfil
Re: [Consulta] Programa para parsear .csv
« Respuesta #7 en: 3 Julio 2012, 10:42 am »

Ejem ... no era más fácil leer línea a línea (no se agarren la *mala* costumbre de leer todo de un saque), pasar todo por strtok() y tomar los 3 valores y encajarlos en un printf como el ejercicio lo pide?

Saludos.

Gracias por ilustrarme vertex, heló aquí el código.

Código
  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5.  
  6. int main()
  7. {
  8. char * tokens[] = {"cosas","hacerlas"};
  9.    char s1[] = "Las [$0] hay que [$1] en el momento que hay que [$1].\n";
  10.    char s2[] = "[$";
  11.    char *ptr;
  12.    ptr = strtok( s1, s2 );    // Primera llamada => Primer token
  13.    if ( (isdigit(ptr[0])) && (ptr[1] == ']') ) {
  14. //Es un token
  15. printf("%s%s", tokens[atoi(ptr)], ptr+2);
  16. } else {
  17. printf("%s",ptr);
  18.    }
  19.    while( (ptr = strtok( NULL, s2 )) != NULL )    // Posteriores llamadas
  20. if ( (isdigit(ptr[0])) && (ptr[1] == ']') ) {
  21. //Es un token
  22. printf("%s%s", tokens[atoi(ptr)], ptr+2);
  23. } else {
  24. printf("%s",ptr);
  25. }
  26.    return 0;
  27. }

Saludos
En línea

La programación hoy en día es una carrera entre los ingenieros de software intentando construir mejores y más eficientes programas a prueba de idiotas y el Universo intentando producir mejores y más grandes idiotas. De momento, el Universo está ganando
BlackZeroX
Wiki

Desconectado Desconectado

Mensajes: 3.158


I'Love...!¡.


Ver Perfil WWW
Re: [Consulta] Programa para parsear .csv
« Respuesta #8 en: 3 Julio 2012, 12:11 pm »

En mi parecer, al ser un forma de ver el formato de manera uniforme y repetitiva (no compuesto/compleja) donde cada palabra (no  consideran frases) esta solo separada por un signo (en mi caso no era # si no mas bien el espacio o salto de linea '\n' o cualquier carácter que tenga el mismo uso) funciona bastante bien fscanf(file, "%s", ...),se cargan todas la palabras en un "Buffer" para no estar re-leyendo a cada instante el archivo y evitar la latencia de acceso al disco duro por ello yo descarte el uso de strtok() y de lectura de lineas las cuales desconozco su longitud.

* Cuando es un formato del este estilo (palabra1 palabra2 palabra3 palabra4 ... palabraN-esima) y no hay formatos complejos fscanf(file, "%s", ...) va perfecto siempre y cuando haya un separador de palabra, de lo contrario es mas recomendable cargar el archivo en memoria y proseguir a identificar cada palabra/signo clave.

por ejemplo ( Yo cargaría en memoria el archivo si estuviera en el disco y aplicar un analizador sintáctico y enviar todo el archivo a estructuras obviamente ya analizado, a su vez también evitar la mayor cantidad de ciclos incluyendo strtok() ya que en este tipo de cuestiones se pueden omitir o tener palabras/signos opcionales y strtok() sacrificaría demasiado el redimiendo de un algoritmo ademas que ignoraria palabras entre el punto inicial y el punto final, es decir funcionaria solo para identificar la existencia en este caso ):

Código:

// este es un comentario

cadena1{ // Note que no hay espacio entre la palabra y {
    casena(propiedad1 = "algo") { // Note que la palabra tiene propiedades; Note que hay un espacio antes del {
         item1 = ""
    }
}


* strtok() esta bien para hacer por ejemplo una función que extraiga un trozo de texto o similares pero para analizar formatos() puede que si y puede que no, en mi criterio es dar muchos vueltas (en formatos complejos) en simples como este no hay bronca pero lo mejor es leer el archivo y meterlo en estructuras que representen al archivo original y así evitar la latencia de acceso al disco duro.

NOTA: la caga en memoria seria por bloques mas no todo de golpe.

Dulces Lunas!¡.
« Última modificación: 3 Julio 2012, 12:33 pm por BlackZeroX (Astaroth) » En línea

The Dark Shadow is my passion.
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Parsear html, ¿algo sencillo?
Java
Ragnarok 3 9,418 Último mensaje 5 Junio 2007, 18:20 pm
por alvk4r
Parsear con PHP Simple HTML DOM
PHP
multi-media asdfg 5 6,462 Último mensaje 16 Julio 2011, 01:20 am
por multi-media asdfg
Parsear HTML ayuda !!!
.NET (C#, VB.NET, ASP)
TrashAmbishion 4 3,091 Último mensaje 8 Julio 2012, 18:50 pm
por TrashAmbishion
consulta para programa de contabilizar
Programación Visual Basic
POLLITOXD 0 1,584 Último mensaje 4 Noviembre 2013, 21:22 pm
por POLLITOXD
Ayuda para parsear este formato...
Ingeniería Inversa
Eleкtro 4 5,964 Último mensaje 31 Diciembre 2016, 17:00 pm
por ivancea96
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines