Reputation: 1401
I've found several questions on this but none of them have helped me get this working. I have the following.
struct general_calibration_t {
double pressure_span;
double pressure_offset;
double steam_temperature_offset;
};
struct general_t {
struct general_calibration_t calibration;
};
int generateGenericJSON(string* str, const char* json, ...) {
char* tmp = (char*)malloc(2048);
if (tmp == NULL)
goto fail;
va_list ap;
va_start(ap, json);
const int amount = snprintf(tmp, 2048, json, ap);
va_end(ap);
if (amount >= 2048 || amount < 0)
goto release;
string_new_value(str, tmp, amount);
free(tmp);
return 0;
release:
free(tmp);
fail:
return 1;
}
Which is called with the following:
struct general_t data;
data.calibration.pressure_offset = 1.0;
data.calibration.pressure_span = 34.8;
data.calibration.steam_temperature_offset = 20.0;
string calibrationStr;
generateGenericJSON(&calibrationStr,
"\"Calibration\":{\"PressureSpan\":%.3f,\"PressureOffset\":%.3f,\"SteamTemperatureOffset\":%.3f}",
data.calibration.pressure_span,
data.calibration.pressure_offset,
data.calibration.steam_temperature_offset);
My output is the following:
"Calibration":{"PressureSpan":0.000,"PressureOffset":0.000,"SteamTemperatureOffset":-92559631349317830736831783200707727132248687965119994463780864.000}
Something appears wrong while passing the va_list
to snprintf
. If I use va_arg
to walk through the list in the function generateGenericJSON
the data is correct. I tried passing the va_list
as a pointer but I get the same invalid data.
What am I doing wrong in passing this va_list
to snprintf
?
Upvotes: 1
Views: 204
Reputation: 70981
What am I doing wrong in passing this va_list to snprintf?
You want to use vsnprintf()
instead of snprintf()
.
Following up dash-o's comment: Try to avoid (the possibility of) spagetti-code.
A possible way to handle the different cases of success/failure could be:
int generateGenericJSON(string* str, const char* json, ...) {
int result = 0; /* Be optimistic. */
do { /* One time "loop" */
char* tmp = malloc(2048); /* No need to cast malloc() and friends in C. */
if (tmp == NULL) {
result = -1; /* By convention -1 indicates failure. */
break;
}
va_list ap;
va_start(ap, json);
const int amount = vsnprintf(tmp, 2048, json, ap);
va_end(ap);
if (amount >= 2048 || amount < 0) {
result = -1;
break;
}
string_new_value(str, tmp, amount);
} while (0);
free(tmp); /* Passing NULL to free is fine. */
return result;
}
Upvotes: 3