2015-04-21 67 views
-2

所以我有一个看起来像这样的结构:C语言结构为String

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就是为格式化的空间和结束时的空终止符,但如果将转换双精度值或整型值转换为字符串,并且它们很大,那么它会超出数组边界并超出正确范围?完成此任务的最佳方法是:

构造一个代表给定机场的新字符串。格式化的细节可以是任何事情,但它应该是可读的并且提供关于机场结构的合理的详细数量。而且,返回的字符串 应该动态分配。

+1

'的snprintf()'将返回会如果传入的大小是无限的已打印的字符数。你可以在任何缓冲区上调用它以获得正确的大小来动态分配你的字符串,然后再用你动态分配的缓冲区再次调用它来实际写入它。没有必要说“我知道'sprintf'和所有这些方法” - 如果你知道它们,那么使用它们,它们是正确的方法。 –

+0

我认为我脑子里有什么问题,sprintf会不会真的打印我合并的字符串是正确的?它会将参数放入第一个参数中,然后我需要打印是的?例如,如果我有: sprintf(str,“Test%f”,M_PI); 它会把测试3.14 .....进入str但不打印是吗? – AndyPet74

+0

是的,这是正确的,'sprintf'和'snprintf'的输出会进入您作为第一个参数传递的缓冲区。 – user3386109

回答

2

正如所指出的,一个有效的方法来确定的所需的空间量是使至snprintf的初始呼叫指定为NULLstr & size0,分别迫使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'