Convertir un token de preprocesador a una cadena
-
04-07-2019 - |
Pregunta
Estoy buscando una manera de convertir un token de preprocesador a una cadena.
Específicamente, en algún lugar tengo:
#define MAX_LEN 16
y quiero usarlo para evitar la saturación del búfer:
char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);
Estoy abierto a otras formas de lograr lo mismo, pero solo a la biblioteca estándar.
Solución
vea http://www.decompile.com/cpp/faq/file_and_line_error_string.htm específicamente:
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)
para que su problema se pueda resolver haciendo
sscanf (buf, "% " TOSTRING (MAX_LEN) " ;, val);
Otros consejos
Encontré una respuesta en línea.
#define VERSION_MAJOR 4 #define VERSION_MINOR 47 #define VERSION_STRING "v" #VERSION_MAJOR "." #VERSION_MINOR
Lo anterior no funciona pero es de esperar ilustra lo que me gustaría hacer, es decir, hacer que VERSION_STRING termine como " v4.47 " ;.
Para generar la forma numérica adecuada usa algo como
#define VERSION_MAJOR 4 #define VERSION_MINOR 47 #define STRINGIZE2(s) #s #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_STRING "v" STRINGIZE(VERSION_MAJOR) \ "." STRINGIZE(VERSION_MINOR) #include <stdio.h> int main() { printf ("%s\n", VERSION_STRING); return 0; }
Ha pasado un tiempo, pero esto debería funcionar:
sscanf(buf, "%" #MAX_LEN "s", val);
Si no, necesitará " expansión doble " truco:
#define STR1(x) #x
#define STR(x) STR1(x)
sscanf(buf, "%" STR(MAX_LEN) "s", val);
Debes usar el truco de macro de stringificación de doble expansión. O simplemente tener un
#define MAX_LEN 16
#define MAX_LEN_S "16"
char val[MAX_LEN+1];
sscanf(buf, "%"MAX_LEN_S"s", val);
y mantenlo sincronizado. (Eso es un poco molesto, pero mientras las definiciones estén una al lado de la otra, probablemente lo recuerden).
En realidad, en este caso particular, ¿no sería suficiente strncpy
?
strncpy(val, buf, MAX_LEN);
val[MAX_LEN] = '\0';
Sin embargo, si fuera printf
, esto sería más fácil:
sprintf(buf, "%.*s", MAX_LEN, val);
Mientras que algunos de los " trabajo " ;, " ;, personalmente, recomiendo simplemente usar una cadena de API simple en lugar de la dreck que viene en libc. Existen varias API portátiles, algunas de las cuales también están optimizadas para facilitar su inclusión en su proyecto ... y otras como ustr tiene una sobrecarga de espacio y soporte para las variables de pila.