如何将 std::string 的实例转换为小写

How to convert an instance of std::string to lower case

提问人:Konrad 提问时间:11/24/2008 最后编辑:Peter MortensenKonrad 更新时间:6/23/2023 访问量:1311933

问:

我想将 a 转换为小写。我知道这个功能。但是,过去我遇到过这个函数的问题,无论如何它都不是理想的,因为将它与 a 一起使用需要遍历每个字符。std::stringtolower()std::string

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

C++ 字符串 C++-Standard-Library tolower

评论

51赞 11/24/2008
否则,如何在不遍历列表的情况下将任何内容列表的每个元素转换为其他元素?字符串只是一个字符列表,如果您需要对每个字符应用一些函数,则必须遍历字符串。没办法。
29赞 Konrad 11/24/2008
为什么这个问题会降低评级?我在遍历我的字符串时没有问题,但我在问除了 tolower()、toupper() 等之外是否还有其他函数。
16赞 Steve Jessop 11/24/2008
@Dan:如果它们可能已经是小写的,但肯定是 A-Z 或 a-z,你可以用 OR 0x20而不是添加。那些如此聪明的优化之一,可能是愚蠢的,几乎从来都不值得......
6赞 warren 11/24/2008
我不知道为什么它会被否决......当然,它的措辞有点奇怪(因为你必须以某种方式遍历每个项目),但这是一个有效的问题
6赞 Constantin 11/24/2008
注意:不是 100% 工作。小写/大写操作仅适用于字符,std::string 本质上是字节数组,而不是字符。plain 非常适合 ASCII 字符串,但它不会正确地将 latin-1 或 utf-8 字符串小写。您必须知道字符串的编码,并可能先对其进行解码,然后才能将其字符小写。tolower()tolower

答:

373赞 Rob 11/24/2008 #1

Boost 为此提供了一个字符串算法

#include <boost/algorithm/string.hpp>

std::string str = "HELLO, WORLD!";
boost::algorithm::to_lower(str); // modifies str

或者,对于非就地

#include <boost/algorithm/string.hpp>

const std::string str = "HELLO, WORLD!";
const std::string lower_str = boost::algorithm::to_lower_copy(str);

评论

25赞 DevSolar 2/27/2015
对于非 ASCII-7 失败。
3赞 prehistoricpenguin 6/29/2021
这很慢,请参阅此基准测试:godbolt.org/z/neM5jsva1
3赞 Mayou36 2/12/2022
@prehistoricpenguin慢?好吧,调试代码很慢,因为您自己的实现有一个错误,因为它比仅仅调用 boost 库更复杂;)如果代码很关键,比如调用了很多代码并提供了瓶颈,那么,好吧,值得考虑缓慢
0赞 ZoomIn 10/13/2022
我相信boost不是C++标准库解决方案,不是吗?
3赞 Logix 1/28/2023
不,不是。这是您在本网站上的每一个 C++ 问题中看到的这些极其不幸的答案之一......因为添加整个库只是为了做一些如此简单的事情,这显然是最受欢迎的途径!
1112赞 Stefan Mai 11/24/2008 #2

改编自不那么常见的问题

#include <algorithm>
#include <cctype>
#include <string>

std::string data = "Abc";
std::transform(data.begin(), data.end(), data.begin(),
    [](unsigned char c){ return std::tolower(c); });

如果不遍历每个角色,你真的不会逃脱。否则,无法知道字符是小写还是大写。

如果你真的讨厌 tolower(),这里有一个专门的仅限 ASCII 的替代方案,我不建议你使用:

char asciitolower(char in) {
    if (in <= 'Z' && in >= 'A')
        return in - ('Z' - 'z');
    return in;
}

std::transform(data.begin(), data.end(), data.begin(), asciitolower);

请注意,它只能执行每个单字节字符的替换,这不适合许多脚本,尤其是在使用 UTF-8 等多字节编码时。tolower()

评论

