2010-12-15 106 views
1

Je suis préoccupé par les débordements de buffer, et j'ai besoin de sortir certains caractères d'une classe dérivée de std :: istream. D'après ce que je comprends, il n'y a aucun moyen de diffuser vers une chaîne std :: directement à partir d'un istream, sans mon propre opérateur. J'ai donc envisagé de diffuser le contenu dans un tableau char, puis de le mettre dans une chaîne std :: string. Voici un exemple simple:Le moyen le plus sûr d'extraire du flux vers le tableau char ou std :: string

char CharArray[1000] = {0}; 
SomeIStream >> CharArray; 
std::string StuffFromStream(CharArray); 

Cependant, il semble qu'il n'y ait aucun moyen de savoir que CharArray ne sera pas débordé. Y a-t-il un maximum que l'opérateur d'extraction de flux écrira à chararray? Y at-il un moyen de vérifier combien sera extrait de façon préventive? Est-ce que tout est faux, y a-t-il un moyen qui soit beaucoup mieux que cela?

Édition1 :, J'ai corrigé ma fuite de mémoire. Pas besoin d'appeler supprimer. Je ne peux pas croire que je l'ai fait. Edit2: La suggestion d'utiliser le >> directement dans la chaîne a été suggérée. J'ai tenté cette précédente dans la base de code ce problème est venu et il a échoué. Dire qu'aucune correspondance appropriée pour l'opérateur n'a pu être trouvée. J'ai alors essayé avec un std :: fstream et il a échoué encore. Essayer le code std :: fstream dans un projet minimaliste simple a réussi. Cela me dit que quelque chose d'autre ne va pas avec mon plus gros projet. L'intention originale de cette question n'est plus valide.

Édition3: J'ai résolu ce problème. J'ai essayé de streamer vers une typedef String, que je pensais être en fait et std :: string, mais c'était vraiment une const std :: String. Naturellement, il n'y a pas d'opérateur d'extraction de flux pour écrire sur un objet non-inscriptible, donc cela m'a donné tous les opérateurs listés dans l'en-tête istream (celui dont j'avais besoin était dans l'entête de la chaîne).

Merci aux personnes qui ont souligné ma recherche défectueuse et pointe dans la bonne direction.

Répondre

3

Si vous avez hérité (correctement) de std :: istream, vous n'avez rien à faire de particulier et vous pouvez simplement utiliser operator >> (std::istream&, std::string&).

std::string s; 
SomeIStream >> s; 

Lorsque je dis «correctement», je veux dire que les fonctions virtuelles appropriées d'istream sont remplacées. "Je sais que s'il y a une exception avant la suppression, cela entraînera une fuite de mémoire." Non, ça ne va pas. Vous n'avez pas alloué CharArray avec new; appeler le delete ne fera pas ce que vous voulez.

+0

J'ai essayé cela, exactement, mais mon compilateur a précisé qu'il n'y avait pas une telle surcharge d'opérateur définie. Je vais vérifier et voir si c'est juste ce problème d'implémentations de flux, ou si tout est istreams. – Sqeaky

+0

J'ai testé cela en utilisant et std :: fstream et il a échoué. Cependant, la lecture en utilisant std :: fstream :: read dans un tableau char, puis passer dans une chaîne a travaillé. J'ai lu ceci et il n'y avait pas là http://www.cplusplus.com/reference/iostream/istream/operator%3E%3E/ mais c'est par ici: http://www.cplusplus.com/reference/string/opérateur% 3E% 3E /. Je me demande pourquoi il n'est pas trouvé par mon test avec le fstream ou quand j'ai essayé avec la classe originale dérivée d'istream. – Sqeaky

0

Mélange-t-on des réseaux de chars de type C à l'ancienne avec des cours d'eau? On dirait un code très confus.

Commentaire mis à part, il suffit d'extraire directement à une chaîne. Vous pouvez transmettre cela (via la méthode c_str()) aux API de style C qui attendent const char* paramètres. Et si pour une raison bizarre vous faites vraiment un tableau char, vous pouvez copy du string au tableau de caractères en toute sécurité, après avoir vérifié les limites. Par ailleurs, vous avez clairement illustré la façon principale dont magic numbers are evil. Dans votre cas, le nombre magique en question est 1000. Vous n'avez aucune idée que 1000 est approprié - pas trop grand, pas trop petit - sans totalement deviner. En programmation, deviner souvent == s'écraser. Ou pire encore, ne pas s'écraser. Par la voie 2, vous êtes delete en utilisant une variable automatique ci-dessus. Tu ne fais pas ça. Utilisez delete si et seulement si vous utilisez new. Vous n'avez pas new, alors ne le faites pas delete.

Par ailleurs 3, si vous voulez juste extraire le flux entier dans une chaîne, vous pouvez simplement faire ceci:

string s = SomeIStream.str(); 
+0

Tous les flux n'ont pas de .str(). – Sqeaky

0

Tous les cours d'eau offrent la méthode .str(), qui fournira une copie de leur tampon en tant que std :: string (ou wstring ou autre pour les autres typedefs).

De même, vous avez déclaré un tableau sur la pile et avez ensuite tenté de le supprimer, ce qui correspond à UB.

+4

Seules les chaînes et les stringbufs ont des membres str(). –

0

Si vous voulez lire le flux entier dans une chaîne, ce n'est pas très efficace, mais elle est sûre:

std::string str((std::istream_iterator<char>(some_istream)), std::istream_iterator<char>()); 

(notez la parenthèse supplémentaire, pour éviter le plus vexant-parse)

Si vous voulez lire jusqu'à caractères « n »:

some_istream.read(some_char_array, sizeof(some_char_array)); 

Notez que ce ne sera pas nul fin du tableau. Passez le sizeof(char_array) - 1 à la place si vous souhaitez laisser intacte le dernier caractère de la matrice.

0

C'est ce que mon approche est généralement (de « Penser en C++ » par Bruce Eckel) ::

 
ifstream in("somefile.txt",ios::in); 
istreambuf_iterator istr(in),end; 
string str; 
insert_iterator ins(str,str.begin()); 

while(istr != end){ 
     *ins++ = *istr++; 
} 

Dans le code ci-dessus le fichier entier est pris comme un flux de caractères puis mettre dans une chaîne. Ceci est montré juste comme un exemple.