bir karakter dizisini temizleme c


104

İlk öğeyi bir boşa ayarlamanın, bir char dizisinin tüm içeriğini temizleyeceğini düşündüm.

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

Ancak, bu yalnızca ilk öğeyi null olarak ayarlar.

veya

my_custom_data[0] = 0; 

Kullanmak yerine memset, yukarıdaki 2 örneğin tüm verileri temizlemesi gerektiğini düşündüm.


1
Jared, neden c ++ etiketini ayarladın? "C" hakkında konuştu ve C ++ ile ilgili herhangi bir etiket eklemedi.
Johannes Schaub - litb

1
Bu, C ++ 'daki karakter dizileri için, kendisi belirtmemiş olsa da eşit derecede geçerlidir.
Adam Hawes

4
C ++ 'ya özel çözümler sunan insanlarda gördüklerimizden kaçınmak için C ++ etiketini kaldırdım
Alnitak

Yanıtlar:


113

Diziyi nasıl görüntülemek istediğinize bağlıdır. Diziyi bir dizi karakter olarak görüntülüyorsanız, verileri temizlemenin tek yolu her girişe dokunmaktır. memsetmuhtemelen bunu başarmanın en etkili yoludur.

Öte yandan, bunu bir C / C ++ boş sonlandırılmış dizge olarak görmeyi seçiyorsanız, ilk baytı 0 olarak ayarlamak dizeyi etkili bir şekilde temizleyecektir.


4
Cevaptaki anahtar kelime 'etkili'. Yalnızca ilk öğe 0'a ayarlanmaya başlar ve geri kalanı hala tanımlanmamış değerlere sahiptir, ancak diziyi boş sonlandırılmış bir dize olarak ele alıyorsanız ve ilk öğe boşsa, dize boş kabul edilir.
Arnold Spence

gerçekten de cevap millet.
Johannes Schaub - litb

@caparcode, aynen. Bu yüzden dizinin nasıl kullanıldığını anlamak çok önemlidir.
JaredPar

Evet, ilk yazımda söylemem gereken şey buydu. Char, sonlandırılmış bir dizedir. yani ya bunlar bu numarayı yapacak. karakter [0] = '\ 0'; veya char [0] = 0. Emin değilim ama '\ 0' kullanmanın boş sonlandırılmış dizeleri kullanmak için daha iyi olduğunu duydum.
ant2009

@robUK, evet haklısın. Teknik olarak '\ 0' 0'a eşittir (ascii'de), ancak '\ 0' kullanmalısınız çünkü amacınızı netleştirir
Mark Testa

70

C'deki bir dizi yalnızca bir bellek konumudur, dolayısıyla atamanız my_custom_data[0] = '\0';basitçe ilk öğeyi sıfıra ayarlar ve diğer öğeleri olduğu gibi bırakır.

Dizinin tüm öğelerini temizlemek istiyorsanız, her öğeyi ziyaret etmeniz gerekir. Bunun memsetiçin:

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

Bu genellikle bununla ilgilenmenin en hızlı yoludur. C ++ kullanabiliyorsanız, bunun yerine std :: fill'i düşünün:

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

1
İkinci versiyonun şu olması gerektiğine inanıyorum: std :: fill (arr, arr + sizeof (arr) / sizeof (arr [0]), 0);
David Rodríguez - dribeas

Açıklama: sizeof'u fill ile birlikte kullanmayın, çünkü daha sonra int, long, double dizileriyle veya neye sahip olduğunuzla başınız derde girecek.
Zan Lynx

Tercih ederim: std :: fill (& arr [0], & arr [arr_len], 0);
Zan Lynx

Zan Lynx, bu tanımlanmamış bir davranış. [arr_len] yapamaz ve düzenleyemezsiniz. ancak std :: fill (arr, arr + sizeof arr, 0); veya uzunluğa std :: fill (arr, arr + arr_len, 0); bir karakter dizisi varsayarsak
Johannes Schaub - litb

Yalnızca C'de geçerlidir. soru açıkça C'yi hedeflese de (başka bir adam bir C ++ etiketi ekledi, nedenini bilmiyorum), std :: fill C ++ yakınlığını gösteriyor :)
Johannes Schaub - litb

25

Neden tek bir eleman belirlemenin tüm diziyi temizleyeceğini düşünüyorsunuz? Özellikle C'de, programcı açıkça programlamadan çok az şey olur. İlk öğeyi sıfıra (veya herhangi bir değere) ayarlarsanız, tam olarak bunu yapmış olursunuz ve daha fazlasını yapmazsınız.

Başlatırken bir diziyi sıfıra ayarlayabilirsiniz:

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

Aksi takdirde, memset veya benzeri bir şey dışında herhangi bir teknik bilmiyorum.


Sanırım bu kullandığınız derleyiciye bağlı
cocoafan

