2011-01-16 5 views
-1

Je sais que je ne devrais pas utiliser cette fonction, et je m'en fous. La dernière fois que j'ai vérifié la spécification pour strcat, il a dit quelque chose dans le sens de la mise à jour de la première valeur et du retour de la même chose. Maintenant, c'est une question vraiment stupide, et je veux que vous l'expliquiez comme si vous parliez à une personne vraiment stupide.Je ne peux pas comprendre strcat

Pourquoi cela ne fonctionnera-t-il pas?

char* foo="foo"; 
printf(strcat(foo,"bar")); 

EDIT: Je ne connais pas la différence entre char [] et char *. Comment allouer une chaîne de 255 caractères?

EDIT 2: OK, OK, alors char [nombre] alloue une chaîne de plusieurs octets? Logique. Merci.

EDIT 3: De même, comment utiliser un tableau de caractères sans le déclarer? Est-ce que je le classerais en tant que char [255]?

EDIT 4: strcat ((char [256]) "toto", "bar") renvoie une erreur. J'en ai marre de C.

EDIT 5: Tout comme strcat ((char [256]) "foo", (char []) "barre").

EDIT 5:

char[256] foo="bar"; 

réel lisse. "identificateur attendu"

+0

Il n'y a rien de mal * avec 'strcat'. Ce n'est pas sûr.Heureusement, celui qui vous a dit de ne pas l'utiliser au moins a eu la courtoisie de mentionner 'strncat', le cousin sûr de la mémoire de' strcat', qui assure que le tampon ne déborde pas. –

+0

Edit 3: vous ne pouvez pas. Vous utilisez soit un 'const char *' en lecture seule (inclut des littéraux de chaîne), soit vous déclarez une variable et l'allouez à l'avance, dynamiquement ('char * foo',' malloc', etc.) ou statiquement ('char foo [ 256] = "barre"; '). –

+0

Édition 4: vous ne pouvez pas faire ce typecast. Vous devriez avoir une erreur à l'effet de "cast spécifie le type de tableau". '(char *)', cependant, est autorisé. Pas que ça fasse quoi que ce soit. Si vous avez typé la chaîne littérale "foo", peu importe ce que vous avez lancé, les données restent les mêmes, et elles sont toujours en lecture seule. –

Répondre

0
char* foo="foo"; 

est un littéral de chaîne.

Il ne peut pas être modifié. Faites char [] foo = "foo"; place mais gardez à l'esprit que l'utilisation strcat comme ça, pose des problèmes dans ce cas, car il va écrire dans la mémoire, il ne doit pas en essayant de strcat « bar » donc vous devriez essayer quelque chose comme char foo[30] = "foo";

Modifier : Le typecasting que vous faites ... désolé, je n'ai pas autant de cellules cérébrales que pour essayer de vous expliquer ce que vous essayez de faire. Je peux seulement vous dire que c'est faux. besoin de pour fournir un emplacement de mémoire de sorte que strcat() peut fonctionner.

Essayez que:

int main() 
{ 
    char foo[255]="foo"; 
    printf("%s",strcat(foo,"bar")); 
} 
+0

Cela ne fonctionne pas non plus, cependant. Notez qu'il a fait 'strcat (foo, ...);'. Si la déclaration de foo est 'char foo [] =" foo ";' alors la mémoire tampon n'est pas assez grande pour y entrer. – asveikau

+0

Je ne comprends pas ce qu'est un littéral de chaîne. Une chaîne littérale est-elle une chaîne qui ne peut être étendue qu'à la première longueur à laquelle elle est affectée? Est-ce que char [] est une chaîne dynamique? –

+0

@asvei, je sais. J'y ai réfléchi après la première publication et j'ai modifié en conséquence. – Muggen

2

Vous avez besoin:

  • mémoire inscriptible
  • espace suffisant

constantes de chaîne ne fournissent que le montant exact de la mémoire dans le littéral et ils ne sont pas censés être écrits.

Au lieu de cela, faire:

char foo[255] = "foo"; 
+0

Est-ce que cela alloue une chaîne de 254 caractères? –

+1

@ Anonymous- Il alloue un tableau de 255 caractères, indexés de 0 à 254. Parce que les chaînes C doivent se terminer par un caractère nul final, cela vous donne de la place pour une chaîne de longueur 254. – templatetypedef

+0

D'accord. Qu'en est-il de la typographie? Puis-je utiliser strcat ((char [256]) "foo", "bar") ;? –

2

