xóa một mảng char c


104

Tôi nghĩ bằng cách đặt phần tử đầu tiên thành null sẽ xóa toàn bộ nội dung của mảng char.

char my_custom_data[40] = "Hello!";
my_custom_data[0] = '\0';

Tuy nhiên, điều này chỉ đặt phần tử đầu tiên thành null.

hoặc là

my_custom_data[0] = 0; 

thay vì sử dụng memset, tôi nghĩ 2 ví dụ trên sẽ xóa tất cả dữ liệu.


1
Jared, tại sao bạn lại đặt thẻ c ++? anh ấy đã nói về "C" và không thêm bất kỳ thẻ nào liên quan đến C ++.
Johannes Schaub - litb

1
Điều này cũng áp dụng tốt cho các mảng ký tự trong C ++, mặc dù anh ta không chỉ định.
Adam Hawes

4
Tôi đã gỡ bỏ C ++ thẻ để tránh những gì chúng ta đã thấy với những người cung cấp giải pháp cụ thể C ++
Alnitak

Câu trả lời:


113

Nó phụ thuộc vào cách bạn muốn xem mảng. Nếu bạn đang xem mảng như một chuỗi ký tự, thì cách duy nhất để xóa dữ liệu là chạm vào mọi mục nhập. memsetcó lẽ là cách hiệu quả nhất để đạt được điều này.

Mặt khác, nếu bạn đang chọn xem đây là một chuỗi kết thúc rỗng trong C / C ++, việc đặt byte đầu tiên thành 0 sẽ xóa chuỗi một cách hiệu quả.


4
Từ khóa của họ trong câu trả lời là 'hiệu quả'. Chỉ phần tử đầu tiên được đặt thành 0 và phần còn lại vẫn có giá trị không xác định nhưng nếu bạn đang coi mảng là một chuỗi kết thúc bằng null và phần tử đầu tiên là null, thì chuỗi đó được coi là trống.
Arnold Spence

thực sự, đây là câu trả lời folks.
Johannes Schaub - litb

@caparcode, chính xác. Đó là lý do tại sao điều rất quan trọng là phải hiểu cách mảng đang được sử dụng.
JaredPar

Vâng, đó là những gì tôi nên nói trong bài viết đầu tiên của tôi. Char là một chuỗi kết thúc. vì vậy hoặc những thứ này sẽ thực hiện thủ thuật đó. char [0] = '\ 0'; hoặc char [0] = 0. Tôi không chắc nhưng tôi nghe nói rằng việc sử dụng '\ 0' sẽ tốt hơn cho việc sử dụng các chuỗi kết thúc bằng null.
ant2009,

@robUK, vâng bạn nói đúng. Về mặt kỹ thuật, '\ 0' bằng 0 (trong ascii) nhưng bạn nên sử dụng '\ 0' vì nó làm cho ý định của bạn rõ ràng
Mark Testa

70

Một mảng trong C chỉ là một vị trí bộ nhớ, vì vậy thực tế, my_custom_data[0] = '\0';bài tập của bạn chỉ cần đặt phần tử đầu tiên bằng 0 và giữ nguyên các phần tử khác.

Nếu bạn muốn xóa tất cả các phần tử của mảng, bạn sẽ phải truy cập từng phần tử. Đó là những gì memsetdành cho:

memset(&arr[0], 0, sizeof(arr));

Đây thường là cách nhanh nhất để giải quyết vấn đề này. Nếu bạn có thể sử dụng C ++, hãy xem xét std :: fill thay thế:

char *begin = &arr;
char *end = begin + sizeof(arr);
std::fill(begin, end, 0);

1
Tôi tin rằng phiên bản thứ hai nên là: std :: fill (arr, arr + sizeof (arr) / sizeof (arr [0]), 0);
David Rodríguez - dribeas

Làm rõ: không sử dụng sizeof với điền vì bạn sẽ gặp rắc rối sau này với các mảng int, long, double hoặc những gì có bạn.
Zan Lynx

Tôi thích: std :: fill (& arr [0], & arr [arr_len], 0);
Zan Lynx