6赞 UberJumper 11/24/2008
这太棒了,我一直想知道最好的方法是什么。我不知道使用std::transform。:)
30赞 eq- 11/12/2011
(可能很旧,所讨论的算法变化不大) @Stefan Mai:调用 STL 算法会带来什么样的“大量开销”?这些函数相当精简(即简单的循环),并且经常内联,因为您很少在同一编译单元中使用相同的模板参数对同一函数进行多次调用。
353赞 Rag 2/11/2014
每次你假设字符是 ASCII 时,上帝就会杀死一只小猫。:(
15赞 juanchopanza 5/30/2014
您的第一个示例可能具有未定义的行为(传递给 .)您需要确保不会传递负值。char::tolower(int)
9赞 Charles Ofria 7/31/2016
在 tolower 之前需要 :: 来指示它位于最外层的命名空间中。如果在另一个命名空间中使用此代码,则 tolower 可能会有一个不同的(可能不相关的)定义,最终将优先选择该定义,而没有 ::。
32赞 Patrick Ohly 10/10/2012 #3

如果字符串包含 ASCII 范围之外的 UTF-8 字符,则 boost::algorithm::to_lower 将不会转换这些字符。当涉及 UTF-8 时,最好使用 boost::locale::to_lower。查看 http://www.boost.org/doc/libs/1_51_0/libs/locale/doc/html/conversions.html

评论

0赞 Velkan 1/2/2022
一个工作的例子?
27赞 user2218467 3/28/2013 #4

这是 Stefan Mai 回应的后续:如果您想将转换结果放在另一个字符串中,您需要在调用 .由于 STL 将转换后的字符存储在目标迭代器中(在循环的每次迭代中递增),因此目标字符串不会自动调整大小,并且您有内存踩踏的风险。std::transform

#include <string>
#include <algorithm>
#include <iostream>

int main (int argc, char* argv[])
{
  std::string sourceString = "Abc";
  std::string destinationString;

  // Allocate the destination space
  destinationString.resize(sourceString.size());

  // Convert the source string to lower case
  // storing the result in destination string
  std::transform(sourceString.begin(),
                 sourceString.end(),
                 destinationString.begin(),
                 ::tolower);

  // Output the result of the conversion
  std::cout << sourceString
            << " -> "
            << destinationString
            << std::endl;
}

评论

2赞 Purefan 1/24/2016
这并没有为我调整 Ä 的大小为 ä
1赞 chili 4/24/2017
也可以在这里使用后插入器迭代器,而不是手动调整大小。
4赞 Jason Enochs 9/19/2013 #5

Boost 的替代品是 POCO (pocoproject.org)。

POCO 提供两种变体:

  1. 第一个变体在不更改原始字符串的情况下进行复制。
  2. 第二个变体更改了原有的字符串。
    “就地”版本的名称中始终包含“InPlace”。

两个版本如下所示:

#include "Poco/String.h"
using namespace Poco;

std::string hello("Stack Overflow!");

// Copies "STACK OVERFLOW!" into 'newString' without altering 'hello.'
std::string newString(toUpper(hello));

// Changes newString in-place to read "stack overflow!"
toLowerInPlace(newString);
39赞 incises 10/9/2013 #6

使用基于范围的 for 循环 C++11 更简单的代码是:

#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);
}

评论

10赞 incises 10/9/2013
但是,在法语机器上,此程序不会转换法语中允许的非 ASCII 字符。例如,字符串 'Test String123.É Ï\n' 将转换为 : 'test string123.É Ï\n' 虽然字符 É Ï 及其小写字母“é”和“ï”在法语中是允许的。此线程的其他消息似乎没有提供任何解决方案。
2赞 user1095108 12/30/2013
我认为您需要为此设置一个适当的区域设置。
1赞 Alexis Wilke 9/2/2016
@incises,然后有人发布了关于 ICU 的答案,这当然是要走的路。比大多数尝试理解语言环境的其他解决方案更容易。
0赞 kayleeFrye_onDeck 7/11/2017
就我个人而言,我宁愿尽可能不使用外部库。
2赞 user2548100 1/9/2014 #7

有一种方法可以将大写转换为小写,而无需进行 if 测试,而且非常简单。isupper() 函数/宏对 clocale.h 的使用应该可以解决与您的位置相关的问题,但如果没有,您可以随时根据自己的喜好调整 UtoL[]。

鉴于 C 的字符实际上只是 8 位整数(暂时忽略宽字符集),您可以创建一个 256 字节的数组来保存一组替代字符,并在转换函数中使用字符串中的字符作为下标进入转换数组。

但是,不要使用 1 对 1 映射,而是为大写数组成员提供小写字符的 BYTE int 值。您可能会发现 islower() 和 isupper() 在这里很有用。

enter image description here

代码如下所示...

