Quelles sont les spécificités de la définition d'une chaîne en C?

10

Je suis censé répondre à une question de devoirs pour l'un de mes cours. Plus précisément, je suis censé dire si certains tableaux en C sont considérés comme des chaînes ou non. Sur la base de cet article ( https://www.geeksforgeeks.org/strings-in-c-2/ ), je sais que les chaînes sont un tableau de caractères avec le terminateur nul à la fin.

Mon principal blocage est une partie de la question qui pose un tableau qui ressemble à ceci:

char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };

Il s'agit évidemment d'un tableau de caractères avec un caractère de fin nul à la fin. Cependant, est-elle toujours considérée comme une chaîne car elle a également un caractère de fin nul au milieu? Comment cela affectera-t-il la chaîne?

EDIT: Sur la base des commentaires, j'ai fourni le libellé réel de la question:

"Lequel des tableaux suivants peut être considéré comme des" chaînes "dans le but de les utiliser comme arguments pour strcpy (), strncpy (), strcmp (), strncmp () et des fonctions de chaîne similaires (indiquer toutes les applications)?"

EDIT: J'ai envoyé un courriel à mon professeur à ce sujet car la question semblait libellée de manière ambiguë (comme plusieurs personnes l'ont souligné). Si quelqu'un est curieux, il m'a dit "Oui, c'est une chaîne. La clé est qu'il y a un caractère nul. Mais bien sûr, cela affectera toutes les opérations de chaîne; la chaîne se termine au caractère nul."

quango
la source
4
Vous pourriez dire que c'est la chaîne "CS"avec quelques octets de déchets ajoutés (auquel cas le caractère NUL final n'est pas pertinent). Mais ce n'est pas une chaîne "dans son ensemble". - Néanmoins, le nourrir, strcpyetc. ne fera pas exploser votre PC car ces fonctions ne "verront" que la "CS"pièce.
Hagen von Eitzen
2
c1 peut absolument être utilisé comme argument pour strcmp(). Le fait qu'il puisse être utilisé comme argument pour muter des fonctions de chaîne dépend de facteurs supplémentaires qui ne sont pas fournis.
EOF
2
Le contenu de c1est modifiable, donc je ne vois pas pourquoi il ne serait pas un argument de destination valide pour strcpyou similaire, sauf s'il n'était pas assez grand pour accueillir la chaîne source. Cela ne ferait pas que ce ne soit pas une chaîne, mais pas une chaîne adaptée à un objectif donné.
John Bollinger
1
Dans l'ensemble, je conviens que la question est formulée de manière ambiguë. L'expression c1satisferait les exigences de base pour les arguments de chaîne pour toutes les fonctions de chaîne (étroites) de la bibliothèque standard, y compris toutes celles spécifiquement nommées, mais le comportement pourrait ne pas être ce que l'appelant attend ou veut (même en ignorant les comportements indéfinis qui pourraient être obtenus).
John Bollinger
1
Notez que le type n'a pas besoin d'être char. N'importe quel type de caractère fera l'affaire.
chux

Réponses:

8

c1est la plupart du temps [1] équivalente à &c1[0], qui tient une chaîne "CS".

Il y a une deuxième chaîne qui se cache là - dedans, "324", à partir de &c1[3]- mais aussi longtemps que vous accédez c1comme c1, la chaîne "CS"est toutes les fonctions strcpy()et al. verrait.


[1]: c1est un tableau, &c1[0]est un pointeur.

DevSolar
la source
Alors, est-il approprié d'utiliser c1comme chaîne cible dans une strcpy()commande? La question est ambiguë - au mieux.
Andrew Henle
1
Bien sûr, vous pouvez utiliser c1comme argument pour strcpy(). C'est une corde parfaitement ordinaire dans tous les sens. Les chaînes ordinaires contiennent souvent des déchets résiduels après leurs terminateurs. Le fait que ces ordures soient codées en dur dans le programme donne l'impression que l'auteur a l'intention d'utiliser c1de manière non chaîne, mais cela ne faisait pas partie de la question.
Lee Daniel Crocker
" c1équivaut à &c1[0]" induit en erreur. c1est un tableau. &c1[0]est un pointeur.
chux
2

