Autor
|
Tema: [Consulta] Programa para parsear .csv (Leído 4,883 veces)
|
astinx
Desconectado
Mensajes: 111
|
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
Mensajes: 373
|
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
Mensajes: 1.276
¿Habra que sacarla de paseo?
|
¡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
Mensajes: 3.158
I'Love...!¡.
|
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... #include <stdio.h> #include <stdlib.h> #include <string.h> #define PARSETHIS "[$2] [$2] [$3] [$4] [$300] [$030]" typedef struct acumstrings { char **ptr; size_t count; } acumstrings; acumstrings acum; inline const char* getTokenIndex(const char *str, long *Index) { if (!str) return NULL; char *ptr = strstr(str , "[$"); char *end = NULL; if (ptr) { (*Index ) = strtol(ptr , &end , 10); } return ptr; } inline char* replace(const char *str, const char *find, const char *rep) { char *ret = NULL; size_t strOln; size_t strFln; size_t strRln; const char *end[2]; size_t sizeL; size_t sizeR; if (!str) return NULL; if (!find || (end [0] = strstr(str , find )) == NULL ) { ret = (char*)malloc(strOln + 1); return ret; } end[1] = (char*)((size_t)end[0] + strFln); sizeL = (size_t)end[0] - (size_t)str; sizeR = ((size_t)str + strOln) - (size_t)end[1]; ret = (char*)malloc(sizeL + strRln + sizeR + 1); memcpy((void*)((int)ret + sizeL ), rep , strRln ); memcpy((void*)((int)ret + sizeL + strRln ), end [1], sizeR ); ret[sizeL + strRln + sizeR] = '\0'; return ret; } int main () { FILE* file; size_t ret; char* strLast = NULL; char* strNew = NULL; char* strNewFind = NULL; char strToken[20]; long index; file = fopen("C:\\a.txt", "rb+"); // Obtenemos cada palabra. { acum. ptr = (char**)realloc(acum. ptr, (acum. count + 1) * sizeof(char**)); acum. ptr[acum. count] = (char*)calloc(256, 1); ret = fscanf(file , "%s", acum. ptr[acum. count]); puts(acum. ptr[acum. count]); ++acum.count; } strNewFind = strNew; // reemplazamos cada token por cada una de las palabras respectivas. while(strNewFind = getTokenIndex(strNewFind, &index)) { sprintf(strToken , "[%$%d]\0", index ); if (acum.count > index) { strLast = strNew; strNew = replace(strLast, strToken, acum.ptr[index - 1]); strNewFind = strNew; } else { ++strNewFind; } } while(acum.count--) free(acum. ptr[acum. count]); return 0; }
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
Mensajes: 111
|
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
Mensajes: 2.407
Deprecated
|
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
Mensajes: 373
|
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
Mensajes: 111
|
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. #include <string.h> #include <stdio.h> #include <ctype.h> #include <stdlib.h> int main() { char * tokens[] = {"cosas","hacerlas"}; char s1[] = "Las [$0] hay que [$1] en el momento que hay que [$1].\n"; char s2[] = "[$"; char *ptr; ptr = strtok( s1 , s2 ); // Primera llamada => Primer token if ( (isdigit(ptr [0])) && (ptr [1] == ']') ) { //Es un token } else { } while( (ptr = strtok( NULL , s2 )) != NULL ) // Posteriores llamadas if ( (isdigit(ptr [0])) && (ptr [1] == ']') ) { //Es un token } else { } return 0; }
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
Mensajes: 3.158
I'Love...!¡.
|
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 ): // 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.
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Parsear html, ¿algo sencillo?
Java
|
Ragnarok
|
3
|
9,402
|
5 Junio 2007, 18:20 pm
por alvk4r
|
|
|
Parsear con PHP Simple HTML DOM
PHP
|
multi-media asdfg
|
5
|
6,413
|
16 Julio 2011, 01:20 am
por multi-media asdfg
|
|
|
Parsear HTML ayuda !!!
.NET (C#, VB.NET, ASP)
|
TrashAmbishion
|
4
|
3,075
|
8 Julio 2012, 18:50 pm
por TrashAmbishion
|
|
|
consulta para programa de contabilizar
Programación Visual Basic
|
POLLITOXD
|
0
|
1,573
|
4 Noviembre 2013, 21:22 pm
por POLLITOXD
|
|
|
Ayuda para parsear este formato...
Ingeniería Inversa
|
Eleкtro
|
4
|
5,928
|
31 Diciembre 2016, 17:00 pm
por ivancea96
|
|