#include <clocale>
static char UtoL[256];
// ----------------------------------------------------------------------------
void InitUtoLMap()  {
    for (int i = 0; i < sizeof(UtoL); i++)  {
        if (isupper(i)) {
            UtoL[i] = (char)(i + 32);
        }   else    {
            UtoL[i] = i;
        }
    }
}
// ----------------------------------------------------------------------------
char *LowerStr(char *szMyStr) {
    char *p = szMyStr;
    // do conversion in-place so as not to require a destination buffer
    while (*p) {        // szMyStr must be null-terminated
        *p = UtoL[*p];  
        p++;
    }
    return szMyStr;
}
// ----------------------------------------------------------------------------
int main() {
    time_t start;
    char *Lowered, Upper[128];
    InitUtoLMap();
    strcpy(Upper, "Every GOOD boy does FINE!");

    Lowered = LowerStr(Upper);
    return 0;
}

同时,这种方法将允许您重新映射要更改的任何其他字符。

这种方法在现代处理器上运行时具有一个巨大的优势,无需进行分支预测,因为没有包含分支的 if 测试。这样可以节省 CPU 对其他循环的分支预测逻辑,并倾向于防止管道停顿。

这里的一些人可能会将这种方法与用于将 EBCDIC 转换为 ASCII 的方法相同。

评论

2赞 Gábor Buella 12/16/2014
“有一种方法可以将大写转换为小写,而无需进行 if 测试”听说过查找表吗?
2赞 Roland Illig 11/21/2017
负字符的未定义行为。
0赞 Contango 4/14/2020
现代 CPU 的瓶颈在于内存,而不是 CPU。基准测试会很有趣。
340赞 DevSolar 6/5/2014 #8

TL的;博士

使用 ICU 库如果你不这样做,你的转换例程将在你甚至可能不知道存在的案例上悄无声息地中断。


首先,你必须回答一个问题:你的编码是什么?是ISO-8859-1吗?或者也许是 ISO-8859-8?还是 Windows 代码页 1252?你用来将大写字母转换为小写字母的任何东西都知道吗?(或者它是否为角色惨遭失败?std::string0x7f

如果你使用 UTF-8(8 位编码中唯一理智的选择)作为容器,如果你相信你仍然在控制事物,你就已经在欺骗自己了。您将多字节字符序列存储在不知道多字节概念的容器中,并且您可以对其执行的大多数操作也无法执行!即使是像这样简单的东西也可能导致无效的(子)字符串,因为您在多字节序列的中间进行拆分。std::string.substr()

一旦你尝试类似的东西,或者任何编码,你就有麻烦了。因为 1),该标准一次只能对一个字符进行操作,因此它根本无法转换为正确的字符。2)标准一次只对一个字符进行操作,因此它无法决定是在单词的中间(哪里是正确的),还是在结尾()。另一个例子是 ,它应该根据语言环境产生不同的结果 - 几乎在所有你期望的地方,但在土耳其(拉丁文小写字母 DOTLESS I)是正确的答案(同样,在 UTF-8 编码中,它不止一个字节)。std::toupper( 'ß' )std::tolower( 'Σ' )ßSSΣσςstd::tolower( 'I' )iı

因此,任何一次对一个字符起作用的大小写转换,或者更糟糕的是,一次对一个字节起作用,都会被设计破坏。这包括目前存在的所有变体。std::

还有一点是,标准库,就它能够做什么而言,取决于运行软件的机器上支持哪些语言环境......如果您的目标区域设置在客户端计算机上不受支持,您会怎么做?

因此,您真正要寻找的是一个能够正确处理所有这些的字符串类,而不是任何 std::basic_string<> 变体

