9
votes

Copier le contenu de std :: vecteur dans un tampon de char *?

J'ai un std :: vecteur. Je veux copier le contenu de la vecteur dans un tampon de char * d'une certaine taille.

Y a-t-il un moyen sûr de faire cela? P>

Puis-je faire cela? P>

for (int i = 0; i < _v.size(); i++)
{
  *buffer = _v[i];
  buffer++;
}


12 commentaires

Mon C ++ - Fu est un peu rouillé, mais ne serait-il pas char * str = & _v [0]; faire le travail?


@Polynomial probablement, au moins au début. Si le vecteur réaffecte jamais sa mémoire tampon, l'emplacement peut changer et si le vecteur est détruit, le pointeur est invalide. C'est assez risqué que ce ne soit probablement pas une idée bonne .


@Polynomial: Cela ne copiera pas le vecteur dans un tampon différent, il suffira de saisir l'adresse du tampon interne dans le vecteur.


@Polynomial: Cela fonctionnera parfaitement pour le moment et même être beaucoup plus rapide, cependant, il va briser le moment où vous ajoutez des données au vecteur et dépassera sa capacité. A cette époque, cela allouera un nouveau bloc et libérera celui que vous pointez.


La vraie question est la suivante: pourquoi voulez-vous utiliser un tampon char * ? std :: vecteur est beaucoup mieux dans (presque) à tous égards.


Merci pour les réponses. Je n'ai pas tendance à traiter beaucoup de C ou C ++ ces jours-ci, donc je n'avais donc pas examiné les problèmes de réaffectation. Je suppose que & _ v [0] est toujours utile, cependant. Il peut être agréable pour les cas où vous voulez simplement effectuer une opération rapide sur un std :: vecteur où votre fonction ne prend que char * , et vous n'êtes pas inquiet de conditions de course. Néanmoins, la meilleure pratique est une copie appropriée.


@krebstar: quel avertissement obtenez-vous? Un pointeur est un modèle de Randumiterator qui comprend les exigences relatives à un "code> Overattiterator , donc un pointeur est certainement valide pour le 3ème argument de std :: copie . Pourriez-vous nous montrer le texte de l'avertissement?


@Matthieuum. Je reçois cet avertissement: AVERTISSEMENT C4996: 'std :: Copy': Appel de fonction avec des paramètres pouvant être dangereux - Cet appel s'appuie sur l'appelant pour vérifier que les valeurs transmises sont correctes. Pour désactiver cet avertissement, utilisez -d_scl_secure_no_warnings. Voir la documentation sur la façon d'utiliser Visual C ++ 'Itérateurs vérifiés'


@krebstar: Ah d'accord. AVERTISSEMENTS IN / W4 (IE avec et ID Supérieur à 4000) sont plus souvent que pas simplement du bruit. Comme vous pouvez le lire, cela vous avertit que c'est votre responsabilité pour vous assurer que le tampon de destination est suffisamment grand, car l'utilisation d'un pointeur nu au lieu d'un type plus avancé empêche VC ++ pour insérer le code de débogage pour vérifier Pour toi. Je conseillerais seulement d'aller à / w3 si vous ne voulez pas être noyer.


La réponse à cela dépend de ce que vous voulez faire avec le tampon Char *. S'il vous plaît élaborer.


@Polynomial non, pas vraiment. Le problème est que le terme "tampon char *" est trompeur: un char * n'est pas un tampon. C'est un pointeur sur le tampon. Votre code dit "Point sur le tampon interne utilisé par le std :: vecteur instance". L'effet prévu est "Copier les données dans le tampon qui est en cours de pointe".


@Karlknechtel désolé je suppose que j'aurais dû dire "tampon de charme" pointé par un char *.


5 Réponses :


0
votes

Eh bien, vous voulez attribuer à * tampon pour le cas 3, mais cela devrait fonctionner. Le premier ne fonctionnera presque certainement pas.

Edit: Je suis corrigé concernant # 2.


1 commentaires

Quoi qu'il en soit, n'y a-t-il pas plus vite de faire cela? faire une boucle pour / tandis que la boucle semble bizarre .. = /



22
votes
std::copy(_v.begin(), _v.end(), buffer);
This is preferred way to do this in C++. It is safe to copy this way if buffer is large enough.

18 commentaires

Ce n'est pas suffisant: vous devriez ajouter un caractère \ 0 à la fin.


