2009-02-23 56 views
44

Tôi hơi ngạc nhiên bởi những điều sau đây.Gán các chuỗi ký tự cho các mảng

Ví dụ 1:

char s[100] = "abcd"; // declare and initialize - WORKS 

Ví dụ 2:

char s[100]; // declare 
s = "hello"; // initalize - DOESN'T WORK ('lvalue required' error) 

Tôi đang tự hỏi tại sao phương pháp thứ hai không hoạt động. Nó có vẻ tự nhiên mà nó nên (nó hoạt động với các loại dữ liệu khác)? Ai đó có thể giải thích cho tôi logic đằng sau điều này?

Trả lời

38

Khi khởi tạo một mảng, C cho phép bạn điền vào nó với giá trị. nên

char s[100] = "abcd"; 

về cơ bản là giống như

int s[3] = { 1, 2, 3 }; 

nhưng nó không cho phép bạn làm như assignmend từ s là một mảng và không phải là một con trỏ miễn phí. ý nghĩa của

s = "abcd" 

là gán giá trị con trỏ của "abcd" cho 's' nhưng bạn không thể thay đổi s vì không có gì sẽ trỏ đến mảng.
Điều này có thể và không hoạt động nếu s là char* - con trỏ có thể trỏ đến bất kỳ thứ gì.

nếu bạn muốn sao chép các chuỗi đơn giản sử dụng strcpy

+3

Câu trả lời hay, ngoại trừ bạn không bao giờ nên sử dụng đồng bằng strcpy nữa. Sử dụng strncpy hoặc strlcpy. – dwc

+3

Ngoài ra, s phải là const char *, không phải char *. – aib

+1

's [0] = 'x'; s [1] = 'y'; s [2] = 'z'; s [3] = 'm'; 'hoạt động nếu người ta muốn thay thế các ký tự chuỗi từng cái một ngay cả sau khi khởi tạo. – RBT

9

Khởi tạo và gán là hai hoạt động riêng biệt xảy ra để sử dụng cùng toán tử ("=") tại đây.

41

Không có thứ như "chuỗi" trong C. Chuỗi là mảng char, được kết thúc theo quy ước NULL theo quy ước. Vì bạn không thể gán mảng trong C, bạn cũng không thể gán chuỗi. Các chữ "hello" là cú pháp đường cho const char x[] = {'h','e','l','l','o','\0'};

Cách đúng sẽ là:

char s[100]; 
strncpy(s, "hello", 100); 

hoặc tốt hơn nào:

#define STRMAX 100 
char s[STRMAX]; 
size_t len; 
len = strncpy(s, "hello", STRMAX); 
+0

Không phải phương pháp được đề xuất. Hãy coi chừng những điều kỳ quặc của strncpy: http://stackoverflow.com/a/1258577/2974922 – nucleon

3
1 char s[100]; 
2 s = "hello"; 

Trong ví dụ mà bạn cung cấp, s thực sự là khởi tạo tại dòng 1, không phải xếp hàng 2. Mặc dù bạn không gán cho nó một giá trị rõ ràng tại thời điểm này, trình biên dịch đã làm. Tại dòng 2, bạn đang thực hiện một thao tác gán, và bạn không thể gán một mảng ký tự cho một mảng ký tự như thế này. Bạn sẽ phải sử dụng strcpy() hoặc một số loại vòng lặp để gán mỗi phần tử của mảng.

2

Mở rộng trên Sparr's answer

Khởi tạo và phân công là hai hoạt động riêng biệt mà xảy ra để sử dụng các nhà điều hành cùng ("=") ở đây.

nghĩ về nó như thế này:

Hãy tưởng tượng rằng có 2 chức năng, gọi InitializeObjectAssignObject.Khi trình biên dịch thấy thing = value, nó xem xét ngữ cảnh và gọi một InitializeObject nếu bạn đang tạo một thing mới. Nếu không, thay vào đó, hãy gọi số AssignObject.

Thường thì điều này là tốt như InitializeObjectAssignObject thường hoạt động theo cùng một cách. Ngoại trừ khi giao dịch với mảng char (và một vài trường hợp cạnh khác), trong trường hợp này chúng hoạt động khác nhau. Tại sao làm điều này? Vâng đó là một bài viết khác liên quan đến ngăn xếp so với đống và vv và vv.

PS: Là một sang một bên, suy nghĩ về nó theo cách này cũng sẽ giúp bạn hiểu nhà xây dựng bản sao và những thứ khác như vậy nếu bạn đã từng dấn thân vào C++

0

Lưu ý rằng bạn vẫn có thể làm:

s[0] = 'h'; 
s[1] = 'e'; 
s[2] = 'l'; 
s[3] = 'l'; 
s[4] = 'o'; 
s[5] = '\0'; 
+0

Nó đẹp hơn và dễ sử dụng hơn strncpy(), mặc dù tôi khá chắc chắn strncpy() thực hiện chính xác nội bộ này. –

+0

Tất nhiên. Nhưng điều này là gần như nó được để 's = "hello";' Trong thực tế, điều này cần phải được thực hiện trong C, xem như cách bạn có thể gán cấu trúc. – aib

+0

Tôi có nghĩa là, sao chép thành viên theo phân công trong cấu trúc nhưng không phải trong mảng không có ý nghĩa. – aib

-3

Những gì tôi sẽ sử dụng là

char *s = "abcd"; 
+0

Hầu hết chúng ta sẽ không, bởi vì nó có nguy cơ hành vi không xác định. Ở trên chỉ an toàn cho 'const char *'. –

0

Bạn có thể sử dụng này:

yylval.sval=strdup("VHDL + Volcal trance..."); 

Trong đó yylval là char *. strdup từ công việc.

+0

strdup từ thực hiện công việc :) – Yekatandilburg

Các vấn đề liên quan