limpando uma matriz char c


104

Achei que definir o primeiro elemento como nulo limparia todo o conteúdo de uma matriz char.

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

No entanto, isso apenas define o primeiro elemento como nulo.

ou

my_custom_data[0] = 0; 

em vez de usar memset, pensei que os 2 exemplos acima deveriam limpar todos os dados.


1
Jared, por que você definiu a tag c ++? ele falou sobre "C" e não adicionou nenhuma tag relacionada a C ++.
Johannes Schaub - litb

1
Isso se aplica igualmente bem a matrizes de caracteres em C ++, embora ele não tenha especificado.
Adam Hawes,

4
Removi a tag C ++ para evitar o que já vimos com pessoas que oferecem soluções específicas de C ++
Alnitak

Respostas:


113

Depende de como você deseja visualizar a matriz. Se você estiver vendo o array como uma série de caracteres, a única maneira de limpar os dados é tocar em cada entrada. memseté provavelmente a maneira mais eficaz de conseguir isso.

Por outro lado, se você estiver escolhendo ver isso como uma string C / C ++ terminada em nulo, definir o primeiro byte como 0 limpará efetivamente a string.


4
A palavra-chave na resposta é 'efetivamente'. Apenas o primeiro elemento é definido como 0 e o resto ainda tem valores indefinidos, mas se você estiver tratando a matriz como uma string terminada em nulo e o primeiro elemento for nulo, a string será considerada vazia.
Arnold Spence,

na verdade, esta é a resposta, pessoal.
Johannes Schaub - litb

@caparcode, exatamente. É por isso que é muito importante entender como o array está sendo usado.
JaredPar

Sim, isso é o que eu deveria ter dito no meu primeiro post. O char é uma string terminada. então qualquer um deles fará esse truque. char [0] = '\ 0'; ou char [0] = 0. Não tenho certeza, mas ouvi dizer que usar '\ 0' é melhor para usar strings com terminação nula.
ant2009

@robUK, sim, você está correto. Tecnicamente, '\ 0' é igual a 0 (em ascii), mas você deve usar '\ 0' porque torna sua intenção clara
Mark Testa

70

Um array em C é apenas um local de memória, então, de fato, sua my_custom_data[0] = '\0';atribuição simplesmente define o primeiro elemento como zero e deixa os outros elementos intactos.

Se você quiser limpar todos os elementos do array, terá que visitar cada elemento. É memsetpara isso:

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

Geralmente, essa é a maneira mais rápida de cuidar disso. Se você pode usar C ++, considere std :: fill em vez disso:

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

1
Eu acredito que a segunda versão deveria ser: std :: fill (arr, arr + sizeof (arr) / sizeof (arr [0]), 0);
David Rodríguez - dribeas

Esclarecimento: não use sizeof com fill porque você terá problemas mais tarde com arrays de int, long, double ou o que for.
Zan Lynx

Eu prefiro: std :: fill (& arr [0], & arr [arr_len], 0);
Zan Lynx

Zan Lynx, esse é um comportamento indefinido. você não pode fazer & arr [arr_len]. mas você tem que fazer std :: fill (arr, arr + sizeof arr, 0); ou se você tiver o comprimento em algum lugar std :: fill (arr, arr + arr_len, 0); assumindo uma matriz de char
Johannes Schaub - litb

É válido apenas em C. embora a questão claramente visasse C (outro cara adicionou uma tag C ++, não tenho ideia do porquê), o std :: fill mostra afinidade C ++ :)
Johannes Schaub - litb

25

Por que você acha que definir um único elemento limparia todo o array? Em C, especialmente, pouco acontece sem o programador programá-lo explicitamente. Se você definir o primeiro elemento como zero (ou qualquer valor), terá feito exatamente isso e nada mais.

Ao inicializar, você pode definir uma matriz para zero:

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

Caso contrário, não conheço nenhuma técnica diferente de memset ou algo semelhante.


Acho que isso depende do compilador que você usa
cocoafan

