effacer un tableau de caractères c

104

Je pensais qu'en définissant le premier élément sur null effacerait tout le contenu d'un tableau de caractères.

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

Cependant, cela ne définit que le premier élément sur null.

ou

my_custom_data[0] = 0; 

plutôt que d'utiliser memset, j'ai pensé que les 2 exemples ci-dessus devraient effacer toutes les données.

ant2009
la source
1
Jared, pourquoi avez-vous défini la balise c ++? il a parlé de "C" et n'a pas ajouté de balises liées au C ++.
Johannes Schaub - litb
1
Cela s'applique également aux tableaux de caractères en C ++, même s'il n'a pas spécifié.
Adam Hawes
4
J'ai supprimé la balise C ++ pour éviter ce que nous avons déjà vu avec des personnes proposant des solutions spécifiques au C ++
Alnitak

Réponses:

113

Cela dépend de la façon dont vous souhaitez afficher le tableau. Si vous visualisez le tableau sous la forme d'une série de caractères, le seul moyen d'effacer les données est de toucher chaque entrée. memsetest probablement le moyen le plus efficace pour y parvenir.

D'un autre côté, si vous choisissez de l'afficher comme une chaîne terminée par null C / C ++, la définition du premier octet à 0 effacera effectivement la chaîne.

JaredPar
la source
4
Le mot clé dans la réponse est «effectivement». Seul le premier élément est initialisé à 0 et le reste a toujours des valeurs non définies, mais si vous traitez le tableau comme une chaîne terminée par une valeur nulle et que le premier élément est nul, la chaîne est considérée comme vide.
Arnold Spence
en effet, c'est la réponse aux gens.
Johannes Schaub - litb
@caparcode, exactement. C'est pourquoi il est très important de comprendre comment le tableau est utilisé.
JaredPar
Oui, c'est ce que j'aurais dû dire dans mon premier post. Le char est une chaîne terminée. donc soit ceux-ci feront ce tour. char [0] = '\ 0'; ou char [0] = 0. Je ne suis pas sûr mais j'ai entendu dire que l'utilisation de '\ 0' est préférable pour l'utilisation de chaînes terminées par null.
ant2009
@robUK, oui vous avez raison. Techniquement, '\ 0' est égal à 0 (en ascii) mais vous devriez utiliser '\ 0' car cela rend votre intention claire
Mark Testa
70

Un tableau en C est juste un emplacement mémoire, donc en effet, votre my_custom_data[0] = '\0';affectation met simplement le premier élément à zéro et laisse les autres éléments intacts.

Si vous souhaitez effacer tous les éléments du tableau, vous devrez visiter chaque élément. C'est à cela que memsetsert:

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

C'est généralement le moyen le plus rapide de s'en occuper. Si vous pouvez utiliser C ++, considérez plutôt std :: fill:

char *begin = &arr;
char *end = begin + sizeof(arr);
std::fill(begin, end, 0);
John Feminella
la source
1
Je crois que la deuxième version devrait être: std :: fill (arr, arr + sizeof (arr) / sizeof (arr [0]), 0);
David Rodríguez - dribeas
Clarification: n'utilisez pas sizeof avec fill car vous aurez des problèmes plus tard avec des tableaux de int, long, double ou autres.
Zan Lynx
Je préfère: std :: fill (& arr [0], & arr [arr_len], 0);
Zan Lynx
Zan Lynx, c'est un comportement indéfini. vous ne pouvez pas faire & arr [arr_len]. mais vous devez faire std :: fill (arr, arr + sizeof arr, 0); ou si vous avez la longueur quelque part std :: fill (arr, arr + arr_len, 0); assuming an array of char
Johannes Schaub - litb
Il n'est valable qu'en C. bien que la question visait clairement C (un autre gars a ajouté une balise C ++, je n'ai aucune idée de pourquoi), le std :: fill montre une affinité C ++ :)
Johannes Schaub - litb
25

Pourquoi pensez-vous que la définition d'un seul élément effacerait tout le tableau? En C, en particulier, il ne se passe rien sans que le programmeur ne le programme explicitement. Si vous définissez le premier élément sur zéro (ou sur n'importe quelle valeur), c'est exactement ce que vous avez fait et rien de plus.

Lors de l'initialisation, vous pouvez définir un tableau sur zéro:

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

Sinon, je ne connais aucune technique autre que memset, ou quelque chose de similaire.

Abelenky
la source
Je suppose que cela dépend du compilateur que vous utilisez
cocoafan
1
@cocoafan: Non, cela ne dépend pas du compilateur. Cela fait partie de la spécification du langage. Tout compilateur qui se comporte différemment ne suit pas le langage C.
abelenky
Je ne savais pas ça, merci. Je n'ai trouvé aucune ressource permettant de lire ce cas particulier. Ce serait bien de l'avoir comme signet.
cocoafan
1
Cela s'appelle une initialisation partielle. Je n'ai pas la spécification C99, mais voici deux sources: bit.ly/enBC2m "Vous n'avez pas besoin d'initialiser tous les éléments d'un tableau. Si un tableau est partiellement initialisé, les éléments non initialisés reçoivent la valeur 0 de le type approprié. " bit.ly/f9asHH "S'il y a moins d'initialiseurs que d'éléments dans le tableau, les éléments restants sont automatiquement initialisés à 0"
abelenky
Cela ne s'applique pas à un tableau qui a déjà été déclaré et des valeurs attribuées n'est-ce pas?
skinnedKnuckles
10

