:: 与 tolower() 一起使用所必需的运算符

:: operator necessary to use with tolower()?

本文关键字:运算符 tolower 一起      更新时间:2023-10-16
transform(mystr.begin(), mystr.end(), mystr.begin(), tolower);

我正在使用 transform 函数使字符串全部小写字母,但即使在编写"使用命名空间 std;"之后,在我的程序顶部,我也会收到一大堆错误(当像上面一样编写时)。当我在 tolower 参数之前包含 :: 运算符时(如下所示),我没有。这是为什么呢?我认为 tolower 函数位于 std 命名空间中,它会像我上面一样工作。

transform(mystr.begin(), mystr.end(), mystr.begin(), ::tolower);

我有以下内容包括:

#include <iostream>
#include <fstream
#include <sstream>
#include <algorithm>
#include <vector>

在错误消息中,我看到:

error: no matching function for call to 'transform(std::basic_string<char>::iterator, ...

然后它是参数列表中"降低"的位置

, <unresolved overloaded function type>);'

嗯,这有点复杂。添加#include <cctype>似乎可以解决您的问题。然而,还有更多的事情要做。

有两个版本的tolower

int std::tolower(int ch);                           // #include <cctype>
template<typename charT>
charT std::tolower(charT ch, const std::locale& loc);    // #include <locale>

但也可能有这个版本:

int ::tolower(int ch);    // #include <cctype> or #include <ctype.h>

因为允许实现将名称从std注入全局命名空间。此外,您不能指望是否包含cctypelocale,因为任何标准包含也可能包括任何其他标准包含。


看起来您打算使用<cctype> 中的版本。 但是,这将是一个错误。如果您查看该版本tolower的文档,您将看到参数在传递给函数之前应转换为unsigned char

IOW,将具有负值的char传递给 tolower 的 cctype 版本会导致未定义的行为。(尽管常见的实现支持它,因为它是一个常见的错误)。

要更正您的代码并仍然使用 cctype 版本,您可以编写:

#include <cctype>
// ...
transform(mystr.begin(), mystr.end(), mystr.begin(), 
    [](char ch) { return std::tolower( (unsigned char)ch ); } );

虽然使用起来似乎更简单一些:

for (char &ch : mystr)
    ch = std::tolower( (unsigned char)ch );

<locale>版本如下所示(记住它是一个函数模板):

#include <locale>
#include <functional>
// ...
transform(mystr.begin(), mystr.end(), mystr.begin(), 
    std::bind( std::tolower<char>, std::placeholders::_1, std::locale() ) );

std::locale loc;
for ( char &ch : mystr )
    ch = std::tolower(ch, loc);

这是为了解决 tolower 之间的重载之间的冲突 <cctype>int tolower(int c)<locale>的模板<typename charT> charT tolower(charT c, locale const& loc)

::tolower使用全局范围

您包含的头文件是什么?确保,你包括<cctype>而不是<ctype.h>..在<cctype>中,所有函数都在命名空间 std 中定义。

::是说它在全局命名空间中。它只是说清楚