我想将一个std::string
转换为小写。虽然我知道有函数tolower()
,但是以往使用这个函数时遇到问题,而且即使使用它来处理std::string
也并不理想,因为它需要迭代每个字符。
是否有其他的方法可以保证100%的成功率呢?
我想将一个std::string
转换为小写。虽然我知道有函数tolower()
,但是以往使用这个函数时遇到问题,而且即使使用它来处理std::string
也并不理想,因为它需要迭代每个字符。
是否有其他的方法可以保证100%的成功率呢?
内容摘自不那么常见的问题:
#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);
请注意,tolower()
只能进行单个字节字符的替换,这在许多脚本中并不适合,特别是如果使用像UTF-8这样的多字节编码。
char
传递给::tolower(int)
)。你需要确保不要传递负值。 - juanchopanza::tolower
可能会导致崩溃,对于非 ASCII 输入是未定义行为。 - Cheers and hth. - Alf#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);
简述:
使用ICU库。如果不使用,你的转换程序可能会在一些你甚至没有意识到的情况下默默失败。
std::toupper( 'ß' )
或std::tolower( 'Σ' )
这样的操作,无论在任何编码中,都会遇到麻烦。因为1)标准只能一次处理一个字符,所以它无法正确地将ß
转换为SS
。2)标准只能一次处理一个字符,所以它无法确定Σ
是单词中间(应该使用σ
)还是在末尾(应该使用ς
)。另一个例子是std::tolower('I')
,其结果应根据区域设置而异,在大多数情况下期望得到i
,但在土耳其,ı
(LATIN SMALL LETTER DOTLESS I)是正确的答案(在UTF-8编码中占用多个字节)。#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>
的解决方案可以为您提供这种转换。std::string
不知道它包含的是多字节字符编码的文本,这是一种特性而不是错误。这是唯一明智的做法,这也是为什么几乎每个人都这样做的原因。然而,从过去到现在,没有适当的标准 API 来处理除基本文本以外的任何内容确实是一个问题。即使在托管环境中,它也必须是可选的,因为它相当沉重,并且有许多情况下它并不需要。 - Deduplicator使用 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);
}
使用基于范围的for循环和引用变量的另一种方法
string test = "Hello World";
for(auto& c : test)
{
c = tolower(c);
}
cout<<test<<endl;
这是对Stefan Mai回答的跟进:如果您想将转换结果放在另一个字符串中,您需要在调用std::transform
之前预先分配其存储空间。由于STL会将转换后的字符存储到目标迭代器(在循环的每次迭代中将其递增),目标字符串不会自动调整大小,您会面临内存覆盖的风险。
#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;
}
将字符串转换为小写的最简单方法是如下所示,无需担心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;
}
std::tolower
无法处理 char
,它只支持 unsigned char
。因此,如果 str
包含 0x00-0x7F 之外的字符,则此代码将产生未定义行为。 - Dmitry Grigoryevstr
开头的标识符是严格保留的。 - Roflcopter4我编写了这个简单的帮助函数:
#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.
我自己写的模板函数,用于执行大小写转换。
#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;
}
towlower
函数。 - Juv
tolower()
并非始终有效。小写/大写操作仅适用于字符,而std::string
本质上是一个字节数组,而非字符数组。对于ASCII字符串,普通的tolower()
函数很好用,但它无法正确地将Latin-1或UTF-8字符串转换为小写形式。你必须了解字符串的编码,并且可能需要在转换为小写字符之前进行解码。 - Constantin