我想转换一个std::字符串小写。我知道tolower()函数。然而,在过去,我有这个函数的问题,它几乎不是理想的无论如何使用std::string将需要迭代每个字符。

有没有一种替代方案能100%有效?


当前回答

由于没有一个答案提到即将到来的Ranges库,它从c++ 20开始就在标准库中可用,目前在GitHub上单独可用为range-v3,我想添加一种使用它执行转换的方法。

就地修改字符串:

str |= action::transform([](unsigned char c){ return std::tolower(c); });

生成一个新的字符串:

auto new_string = original_string
    | view::transform([](unsigned char c){ return std::tolower(c); });

(不要忘记#include <cctype>和所需的Ranges头。)

注意:使用unsigned char作为lambda的参数是受cppreference的启发,它声明:

Like all other functions from <cctype>, the behavior of std::tolower is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. To use these functions safely with plain chars (or signed chars), the argument should first be converted to unsigned char: char my_tolower(char ch) { return static_cast<char>(std::tolower(static_cast<unsigned char>(ch))); } Similarly, they should not be directly used with standard algorithms when the iterator's value type is char or signed char. Instead, convert the value to unsigned char first: std::string str_tolower(std::string s) { std::transform(s.begin(), s.end(), s.begin(), // static_cast<int(*)(int)>(std::tolower) // wrong // [](int c){ return std::tolower(c); } // wrong // [](char c){ return std::tolower(c); } // wrong [](unsigned char c){ return std::tolower(c); } // correct ); return s; }

其他回答

这可能是另一个简单的版本,将大写字母转换为小写字母,反之亦然。我使用VS2017社区版来编译这个源代码。

#include <iostream>
#include <string>
using namespace std;

int main()
{
    std::string _input = "lowercasetouppercase";
#if 0
    // My idea is to use the ascii value to convert
    char upperA = 'A';
    char lowerA = 'a';

    cout << (int)upperA << endl; // ASCII value of 'A' -> 65
    cout << (int)lowerA << endl; // ASCII value of 'a' -> 97
    // 97-65 = 32; // Difference of ASCII value of upper and lower a
#endif // 0

    cout << "Input String = " << _input.c_str() << endl;
    for (int i = 0; i < _input.length(); ++i)
    {
        _input[i] -= 32; // To convert lower to upper
#if 0
        _input[i] += 32; // To convert upper to lower
#endif // 0
    }
    cout << "Output String = " << _input.c_str() << endl;

    return 0;
}

注意:如果有特殊字符,则需要使用条件检查来处理。

c++不需要为std::string实现ower或toupper方法,但可以用于char。人们可以很容易地读取字符串的每个字符,将其转换为所需的大小写,并将其放回字符串。 不使用任何第三方库的示例代码:

#include<iostream>
    
int main(){
    std::string str = std::string("How ARe You");
    for(char &ch : str){
        ch = std::tolower(ch);
    }
    std::cout<<str<<std::endl;
    return 0;
}

对于字符串上基于字符的操作:对于字符串中的每个字符

使用c++ 11中基于范围的for循环,代码会更简单:

#include <iostream>       // std::cout
#include <string>         // std::string
#include <locale>         // std::locale, std::tolower

int main ()
{
  std::locale loc;
  std::string str="Test String.\n";

 for(auto elem : str)
    std::cout << std::tolower(elem,loc);
}

我尝试了std::transform,我得到的是可恶的stl criptic编译错误,只有200年前的德鲁伊才能理解(不能从flibidi flabidi流感转换)

这工作得很好,可以很容易地调整

string LowerCase(string s)
{
    int dif='a'-'A';
    for(int i=0;i<s.length();i++)
    {
        if((s[i]>='A')&&(s[i]<='Z'))
            s[i]+=dif;
    }
   return s;
}

string UpperCase(string s)
{
   int dif='a'-'A';
    for(int i=0;i<s.length();i++)
    {
        if((s[i]>='a')&&(s[i]<='z'))
            s[i]-=dif;
    }
   return s;
}

为ASCII字符串to_lower添加了一些可选库,它们都是生产级的,并进行了微优化,预计会比这里现有的答案更快(TODO:添加基准测试结果)。

Facebook的愚蠢:

void toLowerAscii(char* str, size_t length)

谷歌的绳降:

void AsciiStrToLower(std::string* s);