Si vous voulez connaître les spécificités de la définition d'une chaîne en C, allez à la source.

De la norme C90 :

7 Bibliothèque

7.1 Introduction

7.1.1 Définitions des termes
Une chaîne est une séquence contiguë de caractères se terminant par et incluant le premier caractère nul. Un «pointeur vers» une chaîne est un pointeur sur son caractère initial (adressé le plus bas). La «longueur» d'une chaîne est le nombre de caractères précédant le caractère nul et sa «valeur» est la séquence des valeurs des caractères contenus, dans l'ordre.

(Il n'y a eu aucun changement pertinent dans les normes ultérieures.)

Ainsi, c1contient deux chaînes consécutives, "CS" et "324", mais n'est pas lui-même une chaîne.

Si nous passons un tableau à une fonction, il se désintègre en un pointeur sur son premier élément, +c1pointe donc sur une chaîne (le premier), ce qui est assez bon pour toute fonction qui attend un pointeur sur une chaîne. Il ne pointe pas vers une chaîne "CS \ 0324", mais c'est probablement suffisant pour la question de vos instructeurs, ce qui est ambigu.

Déduplicateur
la source
4
Je dirais que même selon cette définition, c1 est clairement la chaîne "CS". Période. Le fait qu'il puisse contenir des octets non nuls après le terminateur n'est pas pertinent - de nombreuses chaînes seront comme ça au cours de leur vie.
Lee Daniel Crocker
+c1pointe sur une chaîne, car c1commence par une chaîne. Cela ne fait en aucun cas, forme ou forme c1une chaîne.
Déduplicateur
2
C'est l'adresse d'une section de mémoire qui contient des caractères terminés par un octet zéro. Si printf () convenait très bien avec un% s, cela donnerait un nombre parfaitement bon passé à strlen (), fonctionnerait s'il était passé à strcpy (), etc. Sonne comme une chaîne pour moi.
Lee Daniel Crocker
Bien sûr. Mais les tableaux peuvent certainement être des chaînes.
Lee Daniel Crocker
0

Ajout à la réponse de @ DevSolar, quelque chose que j'ai découvert après avoir joué avec la chaîne donnée, si elle devait être:

char c1[] = { 'C', 'S', '\\0', '3', '2', '4', '\\0' };

Si vous produisez cette chaîne, vous obtiendrez CS03240et la taille de cette chaîne est de 7. Pour autant que je sache, \\0est utilisé pour désigner le caractère nul ( ie \0 ). Si tu fais:

printf("\0");

Vous ne voyez rien dans le journal de sortie, mais si vous le faites:

printf("\\0");

Vous voyez un \0, quelque chose qui est attendu car pour générer des caractères spéciaux tels que des barres obliques inverses ou des guillemets, vous devez utiliser un \avec eux.

Quelque chose qui me laisse perplexe est la sortie CS03240et sa taille 7. Il est communément admis que la taille d'une chaîne est le nombre de caractères qu'elle contient plus un (pour le caractère nul). En outre, la taille est 7 même pour la chaîne, char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };.

Alors peut-être une suite à cette question, que se passe-t-il ici?

rasengan__
la source
1
'\\0'n'est pas un caractère nul . C'est une constante à plusieurs caractères. Il a une valeur définie de mise en œuvre certainement hors de la plage de char. c1[]n'est pas une chaîne car il lui manque un caractère nul . "vous sortez cette chaîne" entraîne probablement un comportement indéfini .
chux
Je ne vous ai pas exactement compris, bien que j'ai recherché des constantes multi-caractères. Si c1 [] n'est pas une chaîne car il n'a pas de caractère nul à la fin, alors pourquoi la taille ressort-elle à 7 dans le cas initial tel que publié par l'OP?
rasengan__
char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };est de taille 7 car il est initialisé avec 7 valeurs. Sa taille n'a rien à voir avec les cordes . char c1[] = { 1, 2, 3, 4, 5, 6, 7 };ferait encore la taille 7.
chux - Réinstalle Monica
Quant au tableau c1contient-il une piqûre? C'est une question distincte. Voir aussi
chux