Quick Links: |
Provide a macro for checking scanf
-style format strings.
More...
scanf
-style format strings. BSLA_SCANF(FMTIDX, STARTIDX) | validate scanf format and arguments |
BSLA_SCANF_IS_ACTIVE | 0 if BSLA_SCANF expands to nothing and 1 otherwise |
scanf
-style format string, and that the arguments starting at a certain index are to be checked for compatibility with that format string. BSLA_SCANF(FMTIDX, STARTIDX)
This annotation instructs the compiler to perform additional checks on so-annotated functions that take scanf
-style arguments, which should be type-checked against a format string. FMTIDX
parameter is the one-based index to the const
formatSTARTIDX
parameter is the one-based index to the firstextern int my_scanf(void *obj, const char *format, ...) BSLA_SCANF(2, 3);
BSLA_SCANF_IS_ACTIVE
The macro BSLA_SCANF_IS_ACTIVE
is defined to 0 if BSLA_SCANF
expands to nothing and 1 otherwise.int
s and float
s with random numbers in the range [ 0 .. 100 )
. int populateValues(const char *format, ...) BSLA_SCANF(1, 2); // Use 'rand' to populate 'int's and 'float's, passed by pointer after // the specified 'format', which will specify the types of the // variables passed. Return the number of variables populated, or -1 // if the format string is invalid. int populateValues(const char *format, ...) { int ret = 0; va_list ap; va_start(ap, format); for (const char *pc = format; *pc; ++pc) { if ('%' != *pc) { continue; } const char c = *++pc; if ('%' == c) { continue; } else if ('d' == c) { va_arg(ap, int *) = static_cast<unsigned>(rand()) % 100; } else if ('f' == c || 'e' == c || 'g' == c) { const int characteristic = static_cast<unsigned>(rand()) % 100; const int mantissa = static_cast<unsigned>(rand()) % 1000; va_arg(ap, float *) = static_cast<float>(characteristic + mantissa / 1000.0); } else { // Unrecognized character. Return a negative value. ret = -1; break; } ++ret; } va_end(ap); return ret; }
main
, we call populateValues
properly: float ff[3] = { 0, 0, 0 }; int ii[3] = { 0, 0, 0 }; int numVars = populateValues("%d %g %g %d %d %g", &ii[0], &ff[0], &ff[1], &ii[1], &ii[2], &ff[2]); assert(6 == numVars); for (int jj = 0; jj < 3; ++jj) { assert(0 <= ii[jj]); assert(0 <= ff[jj]); assert( ii[jj] < 100); assert( ff[jj] < 100); } printf("%d %g %g %d %d %g\n", ii[0], ff[0], ff[1], ii[1], ii[2], ff[2]);
83 86.777 15.793 35 86 92.649
numVars = populateValues("%d %g", &ff[0], &ii[0]);
.../bsla_scanf.t.cpp:351:43: warning: format specifies type 'int *' but the argument has type 'float *' [-Wformat] numVars = populateValues("%d %g", &ff[0], &ii[0]); ~~ ^~~~~~ %f .../bsla_scanf.t.cpp:351:51: warning: format specifies type 'float *' but the argument has type 'int *' [-Wformat] numVars = populateValues("%d %g", &ff[0], &ii[0]); ~~ ^~~~~~ %d