2015-04-21 63 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'