15.5. Les flux d'entrée / sortie sur chaînes de caractères

Afin de donner la possibilité aux programmeurs d'effectuer les opérations de formatage des données en mémoire aussi simplement qu'avec les classes de gestion des flux d'entrée / sortie standards, la bibliothèque d'entrée / sortie définit trois classes de flux capables de travailler dans des chaînes de caractères de type basic_string. Ces classes sont les classes basic_ostringstream, pour les écritures dans les chaînes de caractères, basic_istringstream, pour les lectures de données stockées dans les chaînes de caractères, et basic_stringstream, pour les opérations à la fois d'écriture et de lecture.

Ces classes dérivent respectivement des classes de flux basic_istream, basic_ostream et basic_iostream et reprennent donc à leur compte toutes les fonctions de formatage et d'écriture de ces classes. Les écritures et les lectures de données en mémoire se font donc, grâce à ces classes, aussi facilement qu'avec les flux d'entrée / sortie standards, et ce de manière complètement transparente.

En fait, les classes de flux orientées chaînes de caractères fonctionnent exactement comme leurs classes de base, car toutes les fonctionnalités de gestion des chaînes de caractères sont encapsulées au niveau des classes de gestion des tampons qui ont été présentées au début de ce chapitre. Cependant, elles disposent de méthodes spécifiques qui permettent de manipuler les chaînes de caractères sur lesquelles elles travaillent. Par exemple, la classe basic_ostringstream est déclarée comme suit dans l'en-tête sstream :

template <class charT,
    class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
class basic_ostringstream : public basic_ostream<charT, traits>
{
public:
// Les types de données :
    typedef charT            char_type;
    typedef typename traits::int_type int_type;
    typedef typename traits::pos_type pos_type;
    typedef typename traits::off_type off_type;

// Les constructeurs et destructeurs :
    explicit basic_ostringstream(ios_base::openmode mode = ios_base::out);
    explicit basic_ostringstream(
        const basic_string<charT, traits, Allocator> &chaine,
        ios_base::openmode mode = ios_base::out);
    virtual ~basic_ostringstream();

// Les méthodes de gestion de la chaîne de caractères :
    basic_stringbuf<charT, traits, Allocator> *rdbuf() const;
    basic_string<charT, traits, Allocator> str() const;
    void    str(const basic_string<charT, traits, Allocator> &chaine);
};
Les classes basic_istringstream et basic_stringstream sont déclarées de manière identique, à ceci près que les classes de base et les valeurs par défaut pour les modes d'ouverture du tampon sur la chaîne de caractères ne sont pas les mêmes.

Comme vous pouvez le constater, il est possible de construire un flux d'entrée / sortie sur une chaîne de caractères de différentes manières. La première méthode est de construire un objet flux, puis de préciser, pour les flux d'entrée, la chaîne de caractères dans laquelle les données à lire se trouvent à l'aide de la méthode str. La deuxième méthode est tout simplement de fournir tous les paramètres en une seule fois au constructeur. En général, les valeurs par défaut spécifiées dans les constructeurs correspondent à ce que l'on veut faire avec les flux, ce qui fait que la construction de ces flux est extrêmement simple.

Une fois construit, il est possible de réaliser toutes les opérations que l'on désire sur le flux. Dans le cas des flux d'entrée, il est nécessaire que le flux ait été initialisé avec une chaîne de caractères contenant les données à lire, et l'on ne cherche généralement pas à récupérer cette chaîne après usage du flux. Pour les flux de sortie, cette initialisation est inutile. En revanche, le résultat des opérations de formatage sera généralement récupéré à l'aide de la méthode str une fois celles-ci réalisées.

Exemple 15-9. Utilisation de flux d'entrée / sortie sur chaînes de caractères

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main(void)
{
    // Lit une ligne en entrée :
    cout << "Entier Réel Chaîne : ";
    string input;
    getline(cin, input);
    // Interprète la ligne lue :
    istringstream is(input);
    int i;
    double d;
    string s;
    is >> i >> d;
    is >> ws;
    getline(is, s);
    // Formate la réponse :
    ostringstream os;
    os << "La réponse est : " << endl;
    os << s << " " << 2*i << " " << 2*d << endl;
    // Affiche la chaîne de la réponse :
    cout << os.str();
    return 0;
}

Comme l'exemple précédent vous le montre, l'utilisation des flux d'entrée / sortie de la bibliothèque standard sur les chaînes de caractères est réellement aisée. Comme ces opérations ne peuvent être réalisées qu'en mémoire, c'est à dire en dehors du contexte du système d'exploitation utilisé, les classes de flux de la bibliothèque restent utiles même si les opérations d'entrée / sortie du système se font de telle manière que les objets cin et cout ne sont pratiquement pas utilisables.