Utilisation:

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

Ou:

memset(my_custom_data, 0, strlen(my_custom_data));
Jake1164
la source
1
La deuxième option ( memset(my_custom_data, 0, strlen(my_custom_data));) n'effacera que le premier '\ 0', qui pourrait être au-delà de la fin du tableau. Cela peut, ou non, être correct.
brewmanz
9

Essayez le code suivant:

void clean(char *var) {
    int i = 0;
    while(var[i] != '\0') {
        var[i] = '\0';
        i++;
    }
}
Cristian Altamirano
la source
2
FYI - indentez le code de 4 espaces ou sélectionnez-le et appuyez sur le bouton «code», qui ressemble à deux lignes de binaire.
meagar
Excellente solution si vous ne voulez pas inclure string.h pour memset ().
Akash Agarwal
7

Pourquoi ne pas l'utiliser memset()? Voilà comment procéder.

La définition du premier élément laisse le reste de la mémoire intact, mais les fonctions str traiteront les données comme vides.

John Fricker
la source
1
N'utilisez pas memset sur la lisibilité: stackoverflow.com/questions/453432/…
Johann Gerell
1
et quelle est votre réponse alors?
mkb
6

Veuillez trouver ci-dessous où j'ai expliqué avec les données du tableau après le cas 1 et le cas 2.

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

Cas 1:

sc_ArrData[0] = '\0';

Résultat:

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

Cas 2:

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

Résultat:

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

Bien que définir le premier argument sur NULL fera l'affaire, il est conseillé d'utiliser memset

Akaanthan Ccoder
la source
4

Nan. Tout ce que vous faites est de définir la première valeur sur «\ 0» ou 0.

Si vous travaillez avec des chaînes terminées nulles, dans le premier exemple, vous obtiendrez un comportement qui imite ce que vous attendez, mais la mémoire est toujours définie.

Si vous souhaitez effacer la mémoire sans utiliser memset, utilisez une boucle for.

Alan
la source
Je dis non sur la boucle for. Essayez de ne pas écrire vos propres fonctions de bibliothèque «améliorées» (et généralement pas). En fait, memset et memcpy sont plutôt spéciaux et sont souvent intégrés dans le code machine personnalisé pour le processeur en fonction de ce que l'on sait sur l'alignement et la longueur des données.
Zan Lynx
@Zan l'OP ne veut pas utiliser memset (peut-être qu'il est intégré et ne l'a pas disponible). Mais oui, memset est généralement très optimal, et probablement plus rapide qu'une boucle for.
Adam Hawes
C'est vrai, mais il ne voulait pas utiliser memset, alors j'ai suggéré une boucle for.
Alan
3

Vous devez utiliser memset. Définir uniquement le premier élément ne fonctionnera pas, vous devez définir tous les éléments.Sinon, comment pourriez-vous définir uniquement le premier élément à 0?

Michael
la source
memset ne doit pas être utilisé au-dessus de la lisibilité: stackoverflow.com/questions/453432/…
Johann Gerell
2

L'écriture d'un caractère nul sur le premier caractère fait exactement cela. Si vous le traitez comme une chaîne, le code obéissant au caractère de terminaison nul le traitera comme une chaîne nulle, mais ce n'est pas la même chose que d'effacer les données. Si vous souhaitez réellement effacer les données, vous devrez utiliser memset.

Tvanfosson
la source
2

Je fais généralement comme ça:

memset(bufferar, '\0', sizeof(bufferar));
Jevgenij Kononov
la source
1

Je pensais qu'en définissant le premier élément sur null effacerait tout le contenu d'un tableau de caractères.

Ce n'est pas correct comme tu l'as découvert

Cependant, cela ne définit que le premier élément sur null.

Exactement!

Vous devez utiliser memset pour effacer toutes les données, il ne suffit pas de définir l'une des entrées sur null.

Cependant, si la définition d'un élément du tableau sur null signifie quelque chose de spécial (par exemple lors de l'utilisation d'une chaîne de terminaison nulle dans), il peut être suffisant de définir le premier élément sur null. De cette façon, tout utilisateur du tableau comprendra qu'il est vide même si le tableau inclut toujours les anciens caractères en mémoire

Hhafez
la source
N'utilisez pas "memset" sur la lisibilité: stackoverflow.com/questions/453432/…
Johann Gerell
1

définissez le premier élément sur NULL. l'impression du tableau de caractères ne vous rendra rien.


la source
1

Que diriez-vous de ce qui suit:

bzero(my_custom_data,40);
codeconnundrum
la source
-3
void clearArray (char *input[]){
    *input = ' '; 
}
Loup
la source
1
Ce n'est pas EFFACER, il s'agit simplement de régler le premier caractère sur «»! Je pense que vous vouliez écrire * input = '\ 0'
stviper
-4

Essayez ce qui suit:

strcpy(my_custom_data,"");
Greg Grady
la source