C结构到字符串

C结构到字符串,c,structure,C,Structure,所以我有一个结构,看起来像这样: typedef struct { char *gpsId; char *type; char *name; double latitude; double longitude; int elevationFeet; char *city; char *countryAbbrv; } Airport; char * airportToString(const Airport *a); 我还有一个函数,该函数的原型如下所示: typedef struct { c

所以我有一个结构,看起来像这样:

typedef struct {
char *gpsId;
char *type;
char *name;
double latitude;
double longitude;
int elevationFeet;
char *city;
char *countryAbbrv;
} Airport;
char * airportToString(const Airport *a);
我还有一个函数,该函数的原型如下所示:

typedef struct {
char *gpsId;
char *type;
char *name;
double latitude;
double longitude;
int elevationFeet;
char *city;
char *countryAbbrv;
} Airport;
char * airportToString(const Airport *a);
我需要做函数名所建议的事情,我需要将传递的Airport结构转换为字符串,然后使用驱动程序打印返回的字符数组。我知道sprintf和所有这些方法,但我不想从这个函数打印,我需要从主函数打印。我有一些代码,它只是一系列strcat,但它似乎是一种错误的处理方式,而且当它到达纬度时,它会失败,因为你不能使用strcat将一个double放入字符串中。另一个规定是我必须动态分配字符串,这样我就有了一行malloc,看起来像:

char * array = (char * ) malloc((sizeof(Airport) * 1) + 8);
但我认为这也会带来更多的错误,+8只是用于格式化的空格和结尾处的空终止符,但如果将double或int转换为string,并且它们很大,则会超出数组边界并超出边界,对吗?完成这项任务的最佳方式是什么我需要做的是:

构造表示给定机场的新字符串。格式的细节可以是任何东西,但它应该是可读的,并提供合理的 机场结构的详细信息量。此外,返回的字符串
应动态分配。

如前所述,确定所需空间量的一种有效方法是使用指定为
NULL
0
str
size
snprintf
进行初始调用,分别强制
snprintf
返回如果
str
size
为写入提供了足够的空间,本应写入的字符数。然后,您可以使用
snprintf+1
返回的字符数来动态分配一个足以容纳转换为字符串的结构内容的缓冲区。在本例中,输出格式只是一个由
airport
结构值组成的逗号分隔字符串(通常避免在C中使用变量/结构名称的前导大写,而不是无效的,只是一种传统样式)

以下是解决此问题的一种方法。
struct2str
函数返回一个动态分配的字符串,其中包含airport结构的内容,如果成功,否则返回
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;
}

如前所述,确定所需空间量的一种有效方法是使用指定为
NULL
0
str
size
snprintf
进行初始调用,分别强制
snprintf
返回如果
str
size
为写入提供了足够的空间,本应写入的字符数。然后,您可以使用
snprintf+1
返回的字符数来动态分配一个足以容纳转换为字符串的结构内容的缓冲区。在本例中,输出格式只是一个由
airport
结构值组成的逗号分隔字符串(通常避免在C中使用变量/结构名称的前导大写,而不是无效的,只是一种传统样式)

以下是解决此问题的一种方法。
struct2str
函数返回一个动态分配的字符串,其中包含airport结构的内容,如果成功,否则返回
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;
}

snprintf()。您可以在任何缓冲区上调用它以获得正确的大小来动态分配字符串,然后使用动态分配的缓冲区再次调用它以实际写入字符串。说“我知道
sprintf
和所有这些方法”是没有意义的-如果你知道它们,那么就使用它们,它们是正确的方法。我想我脑子里出了点问题,sprintf实际上不会打印我组合的字符串,对吗?它将把参数放在第一个参数中,然后我需要打印出来,是吗?例如,如果我有:sprintf(str,“Test%f”,M_PI);这将使测试3.14。。。。。输入str但不打印它是吗?是的,这是正确的,
sprintf
snprintf
的输出进入作为第一个参数传递的缓冲区。
snprintf()
将返回如果传递的大小是无限的,将打印的字符数。您可以在任何缓冲区上调用它以获得正确的大小来动态分配字符串,然后使用动态分配的缓冲区再次调用它以实际写入字符串。说“我知道
sprintf
和所有这些方法”是没有意义的-如果你知道它们,那么就使用它们,它们是正确的方法。我想我脑子里出了点问题,sprintf实际上不会打印我组合的字符串,对吗?它将把参数放在第一个参数中,然后我需要打印出来,是吗?例如,如果我有:sprintf(str,“Test%f”,M_PI);这将使测试3.14。。。。。输入str但不打印它是吗?是的,这是正确的,
sprintf
snprintf
的输出进入作为第一个参数传递的缓冲区。