| 
	
		|  Autor | Tema: [Consulta] Programa para parsear .csv  (Leído 5,512 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,607 |  5 Junio 2007, 18:20 pm por alvk4r
 |  
						|   |   | Parsear con PHP Simple HTML DOM PHP
 | multi-media asdfg | 5 | 6,732 |  16 Julio 2011, 01:20 am por multi-media asdfg
 |  
						|   |   | Parsear HTML ayuda !!! .NET (C#, VB.NET, ASP)
 | TrashAmbishion | 4 | 3,442 |  8 Julio 2012, 18:50 pm por TrashAmbishion
 |  
						|   |   | consulta para programa de contabilizar Programación Visual Basic
 | POLLITOXD | 0 | 1,749 |  4 Noviembre 2013, 21:22 pm por POLLITOXD
 |  
						|   |   | Ayuda para parsear este formato... Ingeniería Inversa
 | Eleкtro | 4 | 6,330 |  31 Diciembre 2016, 17:00 pm por ivancea96
 |    |