Tell me how optimally (if it is possible - by means of STL) to replace the character set with a string with a character.

Now I do this:

std::wstring author; std::replace(author.begin(), author.end(), L'.', L' '); std::replace(author.begin(), author.end(), L',', L' '); std::replace(author.begin(), author.end(), L'-', L' '); std::replace(author.begin(), author.end(), L'\t', L' '); 

But I would like (if possible) to make an optimal, fast and yet compact code (for example, in 1 line). Perhaps through regulars it can be done, then without a clue how.

  • It is unlikely that wstring+stl+регулярки compatible with быстрый и при том компактный - avp
  • I agree on a clear and compact :) - Zhihar
  • one
    I would make a simple loop for (...) { wchar_t c = author[i]; switch (c) { case L'.' : c = L' '; break; ... } author[i] = c; } for (...) { wchar_t c = author[i]; switch (c) { case L'.' : c = L' '; break; ... } author[i] = c; } for (...) { wchar_t c = author[i]; switch (c) { case L'.' : c = L' '; break; ... } author[i] = c; } and did not fool anyone (and first of all the compiler) - avp

3 answers 3

If you want to use standard algorithms, then it’s better:

 std::replace_if(author.begin(), author.end(), [](wchar_t c){return c == L'.' || c == L',' || c == L'-' || c == L'\t';}, L' '); 
  • one
    Since the object is initially of type std :: wstring, it would be better to write the following const auto & c parameter to the lambda instead of the char c parameter. - Vlad from Moscow
  • This is of course true, but I thought that there was something like std::replace(begin, end, L'.,-\t', L' ') - Zhihar
  • @VladfromMoscow At least there should have been wchar_t , corrected. - HolyBlackCat

You can use both the standard std::replace_if algorithm and the for -range-based loop as well as the native methods of the std::wstring class.

Below is a demonstration program showing the listed ways to replace characters. The program uses the std::quoted manipulator, which appeared in C ++ 17. If your compiler does not support it, then simply replace the std::quoted( s ) expression with s .

 #include <iostream> #include <iomanip> #include <string> #include <iterator> #include <algorithm> int main() { std::wstring s( L"Hello-World." ); std::wcout << std::quoted( s ) << '\n'; std::replace_if( std::begin( s ), std::end( s ), []( const auto &c ) { return c == L'.' or c == L',' or c == L'-' or c == '\t'; }, L' ' ); std::wcout << std::quoted( s ) << '\n'; std::wcout << '\n'; s.assign( L"Hello-World." ); std::wcout << std::quoted( s ) << '\n'; for ( auto &c : s ) { switch ( c ) { case L'.': case L',': case L'-': case L'\t': c = L' '; break; } } std::wcout << std::quoted( s ) << '\n'; std::wcout << '\n'; s.assign( L"Hello-World." ); std::wcout << std::quoted( s ) << '\n'; for ( std::wstring::size_type n = 0; ( n = s.find_first_of( L".,-\t", n ) ) != std::wstring::npos; ++n ) { s.replace( n, 1, 1, L' ' ); } std::wcout << std::quoted( s ) << '\n'; std::wcout << '\n'; return 0; } 

The output of the program to the console:

 "Hello-World." "Hello World " "Hello-World." "Hello World " "Hello-World." "Hello World " 

For switch fallthrough , you can use the fallthrough attribute to avoid unnecessary compiler warnings. For example,

 for ( auto &c : s ) { switch ( c ) { case L'.': [[fallthrough]]; case L',': [[fallthrough]]; case L'-': [[fallthrough]]; case L'\t': c = L' '; break; } } 

    Probably better to use class methods. After all, for that and they are intended:

     wstring d(L".,-\t"); size_t cur = 0; while (true) { cur = autor.find_first_of(d, cur); if (cur == wstring::npos) break; autor.replace(cur, 1, 1, L' '); }