Narzędzia użytkownika

Narzędzia witryny


strumienie_napisowe_sstream

Strumienie napisowe <sstream>

Wstęp

Strumienie napisowe ( stringstream ) są zestawem trzech klas, które umożliwiają wykonywanie operacji na napisach ( string ) tak, jakby były one strumieniami. Takie rozwiązanie bardzo ułatwia manipulację napisami, co w szczególności oznacza że można używać operatorów strumieniowych « i » do konwertowania różnych typów obiektów na napisy i odwrotnie. Dane zapisane w strumieniu napisowym są przechowywane przez wewnętrzny obiekt klasy stringbuf, który jest w miarę potrzeb automatycznie powiększany.

Główne zastosowania strumieni napisowych to:

  • Formatowanie napisów
  • Parsowanie napisów
  • Konwersja napisów na inne typy

Konstrukcja

Nagłówek sstream dostarcza deklaracje trzech klas strumieni napisowych:

  • ostringstream - strumień dziedziczący po ostream, umożliwiający jedynie zapis
  • istringstream - strumień dziedziczący po istream, umożliwiający jedynie odczyt
  • stringstream - strumień dziedziczący po iostream, umożliwiający zarówno zapis jak i odczyt

Konstruktory tych klas są niemal identyczne i pobierają referencję na napis, którego zawartość zostanie skopiowana jako początkowa zawartość strumienia oraz tryb w jakim strumień będzie otwarty. Dzięki zastosowaniu parametrów domyślnych można tworzyć obiekty strumieni napisowych zmieniając tylko ważne dla programisty parametry lub nie podając ich wcale.

//konstruktory klasy stringstream 
explicit stringstream ( openmode which = ios_base::out|ios_base::in );
explicit stringstream ( const string & str, openmode which = ios_base::out|ios_base::in );
 
//konstruktory klasy ostringstream 
explicit ostringstream ( openmode which = ios_base::out );
explicit ostringstream ( const string & str, openmode which = ios_base::out );
 
//konstruktory klasy istringstream 
explicit istringstream ( openmode which = ios_base::in );
explicit istringstream ( const string & str, openmode which = ios_base::in );

Szerokie znaki

Biblioteka sstream dostarcza także definicji strumieni napisowych dla szerokich znaków, odpowiednio:

  • wostringstream
  • wistringstream
  • wstringstream

Metody publiczne

rdbuf

stringbuf* rdbuf ( ) const;

Funkcja zwraca wsaźnik na obiekt stringbuf w którym strumień przechowywuje dane.

str

string str ( ) const;
void str ( const string & s );

Pierwsza wersja fukcji zwraca kopię napisu przechowywanego w strumieniu. Druga wersja pobiera referencję na obiekt napisu, który zostanie skopoiwany do bufora strumienia. Funkcja ta nie czyści flag ustawionych w strumieniu.

Metody odziedziczone

Strumienie napisowe dziedziczą po klasach strumieni biblioteki iostream i udostępniają wszystkie metody standardowych strumieni. Dokładny opis wszystkich funkcji można znaleźć w bibliografii poniżej.

Formatowanie napisów

Interfejs klasy string nie udostępnia operacji do formatowania napisów przez co ciężko łączy się ciągi znaków z liczbami i innymi danymi. Na szczęście do tworzenia sformatowanych ciągów znaków można użyć strumieni napisowych, wykorzystując wszystkie mechanizmy formatowania znane ze strumieni.

	string some_string = "some_string";
 
	// C style
	/* 
	char buffer[BUFFER_SIZE];
	sprintf(buffer, "this is some text with integers %d, floats %f, hexes %x and strings %s\n", 
			9, 
			5.34,
			0xF6,
			some_string.c_str());
	*/
 
	// create string containing some text with integers, floats and strings
	ostringstream osstream;
	osstream	<< "this is some text with integers " 
			<< 9 
			<< ", floats " 
			<< 5.34 
			<< ", hexes " << hex << 0xF6
			<< " and strings " 
			<< some_string << endl;
 
	// print results
	cout << osstream.str();

Parsowanie napisów

Podobnie strumieni napisowych można w wygodny sposób używać do wczytywania danych z ciągów znaków.

        string	some_string;
	int	some_number;
	float	some_float;
 
	// C style
	/* 
	char buffer[BUFFER_SIZE]; // contents: "some_text 9 5.56"
	sscanf(buffer, "%s %d %f", some_buffer, &some_nuber, &some_float);
 
	*/
 
	// parse text containing string, integer and float
	istringstream isstream("some_text 9 5.56");
	isstream >> some_string >> some_number >> some_float;
 
	if(isstream.fail())
	{
		// handle errors
		cout << "Error in parsing" << endl;
	}
	else
	{
		// print results
		cout	<< "Parsed items: " << endl 
			<< some_string	    << endl 
			<< some_number	    << endl 
			<< some_float	    << endl;
	}

Konwertowanie napisów

Strumieni napisów można także używać do konwersji w obydwie strony napisów i dowolnych innych typów.

// C style
/*
some_number = atoi(buffer); // no error handling since 0 is valid integer
*/
 
// convert string to int with error handling and print it
int some_number;
istringstream isstream("123");
isstream >> some_number;
 
if(isstream.fail())
{
	// handle errors
	cout << "Error while converting string to int" << endl;
}
else
{
	// print results
	cout << "Converted string to integer: " << some_number << endl;
}
 
// convert int to string and print it
ostringstream osstream;
osstream << 9;
cout << "Converted integer to string: "<< osstream.str() << endl;

Takie podejście umożliwia wykrywanie błędów konwersji, jednak wymaga napisania dużej ilości kodu. Z tego powodu do konwertowania napisów zaleca się używanie klasy boost::lexical_cast, która opakowywuje strumienie napisowe i pozwala drastycznie skrócić powyższy zapis.

try
{
	int some_number = lexical_cast<int>(some_string);
}
catch(bad_lexical_cast &)
{
	// handle error
}

Stringstream kontra Strstream

W bibliotece standardowej istnieje także rodzina klas strstream, która funkcjonalnością przypomina omawianą rodzinę stringstream, jednakże są to klasy przestarzałe i nie powinny być używane. Klasy stringstream są nową wersją strumieni napisowych, zgodną z obcenym standardem języka c++ i wolną od błędów projektowych klas strstream.

Przykładowy program

Bibliografia

strumienie_napisowe_sstream.txt · ostatnio zmienione: 2009/04/29 07:54 przez adrian.wisniewski