Quelques problèmes ...

1. foo est ici constante. Vous ne pouvez pas modifier les littéraux de chaîne.

2. Le contrat pour strcat est que le premier paramètre est assez grand pour s'adapter à la chaîne concaténée. Donc, plus réaliste que vous feriez quelque chose ... ce

char foo[8] = "foo"; /* Note that buffer size is larger than the string... */ 

strcat(foo, "bar"); 

3. Comme vous pouvez le deviner, il est pas évident pour un nouveau venu comment cela est censé fonctionner. Je dis qu'il y a une raison à cela: en général strcat est considéré comme plutôt mauvais. Une bonne interface C pour interagir avec des tampons de longueur potentiellement arbitraire rendra cela beaucoup plus explicite. Vous voudrez peut-être regarder strncat ou strlcat quelles tailles de piste.

Je dirais en général que si vous utilisez la famille strcat vous faites quelque chose de mal. Chaque appel à strcat devra traverser la chaîne pour trouver où se trouve la fin. Imaginez que vous faites beaucoup de ces opérations - il est très facile d'imaginer quelque chose qui peut facilement être fait en O (n) étapes devenant soudainement O (n) en raison de la traversée répétée de la chaîne. Si vous devez concaténer plusieurs fois une chaîne, vous devez conserver un pointeur sur la fin courante de la chaîne et faire la copie à partir de là.

Mise à jour: Exemple de la façon dont vous pourriez faire cette dernière suggestion ... suite

struct string 
{ 
    char *current_end; 
    size_t bytes_remaining; 
}; 

int 
smart_concat(struct string *str, const char *tail) 
{ 
    size_t new_length = strlen(tail); 

    /* Do we have enough space? (include NUL character) */ 
    if (new_length + 1 < str->bytes_remaining) 
    { 
     /* Evidently not... */ 
     return -1; 
    } 

    /* Copy the string... (including NUL character) */ 
    memcpy(str->current_end, tail, new_length + 1); 

    /* Update the pointer to the end of our string, and bytes remaining.. */ 
    str->current_end += new_length; 
    str->bytes_remaining -= new_length; 

    return 0; 
} 

Ensuite, vous pouvez l'utiliser comme suit:

struct string str; 
char buffer[some_size]; 

/* Initialize the structure to point at our buffer... */ 
str.current_end = buffer; 
str.bytes_remaining = sizeof(buffer); 

/* Strictly speaking, you should check the return code for overflow... */ 
smart_concat(&str, "foo"); 
smart_concat(&str, "bar"); 

/* Print out the result: */ 
puts(buffer); 
+1

+1 pour le dernier paragraphe. – Muggen

2

strcat est assez simple - il prend un pointeur vers un tampon contenant une chaîne et un pointeur vers une autre chaîne, et copie cette deuxième chaîne dans le tampon à la fin de la chaîne qui est déjà là.

Notez la différence entre les deux arguments. Les deux sont char *, mais le premier est vraiment un pointeur vers un tampon et seulement accessoirement un pointeur vers une chaîne (qui est déjà dans le tampon). En tant que tampon, il a besoin de deux choses qu'une simple chaîne ne compte pas:

  • il doit être inscriptible
  • il a besoin de suffisamment d'espace libre pour tenir la deuxième chaîne qui est copiée dans ce

Dans votre exemple, vous essayez d'utiliser char *foo="foo"; comme premier argument, mais c'est juste une chaîne et il manque les deux exigences pour le tampon. Au lieu de cela, vous devez faire quelque chose comme:

char foo[16] = "foo"; 
printf(strcat(foo, "bar")); 

Maintenant, nous déclarer foo comme un tableau inscriptible char avec beaucoup d'espace pour contenir les deux chaînes - un tampon adéquat. Cela entre dans le problème que la plupart des gens ont avec strcat, qui est la deuxième exigence ci-dessus - comment savez-vous si le tampon a assez d'espace? Dans un exemple simple comme celui-ci, il le fait, mais pour des exemples plus complexes (où vous ne savez pas nécessairement combien de temps les cordes sont), cela devient beaucoup plus difficile. Vous avez besoin de garder une trace de la taille de votre tampon, et utilisez strlen pour voir combien de temps les chaînes sont pour vous assurer qu'elles vont correspondre avant d'appeler Strcat. C'est à la fois inefficace (vous finissez par balayer des chaînes de caractères plusieurs fois pour trouver des longueurs et ensuite copier) et vous êtes sujet aux erreurs.

Questions connexes