1
@cocoafan: Não, não é dependente do compilador. Faz parte da especificação do idioma. Qualquer compilador que se comporta de maneira diferente não segue a linguagem C.
Abelenky

Eu não sabia disso, obrigado. Não consegui encontrar nenhum recurso onde possa ler este caso especial. Seria bom tê-lo como marcador.
cocoafan

1
É chamado de inicialização parcial. Eu não tenho a especificação C99, mas aqui estão duas fontes: bit.ly/enBC2m "Você não precisa inicializar todos os elementos em uma matriz. Se uma matriz for parcialmente inicializada, os elementos que não foram inicializados recebem o valor 0 de o tipo apropriado. " bit.ly/f9asHH "Se houver menos inicializadores do que elementos na matriz, os elementos restantes são inicializados automaticamente para 0"
abelenky

Isso não se aplica a uma matriz que já foi declarada e com valores atribuídos, certo?
skinnedKnuckles

10

Usar:

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

Ou:

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

1
A segunda opção ( memset(my_custom_data, 0, strlen(my_custom_data));) limpará apenas o primeiro '\ 0', que pode estar além do final da matriz. Isso pode, ou não, estar bem.
brewmanz

9

Experimente o seguinte código:

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

2
FYI - recue o código em 4 espaços ou selecione-o e aperte o botão 'código', que se parece com duas linhas de binário.
meagar

Excelente solução se você não quiser incluir string.h para memset ().
Akash Agarwal


6

Por favor, encontre abaixo onde eu expliquei os dados na matriz após os casos 1 e 2.

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

Caso 1:

sc_ArrData[0] = '\0';

Resultado:

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

Caso 2:

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

Resultado:

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

Embora definir o primeiro argumento como NULL resolva o problema, é aconselhável usar o memset


4

Não. Tudo o que você está fazendo é definir o primeiro valor como '\ 0' ou 0.

Se você estiver trabalhando com strings terminadas em null, então, no primeiro exemplo, você obterá um comportamento que imita o que você espera, no entanto, a memória ainda está configurada.

Se você quiser limpar a memória sem usar o memset, use um loop for.


Eu digo não no loop for. Tente não escrever suas próprias funções de biblioteca "aprimoradas" (e geralmente não). Na verdade, memset e memcpy são bastante especiais e muitas vezes embutidos no código de máquina personalizado para a CPU com base no que é conhecido sobre o alinhamento e o comprimento dos dados.
Zan Lynx

@Zan o OP não deseja usar o memset (talvez ele esteja incorporado e não o tenha disponível). Mas sim, o memset geralmente é altamente ideal e provavelmente mais rápido do que um loop for.
Adam Hawes,

É verdade, entretanto, ele não queria usar o memset, então sugeri um loop for.
Alan


2

Escrever um caractere nulo para o primeiro caractere faz exatamente isso. Se você tratá-lo como uma string, o código que obedece ao caractere de terminação nulo o tratará como uma string nula, mas isso não é o mesmo que limpar os dados. Se você quiser realmente limpar os dados, precisará usar o memset.



1

Achei que definir o primeiro elemento como nulo limparia todo o conteúdo de uma matriz char.

Isso não está correto como você descobriu

No entanto, isso apenas define o primeiro elemento como nulo.

Exatamente!

Você precisa usar o memset para limpar todos os dados, não é suficiente definir uma das entradas como nula.

No entanto, se definir um elemento da matriz como nulo significa algo especial (por exemplo, ao usar uma string de terminação nula em), pode ser suficiente definir o primeiro elemento como nulo. Dessa forma, qualquer usuário do array entenderá que ele está vazio mesmo que o array ainda inclua os chars antigos na memória


Não use "memset" em vez de legibilidade: stackoverflow.com/questions/453432/…
Johann Gerell

1

defina o primeiro elemento como NULL. imprimir o array char não lhe dará nada em troca.



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

1
Isso não é CLARO, é apenas definir o primeiro caractere para ''! Acho que você queria escrever * input = '\ 0'
stviper

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.