如何在std::for_each中使用std::toupper

How to use std::toupper in std::for_each?

本文关键字:std toupper each for      更新时间:2023-10-16

我正在尝试使用std::toupper函数将字符串的小写字符转换为大写字符,并且我正在使用std::for_each算法迭代字符串中的字符。

#include <iostream>
#include <string>
#include <algorithm>
#include <locale>
std::string convert_toupper(std::string *x) {
  return std::toupper(*x, std::locale());
}
int main() {
  std::string x ("example");
  std::for_each(x.begin(), x.end(), convert_toupper);
}

当我编译这段代码时,我得到这个错误:

In file included from /usr/include/c++/4.8/algorithm:62:0,
                 from me2.cpp:3:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >; _Funct = std::basic_string<char> (*)(std::basic_string<char>*)]’:
me2.cpp:13:52:   required from here
/usr/include/c++/4.8/bits/stl_algo.h:4417:14: error: invalid conversion from ‘char’ to ‘std::basic_string<char>*’ [-fpermissive]
  __f(*__first);
              ^

使用std::toupper和std::for_each从小写到大写的字符转换的正确方法是什么?

A string基本上是char s的容器。当你迭代一个string的时候,你每次只迭代一个char。因此,传递给for_each的函子将被char调用,而不是string*,因此出现错误:

invalid conversion from ‘char’ to ‘std::basic_string<char>*

正确的实现应该是:

std::for_each(x.begin(), x.end(), std::toupper);

然而,这不会有任何作用。toupper的返回值将被忽略,并且该函数没有副作用。如果您真的想要将字符串转换成它的大写版本,您必须使用std::transform:

std::transform(x.begin(), x.end(), x.begin(), std::toupper);

或者,提供区域设置:

char locale_upper(char c) { return std::toupper(c, std::locale()); }
std::transform(x.begin(), x.end(), x.begin(), locale_upper);

或者在c++ 11中:

std::transform(x.begin(), x.end(), x.begin(), [](char c){
    return std::toupper(c, std::locale());
});

此时,您不妨使用for -loop:

for (char& c : x) {
    c = std::toupper(c, std::locale());
}

<locale>中,您已经有了std::ctype::toupper函数将小写字符串转换为大写。函数调用有点棘手,但它非常紧凑:

std::use_facet<std::ctype<char>>(std::locale()).toupper(&x[0], &x[0] + x.size());

下面是使用std::for_eachstd::toupper将小写字符串转换为大写字符串的一种方法。重要的是要记住将lambda中的参数设置为字符引用,如(char& ch)

#include <algorithm>   // for_each
#include <cctype>      // toupper
#include <iostream>    // cout
#include <string>      // string
int main()
{
   std::string s{ "This is a test" };
   std::cout << s << 'n';
   
   std::for_each(s.begin(), s.end(),[] (char& ch) { ch = std::toupper(ch); } );   
      
   std::cout << s << 'n';
   return 0;
}