Zan Lynx, đó là hành vi không xác định. bạn không thể làm & arr [arr_len]. nhưng bạn phải làm std :: fill (arr, arr + sizeof arr, 0); hoặc nếu bạn có độ dài ở đâu đó std :: fill (arr, arr + arr_len, 0); giả sử một mảng các ký tự
Johannes Schaub - litb

Nó chỉ có giá trị trong C. mặc dù các câu hỏi nhắm mục tiêu rõ ràng C (anh chàng khác thêm một ++ thẻ C, tôi đã không có đầu mối tại sao), các chương trình std :: fill C ++ ái lực :)
Johannes Schaub - litb

25

Tại sao bạn nghĩ rằng việc đặt một phần tử duy nhất sẽ xóa toàn bộ mảng? Đặc biệt, trong C, rất ít điều xảy ra nếu không có lập trình viên lập trình rõ ràng. Nếu bạn đặt phần tử đầu tiên thành 0 (hoặc bất kỳ giá trị nào), thì bạn đã thực hiện chính xác điều đó và không còn gì nữa.

Khi khởi tạo, bạn có thể đặt một mảng thành 0:

char mcd[40] = {0}; /* sets the whole array */

Nếu không, tôi không biết bất kỳ kỹ thuật nào ngoài memset, hoặc thứ gì đó tương tự.


Tôi đoán điều này phụ thuộc vào trình biên dịch bạn sử dụng
cacaofan

1
@cocoafan: Không, nó không phụ thuộc vào trình biên dịch. Nó là một phần của đặc tả ngôn ngữ. Bất kỳ trình biên dịch nào hoạt động khác đều không tuân theo ngôn ngữ C.
abelenky

Tôi không biết điều đó, cảm ơn bạn. Tôi không thể tìm thấy bất kỳ nguồn nào mà tôi có thể đọc trường hợp đặc biệt này. Rất vui nếu có nó như một dấu trang.
cacaofan

1
Nó được gọi là khởi tạo từng phần. Tôi không có thông số C99, nhưng đây là hai nguồn: bit.ly/enBC2m "Bạn không cần phải khởi tạo tất cả các phần tử trong một mảng. Nếu một mảng được khởi tạo một phần, các phần tử không được khởi tạo sẽ nhận giá trị 0 của loại thích hợp. " bit.ly/f9asHH "Nếu có initializers ít hơn các yếu tố trong mảng đó, các yếu tố còn lại sẽ tự động khởi tạo 0"
abelenky

Điều này không áp dụng cho một mảng đã được khai báo và gán giá trị phải không?
skinnedKnuckles

10

Sử dụng:

memset(my_custom_data, 0, sizeof(my_custom_data));

Hoặc là:

memset(my_custom_data, 0, strlen(my_custom_data));

1
Tùy chọn thứ hai ( memset(my_custom_data, 0, strlen(my_custom_data));) sẽ chỉ xóa đến '\ 0' đầu tiên, có thể nằm ngoài phần cuối của mảng. Điều này có thể, hoặc có thể không, không sao.
brewmanz

9

Hãy thử mã sau:

void clean(char *var) {
    int i = 0;
    while(var[i] != '\0') {
        var[i] = '\0';
        i++;
    }
}

2
FYI - thụt lề mã 4 dấu cách hoặc chọn nó và nhấn nút 'mã', trông giống như hai dòng nhị phân.
Mudgar

Giải pháp tuyệt vời nếu bạn không muốn bao gồm string.h cho memset ().
Akash Agarwal

7

Tại sao không sử dụng memset()? Đó là cách để làm điều đó.

Việc đặt phần tử đầu tiên sẽ không ảnh hưởng đến phần còn lại của bộ nhớ, nhưng các hàm str sẽ coi dữ liệu là trống.


1
Không sử dụng memset qua dễ đọc: stackoverflow.com/questions/453432/...
Johann Gerell

1
và câu trả lời của bạn sau đó là gì?
mkb

6

Vui lòng tìm bên dưới nơi tôi đã giải thích với dữ liệu trong mảng sau trường hợp 1 và trường hợp 2.

