Kon*_*rad 736 c++ string c++-standard-library tolower
我想将a转换std::string为小写.我知道这个函数tolower(),但是在过去我遇到了这个函数的问题,并且它很难理想,因为使用a std::string会需要迭代每个字符.
有没有一种方法可以100%的时间运作?
Ste*_*Mai 867
从这个:
#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); });
Run Code Online (Sandbox Code Playgroud)
你真的不会逃避迭代每个角色.否则无法知道字符是小写还是大写.
如果你真的讨厌tolower(),这是一个我不建议您使用的非便携式替代方案:
char asciitolower(char in) {
if (in <= 'Z' && in >= 'A')
return in - ('Z' - 'z');
return in;
}
std::transform(data.begin(), data.end(), data.begin(), asciitolower);
Run Code Online (Sandbox Code Playgroud)
请注意,tolower()只能执行每单字节字符替换,这对于许多脚本来说都是不合适的,特别是如果使用像UTF-8这样的多字节编码.
Rob*_*Rob 304
有一个Boost字符串算法:
#include <boost/algorithm/string.hpp>
std::string str = "HELLO, WORLD!";
boost::algorithm::to_lower(str); // modifies str
Run Code Online (Sandbox Code Playgroud)
或者,对于非就地:
#include <boost/algorithm/string.hpp>
const std::string str = "HELLO, WORLD!";
const std::string lower_str = boost::algorithm::to_lower_copy(str);
Run Code Online (Sandbox Code Playgroud)
Dev*_*lar 221
TL;博士
使用ICU库.
首先,您必须回答一个问题:您的编码是std::string什么?是ISO-8859-1吗?或者ISO-8859-8?或Windows代码页1252?无论你用什么来转换大写到小写都知道吗?(或者对于角色来说,它是否会失败0x7f?)
如果您使用的是UTF-8(8位编码中唯一理智的选择)与std::string作为容器,你已经在自欺欺人,以为你还在控制的事情,因为你是在一个容器中存储的多字节字符序列那不了解多字节概念.甚至像.substr()滴答作响的定时炸弹一样简单.(因为拆分多字节序列将导致无效(子)字符串.)
只要你尝试类似的东西std::toupper( 'ß' ),在任何编码中,你就会陷入困境.(因为根本不可能使用标准库"正确"执行此操作,标准库只能提供一个结果字符,而不是"SS"此处所需的.)[1]另一个例子是std::tolower( 'I' ),根据语言环境应该产生不同的结果.在德国,'i'这是正确的; 在土耳其,'?'(LATIN SMALL LETTER DOTLESS I)是预期的结果.
然后有一点是标准库取决于运行软件的机器上支持的语言环境......如果不是,你会怎么做?
所以你真正想要的是一个能够正确处理所有这些的字符串类,但事实并非如此 std::basic_string<>.
(C++ 11注:std::u16string和std::u32string是更好的,但还不够完善.)
虽然Boost 看起来不错,但API智能,Boost.Locale基本上是ICU的包装器.如果使用ICU支持编译 Boost ...如果不是,则Boost.Locale仅限于为标准库编译的语言环境支持.
并且相信我,让 Boost与ICU一起编译可能是一个真正的痛苦.(Windows没有预编译的二进制文件,因此您必须将它们与您的应用程序一起提供,这会打开一整套新的蠕虫......)
所以我个人建议直接从马口获得完整的Unicode支持并直接使用ICU库:
#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/locid.h>
#include <iostream>
int main()
{
char const * someString = "Eidenges\xe4\xdf";
icu::UnicodeString someUString( someString, "ISO-8859-1" );
// Setting the locale explicitly here for completeness.
// Usually you would use the user-specified system locale.
std::cout << someUString.toLower( "de_DE" ) << "\n";
std::cout << someUString.toUpper( "de_DE" ) << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译(在此示例中使用G ++):
g++ -Wall example.cpp -licuuc -licuio
Run Code Online (Sandbox Code Playgroud)
这给出了:
eidengesäß
EIDENGESÄSS
Run Code Online (Sandbox Code Playgroud)
[1]在2017年,理事会对德国正字裁定"ẞ" U + 1E9E拉丁大写字母清音S可以正式使用,作为传统的"SS"转换旁边的一个选项,以避免歧义,例如在护照(其中名称是大写).我美丽的例子,由委员会决定过时了......
inc*_*ses 31
使用基于范围的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);
}
Run Code Online (Sandbox Code Playgroud)
Pat*_*hly 30
如果字符串包含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
小智 14
这是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;
}
Run Code Online (Sandbox Code Playgroud)
Gil*_* PJ 11
另一种使用基于范围的循环与参考变量的方法
string test = "Hello World";
for(auto& c : test)
{
c = tolower(c);
}
cout<<test<<endl;
Run Code Online (Sandbox Code Playgroud)
我自己的模板函数执行大写/小写。
#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;
}
Run Code Online (Sandbox Code Playgroud)
我写了这个简单的辅助函数:
#include <locale> // tolower
string to_lower(string s) {
for(char &c : s)
c = tolower(c);
return s;
}
Run Code Online (Sandbox Code Playgroud)
用法:
string s = "TEST";
cout << to_lower("HELLO WORLD"); // output: "hello word"
cout << to_lower(s); // won't change the original variable.
Run Code Online (Sandbox Code Playgroud)
据我所知,Boost库的性能非常糟糕.我已经测试了他们的unordered_map到STL,平均慢了3倍(最好的情况2,最差的是10次).此算法看起来也太低了.
差异是如此之大,以至于我确信你需要做的任何事情,tolower以使其等于提升"满足你的需求" 将比提升更快.
我已经在Amazon EC2上完成了这些测试,因此在测试过程中性能会有所不同,但您仍然可以理解.
./test
Elapsed time: 12365milliseconds
Elapsed time: 1640milliseconds
./test
Elapsed time: 26978milliseconds
Elapsed time: 1646milliseconds
./test
Elapsed time: 6957milliseconds
Elapsed time: 1634milliseconds
./test
Elapsed time: 23177milliseconds
Elapsed time: 2421milliseconds
./test
Elapsed time: 17342milliseconds
Elapsed time: 14132milliseconds
./test
Elapsed time: 7355milliseconds
Elapsed time: 1645milliseconds
Run Code Online (Sandbox Code Playgroud)
-O2 这样做:
./test
Elapsed time: 3769milliseconds
Elapsed time: 565milliseconds
./test
Elapsed time: 3815milliseconds
Elapsed time: 565milliseconds
./test
Elapsed time: 3643milliseconds
Elapsed time: 566milliseconds
./test
Elapsed time: 22018milliseconds
Elapsed time: 566milliseconds
./test
Elapsed time: 3845milliseconds
Elapsed time: 569milliseconds
Run Code Online (Sandbox Code Playgroud)
资源:
string str;
bench.start();
for(long long i=0;i<1000000;i++)
{
str="DSFZKMdskfdsjfsdfJDASFNSDJFXCKVdnjsafnjsdfjdnjasnJDNASFDJDSFSDNJjdsanjfsdnfjJNFSDJFSD";
boost::algorithm::to_lower(str);
}
bench.end();
bench.start();
for(long long i=0;i<1000000;i++)
{
str="DSFZKMdskfdsjfsdfJDASFNSDJFXCKVdnjsafnjsdfjdnjasnJDNASFDJDSFSDNJjdsanjfsdnfjJNFSDJFSD";
for(unsigned short loop=0;loop < str.size();loop++)
{
str[loop]=tolower(str[loop]);
}
}
bench.end();
Run Code Online (Sandbox Code Playgroud)
我想我应该在专用机器上进行测试但是我将使用这个EC2所以我真的不需要在我的机器上测试它.
小智 5
在不打扰std命名空间的情况下将字符串转换为loweercase的最简单方法如下
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;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
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";
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
826614 次 |
| 最近记录: |