2010-10-03 86 views
2

C對於字符串來說總是很尷尬,但是爲字符串分配一個大小爲256的char數組通常是可以的,並且可以繼續。從意外長度的函數返回字符串?

但是,如果您希望該函數返回一個字符串並且您不知道大小,那麼您會將字符串連接到幾十或幾百次?顯然,這樣的事情是行不通的:

char * my_function(int n, char *string){ 
    if (n < 20) { 
     return string; 
    } 
    else { 
     char *new_string = "abcdefghijklmnop"; 
     strcat(string, new_string); 
     return my_function(n--, string); 
    } 
} 

因此,如何在C處理?

+0

它通常是好,直到它不提倡使用的256個字符數組,然後它被稱爲一個緩衝區溢出,這是一件壞事。不要依賴這樣的假設,**總是**確保你的字符串符合可用內存。 – Secure 2010-10-03 08:29:34

回答

4

最直接的方式做到這一點連接字符串任意數量的是一個功能:

  1. 遍歷所有的琴絃並加起來他們的strlen()
  2. malloc()的總長度。
  3. 完成malloc'd字符串內的所有並置,然後返回它。
0

你想使用這樣的事:

void my_function (..., char ** result) 
{ 
    // decide how many bytes... 

    // Allocate enough memory. 
    (*result) = malloc(number_of_bytes); 

    // Fill the buffer... 
} 
3

您的第一段提出了一些非常糟糕的假設。我希望你不是那麼做。

無論如何,一般的解決方案都是使用動態分配,並隨時隨地重新分配。然而,這是效率低下的,而更好的方法可能是改變假設你想要連接字符串(少數幾百次),而是在一次操作中用snprintf構建字符串。然後您可以首先計算所需的大小,並且可以選擇分配它,或者只使用固定大小的緩衝區,其中輸出可能會被截斷。

1

有可以處理返回一個字符串,其中最終的大小是未知的幾個常用方法:

  • 你讓來電者負責在緩衝區傳遞的結果,這將是大到足以容納結果。如果你這樣做,你應該要求調用者也傳遞緩衝區的大小,如果結果太大而不是溢出緩衝區,你可以返回一個錯誤(例如,按照snprintf()的例子而不是sprintf()的)。

  • 可以動態分配內存的結果,使主叫方負責釋放內存

一對夫婦(未經測試)的實例爲您my_function()

#include <string.h> 
#include <stdlib.h> 

/* 
    create new string in a dynamically allocated buffer 
*/ 
char * my_function1(int n, char *s1) 
{ 
    static char const new_string[] = "abcdefghijklmnop"; 

    int sz = strlen(s1) + (n * strlen(new_string)) + 1; 

    char* result = malloc(sz); 

    if (result) { 
     strcpy(result, s1); 

     while (n--) { 
      strcat(result, new_string); 
     } 
    } 

    return result; 
} 


/* 
    create new string in a caller provided buffer 
*/ 
int my_function2(int n, char *s1, char* buf, int buf_size) 
{ 
    static char const new_string[] = "abcdefghijklmnop"; 

    int sz = strlen(s1) + (n * strlen(new_string)) + 1; 

    if (sz > buf_size) { 
     return -1; /* error */ 
    } 

    strcpy(buf, s1); 

    while (n--) { 
     strcat(buf, new_string); 
    } 

    return sz-1; /* characters in result */ 
} 
0

有一個方式添加任何長度的字符串到您的原始字符串,使用realloc。您不需要知道字符串的最終長度。

我相信你可以安全地修改調用函數傳遞參數string你的聲明/初始化爲:

char * string = calloc(0, sizeof(char)); 

以任何大小的字符串最初是替換0,再加上1結尾的空。

的功能更改爲:

char * my_function(int n, char *string){ 
    if (n < 20) { 
     return string; 
    } 
    else 
    { 
     char *new_string = "abcdefghijklmnop"; 
     if((temp = realloc(string, strlen(new_string)+ strlen(string) + 1)) == NULL) 
     { 
      printf("Memory allocation error"); 
      exit(1); 
     } 
     strcat(string, new_string); 
     return my_function(n--, string); 
    } 
}