char sc_ArrData[ 100 ];
strcpy(sc_ArrData,"Hai" );

Trường hợp 1:

sc_ArrData[0] = '\0';

Kết quả:

-   "sc_ArrData"
[0] 0 ''
[1] 97 'a'
[2] 105 'i'
[3] 0 ''

Trường hợp 2:

memset(&sc_ArrData[0], 0, sizeof(sc_ArrData));

Kết quả:

-   "sc_ArrData"
[0] 0 ''
[1] 0 ''
[2] 0 ''
[3] 0 ''

Mặc dù đặt đối số đầu tiên thành NULL sẽ thực hiện thủ thuật, nhưng nên sử dụng memset


4

Không. Tất cả những gì bạn đang làm là đặt giá trị đầu tiên thành '\ 0' hoặc 0.

Nếu bạn đang làm việc với chuỗi kết thúc bằng null, thì trong ví dụ đầu tiên, bạn sẽ nhận được hành vi bắt chước những gì bạn mong đợi, tuy nhiên bộ nhớ vẫn được thiết lập.

Nếu bạn muốn xóa bộ nhớ mà không sử dụng memset, hãy sử dụng vòng lặp for.


Tôi nói không với vòng lặp for. Cố gắng không viết các hàm thư viện "cải tiến" (và thường là không) của riêng bạn. Trên thực tế, memset và memcpy khá đặc biệt thường được đưa vào mã máy tùy chỉnh cho CPU dựa trên những gì đã biết về độ dài và căn chỉnh dữ liệu.
Zan Lynx

@Zan OP không muốn sử dụng memset (có lẽ anh ấy đã nhúng và không có sẵn nó). Nhưng có, memset thường rất tối ưu và có thể nhanh hơn vòng lặp for.
Adam Hawes

Đúng, tuy nhiên anh ấy không muốn sử dụng memset, vì vậy tôi đề xuất một vòng lặp for.
Alan

3

Bạn nên sử dụng memset. Chỉ đặt phần tử đầu tiên sẽ không hoạt động, bạn cần phải đặt tất cả các phần tử - nếu không, làm thế nào bạn có thể đặt chỉ phần tử đầu tiên thành 0?


memset không nên được sử dụng quá mức có thể đọc được: stackoverflow.com/questions/453432/…
Johann Gerell,

2

Viết một ký tự null cho ký tự đầu tiên thực hiện điều đó. Nếu bạn coi nó như một chuỗi, mã tuân theo ký tự kết thúc null sẽ coi nó như một chuỗi rỗng, nhưng điều đó không giống như xóa dữ liệu. Nếu bạn muốn thực sự xóa dữ liệu, bạn sẽ cần sử dụng memset.



1

Tôi nghĩ bằng cách đặt phần tử đầu tiên thành null sẽ xóa toàn bộ nội dung của mảng char.

Điều đó không đúng như bạn đã phát hiện

Tuy nhiên, điều này chỉ đặt phần tử đầu tiên thành null.

Chính xác!

Bạn cần sử dụng memset để xóa tất cả dữ liệu, không đủ để đặt một trong các mục nhập thành null.

Tuy nhiên, nếu đặt một phần tử của mảng thành null có nghĩa là một điều gì đó đặc biệt (ví dụ: khi sử dụng chuỗi kết thúc null trong) thì có thể đủ để đặt phần tử đầu tiên thành null. Bằng cách đó, bất kỳ người dùng nào của mảng sẽ hiểu rằng nó trống mặc dù mảng vẫn bao gồm các ký tự cũ trong bộ nhớ


Không sử dụng "memset" vượt quá khả năng đọc: stackoverflow.com/questions/453432/…
Johann Gerell,

1

đặt phần tử đầu tiên thành NULL. in mảng char sẽ không trả lại gì cho bạn.



-3
void clearArray (char *input[]){
    *input = ' '; 
}

1
Đây không phải là XÓA, nó chỉ là đặt ký tự đầu tiên thành ''! Tôi nghĩ rằng bạn muốn viết * input = '\ 0'
stviper

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.