1
@cocoafan: Hayır, derleyiciye bağlı değildir. Dil spesifikasyonunun bir parçasıdır. Farklı davranan herhangi bir derleyici C dilini takip etmiyor.
abelenky

Bunu bilmiyordum, teşekkür ederim. Bu özel durumu okuyabileceğim herhangi bir kaynak bulamadım. Yer imi olarak sahip olmak güzel olurdu.
cocoafan

1
Kısmi başlatma denir. C99 spesifikasyonuna sahip değilim, ancak işte iki kaynak var: bit.ly/enBC2m "Bir dizideki tüm öğeleri başlatmanıza gerek yok. Bir dizi kısmen başlatılmışsa, başlatılmamış öğeler 0 değerini alır uygun tip. " bit.ly/f9asHH " Dizideki öğelerden daha az başlatıcı varsa, kalan öğeler otomatik olarak 0"
abelenky

Bu, önceden bildirilmiş ve değerleri atanmış bir dizi için geçerli değil mi?
skinnedKnuckles

10

Kullanım:

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

Veya:

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

1
İkinci seçenek ( memset(my_custom_data, 0, strlen(my_custom_data));) yalnızca dizinin sonunun ötesinde olabilecek ilk '\ 0'a temizlenir. Bu sorun olabilir veya olmayabilir.
brewmanz

9

Aşağıdaki kodu deneyin:

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

2
Bilginize - kodu 4 boşluk ile girintileyin veya seçin ve iki satırlık ikili gibi görünen 'kod' düğmesine basın.
meagar

Memset () için string.h eklemek istemiyorsanız mükemmel bir çözüm.
Akash Agarwal


6

Pls, durum 1 ve durum 2'den sonra dizideki verilerle açıkladığım yeri aşağıda bulabilirsiniz.

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

Dava 1:

sc_ArrData[0] = '\0';

Sonuç:

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

Durum 2:

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

Sonuç:

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

İlk bağımsız değişkeni NULL olarak ayarlamak işe yarayacak olsa da memset kullanılması tavsiye edilir


4

Hayır! Tüm yaptığınız ilk değeri '\ 0' veya 0 olarak ayarlamaktır.

Boş sonlandırılmış dizelerle çalışıyorsanız, ilk örnekte, beklediğiniz şeyi taklit eden bir davranış elde edersiniz, ancak bellek yine de ayarlıdır.

Belleği memset kullanmadan temizlemek istiyorsanız, for döngüsü kullanın.


For döngüsünde hayır diyorum. Kendi "geliştirilmiş" (ve genellikle değil) kitaplık işlevlerinizi yazmamaya çalışın. Aslında, memset ve memcpy oldukça özeldir ve genellikle veri hizalaması ve uzunluğu hakkında bilinenlere dayalı olarak CPU için özel makine koduna yerleştirilir.
Zan Lynx

@Zan the OP memset'i kullanmak istemiyor (belki de gömülüdür ve mevcut değildir). Ancak evet, memset genellikle oldukça optimaldir ve muhtemelen bir for döngüsünden daha hızlıdır.
Adam Hawes

Doğru, ancak memset'i kullanmak istemedi, bu yüzden bir for döngüsü önerdim.
Alan


2

İlk karaktere boş bir karakter yazmak tam da bunu yapar. Bunu bir dizge olarak ele alırsanız, boş sonlandırma karakterine uyan kod, onu boş bir dizge olarak değerlendirir, ancak bu, verileri temizlemekle aynı şey değildir. Verileri gerçekten temizlemek istiyorsanız, memset kullanmanız gerekir.



1

İlk öğeyi bir boşa ayarlamanın, bir char dizisinin tüm içeriğini temizleyeceğini düşündüm.

Bu senin keşfettiğin gibi doğru değil

Ancak, bu yalnızca ilk öğeyi null olarak ayarlar.

Kesinlikle!

Tüm verileri temizlemek için memset kullanmanız gerekir, girişlerden birini null olarak ayarlamak yeterli değildir.

Bununla birlikte, dizinin bir elemanının null olarak ayarlanması özel bir anlama geliyorsa (örneğin, bir boş sonlandırıcı dizge kullanılırken), ilk elemanı null olarak ayarlamak yeterli olabilir. Bu şekilde, dizinin herhangi bir kullanıcısı, dizi hala bellekte eski karakterleri içermesine rağmen boş olduğunu anlayacaktır.


Okunabilirlik yerine "memset" kullanmayın: stackoverflow.com/questions/453432/…
Johann Gerell

1

ilk öğeyi NULL olarak ayarlayın. char dizisini yazdırmak size hiçbir şey vermez.



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

1
Bu TEMİZLEME değil, sadece ilk karakteri '' olarak ayarlıyor! Sanırım * input = '\ 0'
stviper

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.