2010-06-28 27 views
37

我想了解如何在C中以最清潔/最安全的方式解決這個微不足道的問題。這是我的例子:如何正確分配一個新的字符串值?

#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    typedef struct 
    { 
     char name[20]; 
     char surname[20]; 
     int unsigned age; 
    } person; 

    //Here i can pass strings as values...how does it works? 
    person p = {"John", "Doe",30}; 

    printf("Name: %s; Age: %d\n",p.name,p.age); 
    // This works as expected... 
    p.age = 25; 
    //...but the same approach doesn't work with a string 
    p.name = "Jane"; 

    printf("Name: %s; Age: %d\n",p.name,p.age); 

    return 1; 
} 

編譯器的錯誤是:

main.c: In function ‘main’: main.c:18: error: incompatible types when assigning to type ‘char[20]’ from type ‘char *’

據我所知,C(不是C++)沒有字符串類型,而是使用字符數組,所以另一種方式來做到這一點是改變的例子結構保持字符的指針:

#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    typedef struct 
    { 
     char *name; 
     char *surname; 
     int unsigned age; 
    } person; 

    person p = {"John", "Doe",30}; 

    printf("Name: %s; Age: %d\n",p.name,p.age); 

    p.age = 25; 

    p.name = "Jane"; 

    printf("Name: %s; Age: %d\n",p.name,p.age); 

    return 1; 
} 

可正常工作,但我不知道是否有這樣做更好的方法。謝謝。

+0

如果我們在'main()'中聲明結構體,那麼只有人可以在裏面訪問它。 嘗試從主要移出使用它作爲全球 – EsmaeelE 2018-03-03 19:58:27

回答

29

第一個示例不起作用,因爲您無法將值分配給數組 - 數組在這方面像const指針一樣工作(有點)。什麼可以做,雖然是複製一個新的值到數組:

strcpy(p.name, "Jane"); 

字符數組都很好,如果你知道該字符串的最大大小提前使用,例如在第一個示例中,您100%確定名稱將適合19個字符(不是20,因爲總是需要一個字符來存儲終止的零值)。相反,如果您不知道字符串可能的最大大小,並且/或者您希望優化內存使用情況,例如指針,則指針會更好。避免爲「John」名稱保留512個字符。但是,使用指針需要動態分配它們指向的緩衝區,並在不再需要時釋放它,以避免內存泄漏。

更新:動態分配的緩衝區(使用您的第二個示例結構定義)的例如:

char* firstName = "Johnnie"; 
char* surname = "B. Goode"; 
person p; 

p.name = malloc(strlen(firstName) + 1); 
p.surname = malloc(strlen(surname) + 1); 

p.age = 25; 
strcpy(p.name, firstName); 
strcpy(p.surname, surname); 

printf("Name: %s; Age: %d\n",p.name,p.age); 

free(p.surname); 
free(p.name); 
7

字符串作爲抽象的對象,字符數組作爲容器的思考。該字符串可以是任何大小,但容器必須至少比字符串長度多1(以容納空終止符)。

C對字符串的語法支持很少。沒有字符串操作符(只有char-array和char-pointer操作符)。你不能分配字符串。

但是你可以調用函數來幫助實現你想要的。

可以在這裏使用strncpy()函數。爲了獲得最大的安全性,我建議以下這種模式:

strncpy(p.name, "Jane", 19); 
p.name[19] = '\0'; //add null terminator just in case 

也有看strncat()memcpy()功能。

+1

現在最好的答案,但也是佩特的一個很好(顯示如何使用指針),所以我等一會兒,看看更多的人可以添加更多的提示/關於這個問題的建議。 – 2010-06-28 10:38:07

4

這兩個結構是不同的。當初始化第一個結構時,會分配大約40個字節的內存。初始化第二個結構體時,大約分配了10個字節的內存。 (實際數量取決於架構)

您可以使用字符串文字(字符串常量)初始化字符數組。這就是爲什麼

person p = {"John", "Doe",30};

在第一個例子中工作。

您不能分配(傳統意義上的)的字符串在C

你(「約翰」)是你的代碼執行時加載到內存中的字符串文字。當用這些文字中的一個初始化數組時,字符串被複制到一個新的內存位置。在你的第二個例子中,你只是將指針複製到字符串文字的位置。做這樣的事情:

char* string = "Hello"; 
*string = 'C' 

可能會導致編譯或運行時錯誤(我不知道)。這是一個壞主意,因爲要修改的文本字符串「你好」的,例如在單片機,可設在只讀存儲器中。

+0

你是對的,你寫的任務會導致段錯誤,因爲你正試圖改變一個指針的值,但是引用我的例子就像char * string =「Hello」; string =「C」; (注意最後一條語句沒有指針分配),它按預期工作。 – 2010-06-28 10:07:34

+1

我想提一下,「改變指針值」並不一定會導致段錯誤。原始帖子中的代碼段導致段錯誤的原因是因爲您試圖修改位於受限地址空間中的內存。 – Gus 2010-06-28 10:13:53

相關問題