Suppose there is a line with the name of the processor, which is returned by the function GetProcessorName() :

 // "Intel<R> Core<TM>2 Duo CPU P8400 @ 2.26GHz" std::string some_string = GetProcessorName(); 

It is necessary to remove extra spaces. That is, format the string so that there are no extra spaces or tabs between the words. Like this:

 // "Intel<R> Core<TM>2 Duo CPU P8400 @ 2.26GHz"; 

I tried to replace & replace_if , in the end I realized that these and similar algorithms are intended exclusively for containers. Perhaps lambda help. What advise you to do with std::string ?

    4 answers 4

    In general, std::string is a regular container. same as regular std::vector .

    If you don't want remove / remove_if and the soul needs lambdas, you can

     #include <iostream> #include <algorithm> #include <string> using namespace std; int main() { std::string some_string = "Intel<R> Core<TM>2 Duo CPU P8400 @ 2.26GHz"; auto end = std::unique(some_string.begin(), some_string.end(), [](char l, char r){ return std::isspace(l) && std::isspace(r) && l == r; }); std::cout << std::string(some_string.begin(), end) << '\n'; return 0; } 

    UPD

    Some suggest rewriting condition

     std::isspace(l) && std::isspace(r) && l == r 

    as

     std::isspace(l) && l == r 

    I would still rewrite it as

     std::isspace(l) && std::isspace(r) 

    Why? The question sounds "remove extra spaces and tabs." And if the line is this (the underscore is a space, and \t is a tab)

     a\t\t__\t_\tb 

    it would probably be correct to shorten it to a_b , and not a\t_\t_\tb .

    But if you look at what exactly std::isspace , you will find out that the newline ( \n ) is also considered. Therefore, if the line is a multi-line view abc_\n_def , then it will be reduced to abc_def , which may not be exactly what you want. By the way, this option is closer to the regular version in the answer @GreenDragon, since \s works like isspace .

    • Lambda calls me: error C2780: 'bool std :: isspace (_Elem, const std :: locale &)': expects 2 arguments - 1 provided. Description in editor: no instance of function template "str :: isspace" matches the argument list. Argument type are: (char) - VBS
    • <cctype> connected? - vp_arth
    • perhaps the ancient compiler ideone.com/sJXjDI - KoVadim
    • one
      One std::isspace can be removed. - αλεχολυτ
    • one
      @KoVadim: Well, let's say, std::string is not an ordinary std::vector . The mere presence of a terminator terminator accessible via the [] operator with the size() index illegal for std::vector makes it far from such ordinary. - AnT

    Well, why string not a container? :)
    See for yourself:

     int main(int argc, const char * argv[]) { string s = "Intel<R> Core<TM>2 Duo CPU P8400 @ 2.26GHz"; s = s.substr(0,distance(s.begin(),remove_if(s.begin(), s.end(), [](const char& a) { return (a == ' ') && (*(&a+1) == ' '); }))); cout << "[" << s << "]\n"; } 

      You can use regular expressions for working with text. Starting with C ++ 11 , their support has appeared in the standard library, so your task can also be solved in the following way:

       #include <iostream> #include <string> #include <regex> int main() { std::string str= "Intel<R> Core<TM>2 Duo CPU P8400 @ 2.26GHz"; std::regex e("(\\s)+"); std::cout << std::regex_replace (str,e,"$1")<<"\n"; } 
      • The release source has increased from 34 to 70 KB. Not the best option in this case. But for an unusual, and even extremely short example of solving my problem - thanks. I didn't even know about their presence in C ++ 11. For the sake of readability I will study these wonderful expressions. - VBS
      • one
        @VBS if you like the answer, vote (arrows on the left). - αλεχολυτ

      A slightly simplified version of the @KoVadim code under c ++ 03 :

       #include <iostream> #include <algorithm> #include <string> #include <cctype> bool space2(char l, char r) { return l == r && std::isspace(l); } int main() { std::string s = "Intel<R> Core<TM>2 Duo CPU P8400 @ 2.26GHz"; std::cout << std::string(s.begin(), std::unique(s.begin(), s.end(), space2)) << '\n'; }