(C++11 注:并且更好,但仍然不完美。C++20 带来了 ,但所有这些所做的只是指定编码。在许多其他方面,他们仍然对Unicode机制一无所知,例如规范化,排序规则等。std::u16stringstd::u32stringstd::u8string

虽然 Boost 看起来不错,但 API 方面,Boost.Locale 基本上是 ICU 的包装器。如果Boost 是在 ICU 支持下编译的......如果不是,则 Boost.Locale 仅限于为标准库编译的区域设置支持。

相信我, Boost 与 ICU 一起编译有时真的很痛苦。(Windows 没有包含 ICU 的预编译二进制文件,因此您必须将它们与应用程序一起提供,这会打开一个全新的蠕虫罐头......

因此,就我个人而言,我建议直接从马的嘴里获得完整的Unicode支持,并直接使用ICU库:

#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/locid.h>

#include <iostream>

int main()
{
    /*                          "Odysseus" */
    char const * someString = u8"ΟΔΥΣΣΕΥΣ";
    icu::UnicodeString someUString( someString, "UTF-8" );
    // Setting the locale explicitly here for completeness.
    // Usually you would use the user-specified system locale,
    // which *does* make a difference (see ı vs. i above).
    std::cout << someUString.toLower( "el_GR" ) << "\n";
    std::cout << someUString.toUpper( "el_GR" ) << "\n";
    return 0;
}

编译(在此示例中使用 G++):

g++ -Wall example.cpp -licuuc -licuio

这给出了:

ὀδυσσεύς

请注意,单词中间的 Σ<->σ 转换,以及单词末尾的 Σ<->ς 转换。任何基于解决方案都无法为您提供这种服务。<algorithm>

评论

32赞 lmat - Reinstate Monica 3/25/2015
这是一般情况下的正确答案。除了“ASCII”之外,除了谎言和欺骗之外,该标准没有提供任何处理任何东西。它让你认为你也许可以处理 UTF-16,但你不能。正如这个答案所说,如果不进行自己的 unicode 处理,您将无法获得 UTF-16 字符串的正确字符长度(而不是字节长度)。如果您必须处理真实文本,请使用 ICU。谢谢,@DevSolar
0赞 Shital Shah 5/12/2016
ICU 在 Ubuntu/Windows 上默认可用还是需要单独安装?还有这个答案:stackoverflow.com/a/35075839/207661
0赞 masaers 6/15/2017
icu::UnicodeString::length() 在技术上也对你撒谎(尽管不那么频繁),因为它报告的是 16 位代码单元的数量,而不是代码点的数量。;-)
0赞 DevSolar 6/15/2017
@masaers:公平地说,对于组合字符、零宽度连接器和从右到左标记之类的东西,代码点的数量是毫无意义的。我将删除这句话。
2赞 masaers 6/15/2017
@DevSolar同意了!长度的概念在文本上毫无意义(我们可以在罪犯列表中添加连字)。也就是说,由于人们习惯于使用制表符和控制字符占用一个长度单位,因此代码点将是更直观的度量。哦,谢谢你给出正确的答案,很难过看到它这么远:-(
3赞 Sandeep Datta 8/30/2014 #9

在 Microsoft 平台上,可以使用以下函数系列: http://msdn.microsoft.com/en-us/library/hkxwh33z.aspxstrlwr

// crt_strlwr.c
// compile with: /W3
// This program uses _strlwr and _strupr to create
// uppercase and lowercase copies of a mixed-case string.
#include <string.h>
#include <stdio.h>

int main( void )
{
   char string[100] = "The String to End All Strings!";
   char * copy1 = _strdup( string ); // make two copies
   char * copy2 = _strdup( string );

   _strlwr( copy1 ); // C4996
   _strupr( copy2 ); // C4996

   printf( "Mixed: %s\n", string );
   printf( "Lower: %s\n", copy1 );
   printf( "Upper: %s\n", copy2 );

   free( copy1 );
   free( copy2 );
}
9赞 Atul Rokade 6/12/2015 #10

将字符串转换为 loweercase 而不用担心 std 命名空间的最简单方法如下

1:带/不带空格的字符串

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    getline(cin,str);
//------------function to convert string into lowercase---------------
    transform(str.begin(), str.end(), str.begin(), ::tolower);
//--------------------------------------------------------------------
    cout<<str;
    return 0;
}

2:不带空格的字符串

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    cin>>str;
//------------function to convert string into lowercase---------------
    transform(str.begin(), str.end(), str.begin(), ::tolower);
//--------------------------------------------------------------------
    cout<<str;
    return 0;
}

评论

1赞 Dmitry Grigoryev 1/31/2022
这完全是错误的:如果你检查文档,你会看到不能用,它只支持。因此,如果此代码包含 0x00-0x7F 之外的字符,则此代码为 UB。std::tolowercharunsigned charstr
0赞 Roflcopter4 11/4/2022
由于使用以全局命名空间开头的标识符,这也是错误的,该标识符是严格保留的。str
5赞 Sameer 1/29/2016 #11

std::ctype::tolower()来自标准 C++ 本地化库将为您正确执行此操作。下面是从 tolower 参考页面中提取的示例

#include <locale>
#include <iostream>

