/* * Proyecto que implementa las funciones sprintf u sscanf * Se emplean funciones con un número de parámetros variables. * Se emplea un puntero genérico (void *) para recorrer la * pila del proceso. * * Programa: main.cpp * Autor: Miguel Guanira E. * * Created on 28 de junio de 2010, 08:54 AM */ #include #include #include #include "mi_sprintf.h" #include "mi_sscanf.h" int main(void) { // ******************************************************************** // Código para probar la función: mi_sprintf // ******************************************************************** int edad = 45, categoria = 347; char *nombre; float sueldo = 7643.25; char clave = 'L'; char *cadena; nombre = strdup("Juan Lopez"); cadena = new char[100]; // La variable cadena debe apuntar a un espacio válido donde // almacenar el texto que le asignará la función. mi_sprintf(cadena, "Codigo: %c%d Nombre: %s Sueldo: %f Edad: %d\n", clave, categoria, nombre, sueldo, edad); // Luego de ejecutar esta función, los valores de las variables pasan // a la variable cadena, como un texto. printf("%s\n", cadena); // ******************************************************* // // Código para probar la función: mi_sscanff // // ******************************************************* int codigo; char nomb[20], *apell, nomb2; float sueld; // Todas las variables que intervienen deben tener un // espacio válido donde almacenar valores antes de // ejecutar la función, por eso debemos hacer lo siguiente: apell = new char[20]; mi_sscanf("478325 Ana C Roncal 4795.25", "%d %s %c %s %f", &codigo, nomb, &nomb2, apell, &sueld); // Al ejecutar esta función, los datos de la cadena inicial se // separan, se convierten según la cadena de formato y se // asignan a las vcariables. printf("Codigo: %d\nNombre: %s %c %s\nSueldo: %f\n", codigo, nomb, nomb2, apell, sueld); return (EXIT_SUCCESS); } // *************************************************************** // // Módulo: mi_sprintf.h // // *************************************************************** #ifndef _MI_SPRINTF_H #define _MI_SPRINTF_H void mi_sprintf(char *, char *, ...); #endif /* _MI_SPRINTF_H */ // *************************************************************** // // Módulo: mi_sprintf.cpp // // *************************************************************** #include #include #include void mi_sprintf(char *cadena, char *formato, ...){ void *ptrPila; char *ptrForm=formato, *ptrCad=cadena; // Apuntamos a la pila del proceso mediante el último argumento fijo ptrPila = &formato; // Nos desplazamos al primer argumento variable // (ver explicación adelante){1} ptrPila = ((char **)ptrPila) + 1; // Analizamos los caracteres de la cadena de formato while (*ptrForm){ if (*ptrForm != '%'){ // Pasamos todos los caracteres que no son // de formato al espacio asignado a la variable cadena *ptrCad = *ptrForm; ptrForm++; ptrCad++; //Avanzamos al siguiente caracter } else{ // procesamos los caracteres de formato // (ver explicación adelante){2} ptrForm++; switch(*ptrForm){ case 'd': // Tomamos el valor entero de lal pila int varInt = *(int *)ptrPila; // Nos movemos al siguiente parámetro variable ptrPila = ((int*)ptrPila) + 1; // Convertimos el valor entero en cadena // y lo colocamos en la cadena final itoa(varInt, ptrCad, 10); ptrCad += strlen(ptrCad); // Movemos el puntero para seguir colocando datos allí break; case 'f': // Tomamos el valor de punto flotante de lal pila float varFloat = *(double *)ptrPila; char *strFloat; int posDec, signo; // Nos movemos al siguiente parámetro variable // En este caso nos moveos el espacio de un double ptrPila = ((double*)ptrPila) + 1; // Convertimos el valor de punto flotante en cadena // y lo colocamos en la cadena final strFloat = fcvt(varFloat,30, &posDec,&signo); // En strFloat se coloca una cadena con todas las // cifras del número, sin punto decimal ni signo if(signo){ // si signo = 0 ==> es positivo *ptrCad = '-'; ptrCad++; } // Copiamos la parte entera strncpy(ptrCad, strFloat, posDec); ptrCad[posDec] = 0; ptrCad += strlen(ptrCad); // Colocamos el punto *ptrCad = '.'; ptrCad++; // Copiamos la parte decimal (6 decimales siempre) strncpy(ptrCad, &strFloat[posDec],6); ptrCad[6] = 0; ptrCad += strlen(ptrCad); break; case 's': // Apuntamos a la cadena con el dato char *varStr = *(char **)ptrPila; // Nos movemos al siguiente parámetro variable ptrPila = ((char **)ptrPila) + 1; // Copiamos la cadena dato y la colocamos // en la cadena final strcpy(ptrCad, varStr); // Movemos el puntero de la cadena final para // seguir colocando datos allí ptrCad += strlen(ptrCad); break; case 'c': // Tomamos el caracter de lal pila int varChar = *(char *)ptrPila; // Nos movemos al siguiente parámetro variable // En este caso nos moveos el espacio de un int ptrPila = ((int*)ptrPila) + 1; // Colocamos el caracter en la cadena final // y a continuación el caractter nulo *ptrCad = varChar; ptrCad ++; *ptrCad=0; break; } ptrForm++; } } *ptrCad=0; } // *************************************************************** // // Módulo: mi_sscanf.h // // *************************************************************** #ifndef _MI_SSCANF_H #define _MI_SSCANF_H void mi_sscanf(char *, char *, ...); #endif /* _MI_SSCANF_H */ // *************************************************************** // // Módulo: mi_sscanf.cpp // // *************************************************************** #include #include #include enum Blancos {BLANCO=' ', TAB='\t', EOLN=' '}; void mi_sscanf(char *cadena, char *formato, ...){ void *ptrPila; char *ptrForm=formato, *ptrCad=cadena, cadAux[100], *ptrCadAux; // Apuntamos a la pila del proceso mediante el último argumento fijo ptrPila = &formato; // Nos desplazamos al primer argumento variable (ver *) // (ver explicación adelante){3} ptrPila = ((char **)ptrPila) + 1; while (*ptrForm){ // Saltamos todos los caracteres hasta encontrar uno de formato while (*ptrForm!=0 && *ptrForm != '%')ptrForm++; if (*ptrForm == 0) return; ptrForm++; // avanzamos al siguiente caracter // Buscamos el inicio de la siguiente palabra en la cadena dato while(*ptrCad == BLANCO || *ptrCad == TAB || *ptrCad == EOLN) *ptrCad++; if (*ptrCad==0) return; // Pasamos los caracteres de la palabra a una cadena auxiliar ptrCadAux = cadAux; while(*ptrCad != BLANCO && *ptrCad != TAB && *ptrCad != EOLN && *ptrCad !=0){ *ptrCadAux = *ptrCad; ptrCad++; ptrCadAux++; } *ptrCadAux = 0; // Ponemos el caracter de terminación en la cadena // Analizamos los caracteres de la cadena de formato switch(*ptrForm){ case 'd': int varInt, *posMemInt; // Convertimos la cadena en un entero varInt = atoi(cadAux); // Apuntamos a la dirección dada por el argumento variable posMemInt = *(int**)ptrPila; // Guardamos el entero en la posición de memoria dada // por el argumento *posMemInt = varInt; // Avanzamos el puntero al otro argumento ptrPila = ((int**)ptrPila) + 1; break; case 'f': float varFloat, *posMemFloat; // Convertimos la cadena en un entero varFloat = atof(cadAux);; // Apuntamos a la dirección dada por el argumento variable posMemFloat = *(float**)ptrPila; // Guardamos el entero en la posición de memoria dada // por el argumento *posMemFloat = varFloat; // Avanzamos el puntero al otro argumento ptrPila = ((float**)ptrPila) + 1; break; case 's': char *varStr = *(char **)ptrPila; // Guardamos la cadena en la posición de memoria dada // por el argumento strcpy(varStr, cadAux); // Avanzamos el puntero al otro argumento ptrPila = ((char **)ptrPila) + 1; break; case 'c': char *varChar = *(char **)ptrPila; // Guardamos el caracter en la posición de memoria dada // por el argumento *varChar = *cadAux; // Avanzamos el puntero al otro argumento ptrPila = ((char **)ptrPila) + 1; break; } } }