@Nawaz, mais il est raisonnable de supposer qu'ils peuvent être traités comme tels. Ne pas faire, il suffit de demander des ennuis.


@Adamzalcman: Ce n'est pas raisonnable. Et si le vecteur contient plusieurs \ 0 ?


@Adamzalcman: De plus, si cela est raisonnable, le choix initial de std :: vecteur est faux de commencer, comme std :: string serait un meilleur Choix au cas où si Char * doit être traité avec C-String.


@Nawaz Vector Maintient des informations sur la taille tandis que Char * ne le fait pas. Il ne serait pas sage de fonctionner sur une telle séquence de caractères à l'aide de Char * en premier lieu. Char * est plus qu'un simple pointeur: il a une sémantique impliquée d'une c-string.


@Adamzalcman: _v peut déjà contenir \ 0 à la fin - alors pas besoin d'ajouter plus \ 0


@Adamzalcman: Comme je l'ai dit, dans ce cas std :: string serait un meilleur choix, vous pouvez ajouter \ 0 à la fin lorsque vous en effectuez une copie, et le stocker dans char * .


Nawas a raison, le char * je travaille avec plusieurs \ 0s .. Ce n'est pas une chaîne de caractères dans la sens du mot C.


Ma question est, est la vectorielle garantie d'être un bloc de mémoire contigu? Y a-t-il un moyen de faire cela qui ne donne pas d'avertissements? Peut-être une fonction STD :: copy_s ()?


@Adamzalcman: Non. Je ne pense pas que c'est une réponse bâclée. Quand je vois std :: vecteur au lieu de std :: string , je suppose que la teneur en vecteur n'est pas garantie d'être c-string.


@krebstar: Oui. vecteur est garanti d'être un bloc de mémoire contigu ?.


@ADAM: Il y a trop de choses que nous supposons en répondant à la question. Par exemple, dans votre réponse, vous avez supposé que la mémoire allouée sera traitée avec Supprimer . Mais vous n'avez pas State que, n'est-ce pas? (moi non plus)


@Nawaz Votre hypothèse sur le manque de besoin d'un terminal NULL est directement liée au code que vous avez écrit. Espérons que le lecteur sera averti par cette discussion qui a devenu beaucoup trop longtemps pour un problème trivial comme Null-terminal.


@Adamzalcman: Le problème avec votre ligne de pensée est que lorsque vous voyez char * , c'est vous qui suppose qu'il s'agisse de c-string. Mais quand je vois char * , je ne vois que char * . Aucune hypothèse. Comme je l'ai dit, char * ne signifie pas nécessairement que c-string.


@Nawaz vous manquez le point: je sais char * peut être une chaîne C. Le point est que le lecteur du code et la réponse peuvent facilement être induits en erreur (en raison de l'utilisation extrêmement fréquente de char * pour faire référence aux chaînes C).


Si vous voulez avoir une discussion sur la façon dont la plupart des gens ont interprété char * , veuillez le déplacer pour discuter.


Notez que dans Visual C, à l'aide de STD :: Copy (Copy () Comme suggéré ci-dessus entraînera probablement un avertissement C4996


Pour régler le différend ci-dessus, je vais souligner que j'ai trouvé cette réponse lorsque vous recherchez des conseils sur la manière de gérer les données arbitraires lisez à partir d'une prise réseau, qui se trouve sous la forme d'un std :: vecteur Tampon mais doit être copié dans un tampon de char * .



11
votes

Si vous avez juste besoin de char * code>, vous pouvez le faire:

auto copy = v; // that's simpler way to make copies!!
// and then use copy as new buffer.
// no need to manually delete anything. :-)


0 commentaires

4
votes

le moyen le plus sûr de copier un vecteur code> dans un tampon code> char * code> est de le copier sur un autre vecteur, puis utilisez le tampon interne de ce vecteur:

std::vector<char> copy = _v;
char * buffer = &copy[0];


2 commentaires

C'est presque meilleur. Je ne pensais pas comme ça. +1.


Busticalement: méfiez-vous d'un tel cas: Char * tampon; {std :: vecteur copie = _v; tampon = & copie [0];} cout << tampon;



0
votes
auto vec = read_binary_file(filename);
auto src = (char*) new char[vec.size()];
std::copy(vec.begin(), vec.end(), src);

0 commentaires