int main () {
  std::locale::global(std::locale("en_US.utf8"));
  std::wcout.imbue(std::locale());
  std::wcout << "In US English UTF-8 locale:\n";
  auto& f = std::use_facet<std::ctype<wchar_t>>(std::locale());
  std::wstring str = L"HELLo, wORLD!";
  std::wcout << "Lowercase form of the string '" << str << "' is ";
  f.tolower(&str[0], &str[0] + str.size());
  std::wcout << "'" << str << "'\n";
}

评论

0赞 quazar 8/17/2016
很好,只要你能转换字符就位。如果你的源字符串是?这似乎使它更加混乱(例如,它看起来不像您可以使用),因为您需要将字符放在新字符串中。你会为操作员使用类似的东西吗?constf.tolower()transform()std::bind1st( std::mem_fun() )
0赞 Sameer 8/29/2016
对于 const 字符串,我们可以只制作一个本地副本,然后就地转换它。
0赞 quazar 9/5/2016
是的,但是,制作副本会增加更多开销。
0赞 chili 4/24/2017
您可以将 std::transform 与不采用指针的 ctype::tolower 版本一起使用。使用后插入器迭代器适配器,您甚至无需担心预先调整输出字符串的大小。
0赞 Arne Vogel 5/23/2017
太好了,特别是因为在 libstdc++ 的 with 参数中,隐式调用似乎是性能瓶颈。我的一位同事通过替换(有这个问题)的版本实现了 100% 的速度提升,该版本仅在循环外调用一次。tolowerlocaleuse_facetboost::iequalsuse_facet
2赞 Volomike 1/31/2016 #12

如果您想要一些简单的东西,这里有一个宏技术:

#define STRTOLOWER(x) std::transform (x.begin(), x.end(), x.begin(), ::tolower)
#define STRTOUPPER(x) std::transform (x.begin(), x.end(), x.begin(), ::toupper)
#define STRTOUCFIRST(x) std::transform (x.begin(), x.begin()+1, x.begin(),  ::toupper); std::transform (x.begin()+1, x.end(),   x.begin()+1,::tolower)

但是,请注意,@AndreasSpindler对这个答案的评论仍然是一个重要的考虑因素,但是,如果您正在研究的不仅仅是 ASCII 字符。

评论

3赞 Clearer 11/7/2017
我反对在存在一个完美的解决方案时提供宏 - 你甚至给出这些解决方案。
2赞 Volomike 11/7/2017
宏技术意味着对编程中经常使用的东西的代码输入更少。为什么不使用它呢?否则,为什么还要有宏?
3赞 Clearer 11/7/2017
宏是 C 语言的遗产,正在努力摆脱它。如果要减少键入量,请使用函数或 lambda。void strtoupper(std::string& x) { std::transform (x.begin(), x.end(), x.begin(), ::toupper); }
2赞 Clearer 11/8/2017
不,我不能。不过,Bjarne在这个话题上的立场已经多次明确表示。此外,有很多理由不在 C 和 C++ 中使用宏。 可能是一个有效的表达式,它只是碰巧正确编译,但由于宏会给出完全虚假的结果。x
4赞 Clearer 7/30/2018
@AquariusPower我不同意。我还没有看到一个宏作为模板或 lambda 做得再好不过了。
34赞 Gilson PJ 1/11/2017 #13

另一种使用基于范围的for循环的方法,带有参考变量

string test = "Hello World";
for(auto& c : test)
{
   c = tolower(c);
}

cout<<test<<endl;

评论

1赞 Rodrigo 4/17/2021
我想它不适用于 UTF-8,是吗?
1赞 9T9 3/20/2017 #14
// tolower example (C++)
#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 (std::string::size_type i=0; i<str.length(); ++i)
    std::cout << std::tolower(str[i],loc);
  return 0;
}

欲了解更多信息,请访问:http://www.cplusplus.com/reference/locale/tolower/

-1赞 rashedcs 4/11/2017 #15

代码片段

#include<bits/stdc++.h>
using namespace std;


int main ()
{
    ios::sync_with_stdio(false);

    string str="String Convert\n";

    for(int i=0; i<str.size(); i++)
    {
      str[i] = tolower(str[i]);
    }
    cout<<str<<endl;

    return 0;
}
0赞 uol3c 5/8/2017 #16

fplus 库使用。fplus::to_lower_case()

fplus API 搜索中搜索to_lower_case

例:

