Je dois écrire une fonction remplissant un tampon Char * pour une longueur assignée avec le contenu d'une chaîne. Si la corde est trop longue, je dois juste la couper. Le tampon n'est pas attribué par moi mais par l'utilisateur de ma fonction. J'ai essayé quelque chose comme ceci:
int writebuff(char* buffer, int length){
string text="123456789012345";
memcpy(buffer, text.c_str(),length);
//buffer[length]='\0';
return 1;
}
int main(){
char* buffer = new char[10];
writebuff(buffer,10);
cout << "After: "<<buffer<<endl;
}
10 Réponses :
Il devrait être le plus défiant *, cela empêche les cordes trop longues que le tampon du tampon de la remplit complètement et de faire déborder plus tard lorsque son accès. Bien que iMo, * Si vous avez déjà un doute, allez la route la plus sûre! P> strncpy code> doit être utilisé au lieu de Memcpy code>, mais vous devrez toujours le résilier NULL. (Votre exemple de votre exemple fuit). P>
Ma question concerne le terminateur: devrait-il être là ou non? p> blockQuote>
Oui. Ça devrait être là. Sinon, comment sauriez-vous plus tard où la chaîne se termine? Et comment
cout code> saurait-il savoir? Il continuerait à imprimer des ordures jusqu'à ce qu'il rencontre une poubelle dont la valeur se trouve\ 0 code>. Votre programme pourrait même s'écraser. P>comme Sidenote, votre programme fuit la mémoire. Cela ne libère pas la mémoire qu'il attribue. Mais puisque vous sortez du
principal () code>, cela n'a pas beaucoup d'importance; Après tout, une fois que le programme se termine, toute la mémoire reviendrait au système d'exploitation, que vous l'iez ou non. Mais sa bonne pratique en général, si vous n'oubliez pas vous-même la mémoire (ni toute autre ressource) vous-même. P>
Une chaîne de style C doit être terminée forte> avec un caractère zéro En plus, vous avez un autre problème avec votre code - cela peut essayer copier d'au-delà de la fin de votre chaîne source. C'est un comportement classique non défini. Il peut sembler que cela fonctionne, jusqu'à ce que la seule fois que la chaîne soit allouée à la fin d'un bloc de mémoire en tas et que la copie s'éteigne dans une zone de mémoire protégée et échoue de manière spectaculaire. Vous devez copier uniquement jusqu'au minimum em> de la longueur du tampon ou de la longueur de la chaîne. P> P.s. Pour une exhaustivité, voici une bonne version de votre fonction. Merci à Naveen pour indiquer l'erreur obsolète dans votre terminaison nul. J'ai pris la liberté d'utiliser votre valeur de retour pour indiquer la longueur de la chaîne renvoyée ou le nombre de caractères requis si la longueur passée était <= 0. p> '\ 0' code>.
Si vous devriez ou non mettre fin à la chaîne avec un note, cependant, que Le tampon \ 0 code> dépend de la spécification de votre weblebuff code> fonction. Si ce que vous avez dans tampon code> doit être une chaîne de style C valide après avoir appelé votre fonction, vous devez le terminer avec un \ 0 code>. P>.
c_str () code> se termine avec un \ 0 code> pour vous, donc vous pourrait em> utiliser . Taille () + 1 code> comme taille de la chaîne source. Notez également que si longueur code> est plus grand que la taille de la chaîne, vous copierez plus loin que ce que texte code> fournit avec votre code actuel (vous pouvez utiliser min (longueur - 2, Text.Size () + 1 / * Trailing \ 0 * /) Code> Pour éviter cela, et définir la mémoire tampon [longueur - 1] = 0 code> pour le captiver). < / p>
code> alloué dans Main code> est divulgué, BTW P>
Si vous souhaitez traiter le tampon comme une chaîne, vous devez le terminer null. Pour cela, vous devez copier longueur-1 code> caractères à l'aide de memcpy code> et définir le caractère longueur-1 code> comme \ 0 code> . P>
Inversement, si vous ne voulez pas traiter le tampon comme une chaîne, vous ne devez pas la résilier Nul.
Il est correct de copier longueur code> au lieu de longueur-1 code> caractères et à moitié évite un bogue lorsque vous passez une longueur de tampon de 0 code>.
Char * Les tampons doivent être résiliés NULL à moins que vous n'ayez expressément expressément la longueur avec elle partout et en disant que le tampon n'est pas terminé null. P>
Je suis d'accord avec Necrolis que Strncpy est la voie à suivre, mais il ne recevra pas le terminateur NULL si la chaîne est trop longue. Vous avez eu la bonne idée dans la mise en place d'un terminateur explicite, mais comme écrit votre code le pose un après la fin. (Ceci est en C, puisque vous sembliez faire plus de c que c ++?)
Tout d'abord, je ne sais pas si second, prenant votre exemple spécifique dans son ensemble, il y a deux problèmes. On est que vous transmettez une chaîne non définie à (troisième est une faille de conception - pouvez-vous savoir que code> code> est toujours inférieur à la longueur du texte code>? ) p> Essayez ceci: p> écrivainbuff code> devrait terminer la chaîne ou non. C'est une question de conception, à répondre par la personne qui a décidé que Writbuff code> devrait exister du tout. opérateur << (OStream, char *) code>. Deuxièmement, la ligne commentée écrit au-delà de la fin du tampon indiqué. Ces deux ont invoqué un comportement non défini. P>
Il semble que vous utilisiez C ++ - étant donné que, l'approche la plus simple est (en supposant que la résiliation NUL soit requise par la spécification d'interface)
int writebuff(char* buffer, int length)
{
string text = "123456789012345";
std::fill_n(buffer, length, 0); // reset the entire buffer
// use the built-in copy method from std::string, it will decide what's best.
text.copy(buffer, length);
// only over-write the last character if source is greater than length
if (length < text.size())
buffer[length-1] = 0;
return 1; // eh?
}
dans en C / C ++ Le contrat général avec des tampons de caractères est qu'ils soient résolus, donc je l'inclurais à moins d'avoir été explicitement dit de ne pas le faire. Et si je l'ai fait, je le commenterais, et peut-être même utiliser un paramètre typlef ou nom sur le paramètre principale () code>, vous devriez Supprimer code> le tampon que vous avez attribué avec neuf. code> ou l'affecte statiquement ( Char buf [10] code>). Oui, ce n'est que 10 octets et oui, c'est une mémoire "piscine", pas une fuite, car il s'agit d'une allocations ponctuelles et oui, vous avez besoin de cette mémoire pour toute la durée de fonctionnement du programme. Mais c'est toujours une bonne habitude d'être dans. P> li>
char * code> indiquant que le résultat est une chaîne qui n'est pas terminée null. P> li >
ol>
Si vous utilisez C ++ Strings, utilisez une chaîne plutôt que de char * et utilisez la copie plutôt que MemCy
Si vous essayez d'écrire un fichier source multilingue, vous devez rester à partir de "C ++ isms": no
std :: code>, nonouveau code>, non<<< / code> (Sauf peut-être peut-être si vous voulez dire que vous voulez dire Bitwise Shift), ...Writebuff code> devrait faire ce qu'il est annoncé de faire. Si l'appelant attend un terminateur, alorsWritBuff code> doit le fournir. Si l'appelant n'attend aucun terminateur, alorsWritBuff code> ne doit pas le fournir. Dans ce cas particulier, l'appelant attend clairement un terminateur (Opérateur << (ostream, char *) code> attend un terminateur).Donc, c'est essentiellement strlcpy (3) ou je manque quelque chose?