正如所指出的,一个有效的方法来确定的所需的空间量是使至snprintf
的初始呼叫指定为NULL
str
& size
和0
,分别迫使snprintf
返回,将已经被写入了的字符数str
& size
为写入提供了足够的空间。然后您可以使用snprintf + 1
返回的字符数来动态分配足以容纳转换为字符串的结构内容的缓冲区。对于这个例子来说,输出格式仅仅是一个逗号分隔的字符串结构值(通常避免在C中的变量/结构名称的前导大写,无效,只是传统风格)。
以下是解决此问题的一种方法。如果成功,struct2str
函数将返回一个动态分配的包含airport struct内容的字符串,否则返回NULL
。如果要转换airport
条目的数组,则可以轻松地传递数组中的元素数,并修改该函数以返回指向字符串的指针数组。让我知道如果您有任何疑问:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *gpsId;
char *type;
char *name;
double latitude;
double longitude;
int elevationFeet;
char *city;
char *countryAbbrv;
} airport;
char *struct2str (airport ap);
int main (void) {
/* declare structure and initialize values */
airport a = { "GPS100151", "GPS/ILS/RVR/AWOS", "A.L. Mangham Regional", 31.58, 94.72, 354, "Nacogdoches", "US" };
/* convert struct a to string (no name conflict with struct) */
char *airport = struct2str (a);
printf ("\n airport as a string:\n\n '%s'\n\n", airport);
/* free dynamically allocated memory */
if (airport) free (airport);
return 0;
}
/* convert contents of airport structure to a comma
separated string of values. Returns pointer to
dynamically allocated string containing contents
of airport structure on success, otherwise NULL.
*/
char *struct2str (airport ap)
{
/* get lenght of string required to hold struct values */
size_t len = 0;
len = snprintf (NULL, len, "%s,%s,%s,%lf,%lf,%d,%s,%s", ap.gpsId, ap.type, ap.name, ap.latitude,
ap.longitude, ap.elevationFeet, ap.city, ap.countryAbbrv);
/* allocate/validate string to hold all values (+1 to null-terminate) */
char *apstr = calloc (1, sizeof *apstr * len + 1);
if (!apstr) {
fprintf (stderr, "%s() error: virtual memory allocation failed.\n", __func__);
}
/* write/validate struct values to apstr */
if (snprintf (apstr, len + 1, "%s,%s,%s,%lf,%lf,%d,%s,%s", ap.gpsId, ap.type, ap.name, ap.latitude,
ap.longitude, ap.elevationFeet, ap.city, ap.countryAbbrv) > len + 1)
{
fprintf (stderr, "%s() error: snprintf returned truncated result.\n", __func__);
return NULL;
}
return apstr;
}
输出
$ ./bin/struct_to_str
airport as a string:
'GPS100151,GPS/ILS/RVR/AWOS,A.L. Mangham Regional,31.580000,94.720000,354,Nacogdoches,US'
'的snprintf()'将返回会如果传入的大小是无限的已打印的字符数。你可以在任何缓冲区上调用它以获得正确的大小来动态分配你的字符串,然后再用你动态分配的缓冲区再次调用它来实际写入它。没有必要说“我知道'sprintf'和所有这些方法” - 如果你知道它们,那么使用它们,它们是正确的方法。 –
我认为我脑子里有什么问题,sprintf会不会真的打印我合并的字符串是正确的?它会将参数放入第一个参数中,然后我需要打印是的?例如,如果我有: sprintf(str,“Test%f”,M_PI); 它会把测试3.14 .....进入str但不打印是吗? – AndyPet74
是的,这是正确的,'sprintf'和'snprintf'的输出会进入您作为第一个参数传递的缓冲区。 – user3386109