fplus::to_lower_case(std::string("ABC")) == std::string("abc");
1赞 goulashsoup 4/17/2018 #17

此解决方案工作原理的说明:


string test = "Hello World";
for(auto& c : test)
{
   c = tolower(c);
}

解释:

for(auto& c : test)是一个基于范围的 for 循环range_declaration
range_expressionloop_statement
for ( :)

  1. range_declaration
    这里的自动说明符用于自动类型推导。因此,该类型是从变量初始值设定项中扣除的。
    auto& c

  2. range_expression
    本例中的范围是字符串的字符。
    testtest

字符串的字符可作为 for 循环标识符内的引用。testc

评论

0赞 cigien 6/23/2023
我不认为将其添加为答案或对链接答案的编辑的价值。如果有人需要解释范围循环的工作原理,有多种资源可以做到这一点,例如 stackoverflow.com/questions/35490236。对于这个问题,我认为这种解释只是噪音——就像添加迭代器或标准算法如何为使用 .std::transform
2赞 plugwash 1/29/2019 #18

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

在选择小写方法之前,您需要问自己几个问题。

  1. 字符串是如何编码的?纯 ASCII?UTF-8?某种形式的扩展 ASCII 传统编码?
  2. 小写是什么意思?案例映射规则因语言而异!您是否想要针对用户区域设置进行本地化的内容?您是否希望在运行软件的所有系统上都具有一致的行为?您只想小写 ASCII 字符并传递其他所有内容吗?
  3. 有哪些库可用?

一旦你有了这些问题的答案,你就可以开始寻找适合你需求的解决方案。没有一种尺寸适合任何地方的每个人!

2赞 Mahipal 3/17/2019 #19

C++ 没有为 实现 或 方法,但它可用于 。人们可以很容易地读取字符串的每个字符,将其转换为所需的大小写,然后将其放回字符串中。 不使用任何第三方库的示例代码:tolowertoupperstd::stringchar

#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;
}

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

4赞 L. F. 4/15/2019 #20

由于没有一个答案提到即将到来的范围库,该库自 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); });

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

注意:使用 of 作为 lambda 的参数是受 cpppreference 的启发,它指出:unsigned char

与 的所有其他函数一样,如果参数的值既不能表示为也不能等于 ,则 的行为是未定义的。为了安全地使用普通 s(或 s)的这些函数,应首先将参数转换为:<cctype>std::tolowerunsigned charEOFcharsigned charunsigned char

char my_tolower(char ch)
{
    return static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
}

同样,当迭代器的值类型为 或 时,它们不应直接与标准算法一起使用。相反,请将该值转换为 first:charsigned charunsigned char

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;
}
7赞 TarmoPikaro 5/18/2019 #21

我自己的模板功能,可以执行大写/小写。

#include <string>
#include <algorithm>

//
//  Lowercases string
//
template <typename T>
std::basic_string<T> lowercase(const std::basic_string<T>& s)
{
    std::basic_string<T> s2 = s;
    std::transform(s2.begin(), s2.end(), s2.begin(),
        [](const T v){ return static_cast<T>(std::tolower(v)); });
    return s2;
}

//
// Uppercases string
//
template <typename T>
std::basic_string<T> uppercase(const std::basic_string<T>& s)
{
    std::basic_string<T> s2 = s;
    std::transform(s2.begin(), s2.end(), s2.begin(),
        [](const T v){ return static_cast<T>(std::toupper(v)); });
    return s2;
}

评论

2赞 Juv 4/28/2020
这就是我需要的。我只是使用了支持 UTF-16 的宽字符。towlower
0赞 Andrea Giudiceandrea 4/10/2023
需要 ::tolower 和 ::toupper 而不是 tolower 和 toupper
1赞 Bu Saeed 3/19/2020 #22

试试这个函数:)

string toLowerCase(string str) {

    int str_len = str.length();

    string final_str = "";

    for(int i=0; i<str_len; i++) {

        char character = str[i];

        if(character>=65 && character<=92) {

            final_str += (character+32);

        } else {

            final_str += character;

        }

    }

    return final_str;

}

评论

0赞 prehistoricpenguin 6/29/2021
此功能很慢,不应在现实生活中的项目中使用。
7赞 A-Sharabiani 9/30/2020 #23

我写了这个简单的辅助函数:

#include <locale> // tolower

string to_lower(string s) {        
    for(char &c : s)
        c = tolower(c);
    return s;
}

