/* * Proyecto que implementa las funciones sprintf u sscanf * Se emplean funciones con un número de parámetros variables. * Se emplea la biblioteca de funciones STDARG.H * * * Archivo: main.cpp * Autor : J. Miguel Guanira E. * * Created on 10 de noviembre de 2010 */ #include #include #include #include "mi_sprintf.h" #include "mi_sscanf.h" int main(void) { // ******************************************************************** // Código para probar la función: mi_sprintf usando stdarg.h // ******************************************************************** 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 usando stdarg.h // ******************************************************************** 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 #include void mi_sprintf(char *cadena, char *formato, ...){ va_list pArg; //Variable que recorre la pila del sistema char *ptrForm=formato, *ptrCad=cadena; // Apuntamos a la pila del proceso mediante el último argumento fijo va_start(pArg, formato); // 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 = va_arg(pArg, int); // Convertimos el valor entero en cadena // y lo colocamos en la cadena final itoa(varInt, ptrCad, 10); // Movemos el puntero para seguir colocando datos allí ptrCad += strlen(ptrCad); break; case 'f': // Tomamos el valor de punto flotante de lal pila float varFloat = va_arg(pArg, double); char *strFloat; int posDec, signo; // 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; // Movemos el puntero para seguir colocando datos allí ptrCad += strlen(ptrCad); break; case 's': // Apuntamos a la cadena con el dato char *varStr = va_arg(pArg, char*); // Copiamos la cadena dato y la colocamos // en la cadena final strcpy(ptrCad, varStr); // Movemos el puntero para seguir colocando datos allí ptrCad += strlen(ptrCad); break; case 'c': // Tomamos el caracter de lal pila char varChar = va_arg(pArg, int); // 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 #include enum Blancos {BLANCO=' ', TAB='\t', EOLN=' '}; void mi_sscanf(char *cadena, char *formato, ...){ va_list pArg; //Variable que recorre la pila del sistema char *ptrForm=formato, *ptrCad=cadena, cadAux[100], *ptrCadAux; // Apuntamos a la pila del proceso mediante el último argumento fijo va_start(pArg, formato); 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 = va_arg(pArg, int*); // Guardamos el entero en la posición de memoria dada // por el argumento *posMemInt = varInt; 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 = va_arg(pArg, float*); // Guardamos el entero en la posición de memoria dada // por el argumento *posMemFloat = varFloat; break; case 's': // Apuntamos a la dirección dada por el argumento variable char *varStr = va_arg(pArg, char*); // Guardamos la cadena en la posición de memoria dada // por el argumento strcpy(varStr, cadAux); break; case 'c': // Apuntamos a la dirección dada por el argumento variable char *varChar = va_arg(pArg, char*); // Guardamos el caracter en la posición de memoria dada // por el argumento *varChar = *cadAux; break; } } }