Składnia
#include <iomanip>
namespace std
{
template < template CharT >
quoted( const CharT * s, CharT delim = CharT( '"' ), CharT escape = CharT( '\\' ) );
template < template CharT, template Traits, template Allocator >
quoted( const std::basic_string < CharT, Traits, Allocator >& s, CharT delim = CharT( '"' ), CharT escape = CharT( '\\' ) );
template < template CharT, template Traits, template Allocator >
quoted( std::basic_string < CharT, Traits, Allocator >& s, CharT delim = CharT( '"' ), CharT escape = CharT( '\\' ) );
}
Parametry szablonu
Argumenty
Zwracana wartość
Nie jest wyspecyfikowana w standardzie wartość zwracana, natomiast np. gcc implementuję funkcje jako zwracającą obiekt tymczasowy posiadający operatory strumienia
std::basic_ostream
i
std::basic_istream
Opis szczegółowy
Manipulator standardowych strumieni wejścia/wyjścia służący do umieszczania i wyjmowania tekstu z cytatu. Innymi słowy manipulator zadany tekst umieszcza w odpowiednie znaki separatora (domyślnie
") na początku oraz na końcu tekstu, jednocześnie poprzedzając te znaki separatora odpowiednim znakiem ucieczki (domyślnie
\ ).
Działanie std::quoted()
Umieszczanie tekstu wewnątrz cytatu
W tej sytuacji zachowanie manipulatora jest zgodnie z konceptem
FormattedOutputFunction
.
Zachowanie szczegółowo wygląda tak:
Wyjmowanie tekstu z cytatu
Jeśli pierwszy znak nie jest równy
delim
to zwyczajnie tekst jest drukowany bez zmian.
W przeciwnym razie
Dodatkowe informacje
W standardzie C++17 jest przewidziana dodatkowe przeciążenie tego manipulatora:
template < typename CharT, typename Traits >
quoted( std::basic_string_view < CharT, Traits > s, CharT delim = CharT( '"' ), CharT escape = CharT( '\\' ) );
Rzucane wyjątki
W razie błędu funkcji
operator >>()
i
operator <<()
zostaje wyrzucony:
std::ios_base::failure
.
Implementacja
Implementacja zainspirowana przez tą dostarczoną do kompilatora
gcc w wersji 7.11. W poniższej implementacji pominąłem wyrównywanie tekstu zależnie od flag:
ios_base::left
czy
ios_base::right
.
#include <ios>
template < typename String, typename CharT >
struct QuotedString
{
String s;
CharT delim, escape;
QuotedString( String s, CharT delim, CharT escape )
: s( s )
, delim( delim )
, escape( escape )
{ }
QuotedString & operator =( QuotedString & ) = delete;
};
template < typename CharT, typename Traits = std::char_traits < CharT >, typename Alloc = std::allocator < CharT >>
inline auto quoted( const std::basic_string < CharT, Traits, Alloc >& s, CharT delim = CharT( '"' ), CharT escape = CharT( '\\' ) )
{
return QuotedString < const std::basic_string < CharT, Traits, Alloc >&, CharT >( s, delim, escape );
}
template < typename CharT, typename Traits = std::char_traits < CharT >, typename Alloc = std::allocator < CharT >>
inline auto quoted( const CharT * s, CharT delim = CharT( '"' ), CharT escape = CharT( '\\' ) )
{
return QuotedString < const std::basic_string < CharT, Traits, Alloc >&, CharT >( s, delim, escape );
}
template < typename CharT, typename Traits = std::char_traits < CharT >, typename Alloc = std::allocator < CharT >>
inline auto quoted( std::basic_string < CharT, Traits, Alloc >& s, CharT delim = CharT( '"' ), CharT escape = CharT( '\\' ) )
{
return QuotedString < std::basic_string < CharT, Traits, Alloc >&, CharT >( s, delim, escape );
}
template < typename CharT, typename Traits, typename String >
std::basic_ostream < CharT, Traits >& operator <<( std::basic_ostream < CharT, Traits >& os, const QuotedString < String, CharT >& q )
{
os << q.delim;
for( CharT c: q.s )
{
if( Traits::eq( q.delim, c ) || Traits::eq( q.escape, c ) )
{
os << q.escape << c;
}
else
{
os << c;
}
}
return os << q.delim;
}
template < typename CharT, typename Traits, typename Alloc >
std::basic_istream < CharT, Traits >& operator >>( std::basic_istream < CharT, Traits >& is, const QuotedString < std::basic_string < CharT, Traits, Alloc >&, CharT >& s )
{
auto c = is.get();
if( c != s.delim )
{
is.unget();
return is >> s.s;
}
const auto previousSkipwsFlags = is.flags( is.flags() & ~std::ios_base::skipws );
s.s.clear();
while( true )
{
c = is.get();
if( !is )
{
break;
}
if( Traits::eq( s.delim, c ) )
{
break;
}
else if( Traits::eq( s.escape, c ) )
{
c = is.get();
if( !is )
{
break;
}
}
s.s += c;
}
is.setf( previousSkipwsFlags );
return is;
}
Przykład
#include <iostream>
#include <iomanip>
int main()
{
const std::string text = R "(Dobry informatyk powiedział: " C++jest najlepszy !", od tej pory jest jeszcze lepszym informatykiem)";
std::cout << "Oryginalny tekst: " << text << std::endl;
std::cout << "Cytowany tekst: " << std::quoted( text ) << std::endl;
std::stringstream stream;
stream << std::quoted( text );
std::string textRestored;
stream >> std::quoted( textRestored );
std::cout << "Znowu oryginalny: " << textRestored << std::endl;
}
Standardowe wyjście programu:
Oryginalny tekst: Dobry informatyk powiedział: "C++ jest najlepszy!", od tej pory jest jeszcze lepszym informatykiem
Cytowany tekst: "Dobry informatyk powiedział: \"C++ jest najlepszy!\", od tej pory jest jeszcze lepszym informatykiem"
Znowu oryginalny: Dobry informatyk powiedział: "C++ jest najlepszy!", od tej pory jest jeszcze lepszym informatykiem
Zagadnienia powiązane
char_traits | Standardowe cechowanie znaków. (szablon klasy) |
---|
basic_string | Standardowy kontener C++ dostarczający mechanizmy do łatwej pracy z tekstem, którego znaki są określonego typu. (szablon klasy) |
---|
string | Przechowuje tekst wielobajtowy. Znak jest zdefiniowany za pomocą typu char . (alias) |
---|
allocator | Standardowy alokator. (szablon klasy) |
---|
Linki zewnętrzne