用法:

string s = "TEST";
cout << to_lower("HELLO WORLD"); // output: "hello word"
cout << to_lower(s); // won't change the original variable.
-1赞 prehistoricpenguin 6/22/2021 #24

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

Facebook的愚蠢

void toLowerAscii(char* str, size_t length)

谷歌的绳降

void AsciiStrToLower(std::string* s);
-1赞 The Oathman 2/3/2022 #25

我写了一个适用于任何字符串的模板化版本:

#include <type_traits> // std::decay
#include <ctype.h>    // std::toupper & std::tolower


template <class T = void> struct farg_t { using type = T; };
template <template<typename ...> class T1, 
class T2> struct farg_t <T1<T2>> { using type = T2*; };
//---------------

template<class T, class T2 = 
typename std::decay< typename farg_t<T>::type >::type>
void ToUpper(T& str) { T2 t = &str[0]; 
for (; *t; ++t) *t = std::toupper(*t); }


template<class T, class T2 = typename std::decay< typename 
farg_t<T>::type >::type>
void Tolower(T& str) { T2 t = &str[0]; 
for (; *t; ++t) *t = std::tolower(*t); }

使用 gcc 编译器测试:

#include <iostream>
#include "upove_code.h"

int main()
{

    std::string str1 = "hEllo ";
    char str2 [] = "wOrld";

    ToUpper(str1);
    ToUpper(str2);
    std::cout << str1 << str2 << '\n'; 
    Tolower(str1);
    Tolower(str2);
    std::cout << str1 << str2 << '\n'; 
    return 0;
}

输出:

>HELLO WORLD
>
>hello world
1赞 Edward Gaere 4/25/2022 #26

看看优秀的 c++17 cpp-unicodelibGitHub)。它是单文件和仅标头。


#include <exception>
#include <iostream>
#include <codecvt>

// cpp-unicodelib, downloaded from GitHub
#include "unicodelib.h"
#include "unicodelib_encodings.h"

using namespace std;
using namespace unicode;

// converter that allows displaying a Unicode32 string
wstring_convert<codecvt_utf8<char32_t>, char32_t> converter;

std::u32string  in = U"Je suis là!";
cout << converter.to_bytes(in) << endl;

std::u32string  lc = to_lowercase(in);
cout << converter.to_bytes(lc) << endl;

输出

Je suis là!
je suis là!

评论

4赞 Molochnik 4/30/2022
2022 年,C++17,您必须一次又一次地访问 stackoverflow 来检查 tolower 的另一个版本
-2赞 SHAYAK 5/27/2022 #27

使用此代码更改 C++ 中字符串的大小写。

#include<bits/stdc++.h>

using namespace std;

int main(){
  string a = "sssAAAAAAaaaaDas";
  transform(a.begin(),a.end(),a.begin(),::tolower);
  cout<<a;
}

评论

1赞 Adrian Mole 5/27/2022
切勿在 Stack Overflow 的答案中使用。你会被否决。#include <bits/stdc++.h>
0赞 DimanNe 5/27/2022 #28

谷歌的图书馆有abslabsl::AsciiStrToLower / absl::AsciiStrToUpper

0赞 Lewis Levin 1/28/2023 #29

由于您使用的是 std::string,因此您使用的是 c++。如果使用 c++11 或更高版本,则不需要任何花哨的东西。如果为 ,则:wordsvector<string>

    for (auto & str : words) {
        for(auto & ch : str)
            ch = tolower(ch);
    }

没有奇怪的例外。可能想使用w_char,但除此之外,这应该可以完成所有工作。

0赞 Charlie Reitzel 4/5/2023 #30

从另一个角度来看,有一个非常常见的用例,即对 Unicode 字符串执行区域设置中性大小写折叠。对于这种情况,当您意识到可折叠字符集是有限的且相对较小(< 2000 个 Unicode 码位)时,可以获得良好的大小写折叠性能。它恰好与生成的完美哈希(保证零冲突)配合得很好,可用于将每个输入字符转换为其小写等效字符。

使用 UTF-8 时,您必须注意多字节字符并相应地进行迭代。但是,UTF-8 具有相当简单的编码规则,可以使此操作高效。

有关更多详细信息,包括指向Unicode标准相关部分的链接和完美的哈希生成器,请参阅我在这里对如何在C++中实现与Unicode无关的大小写不区分比较的问题的回答。