【问题标题】:tolower function for C++ stringsC++ 字符串的 tolower 函数
【发布时间】:2011-03-25 03:33:32
【问题描述】:

是否有将 C++ 字符串从大写字母转换为小写字母的内置函数?如果不将其转换为 cstring 并在每个字符上使用 tolower 是唯一的选择?

非常感谢您。

【问题讨论】:

  • 在德国,tolower("STRASSE") 应该导致“straße”。在瑞士,它应该是“strasse”。世界各地还有更多这样的案例。内置函数必须正确处理这些情况。如果您不在乎,只需在每个字符上使用 tolower() 即可,如大多数答案所示。
  • @Sjoerd:很好的例子。你听说过任何优雅地处理这些案例的图书馆吗?我可能对此感兴趣。
  • @ereOn:不,我从来不需要。我知道 tolower() 存在问题,但是在我居住的地方和我编写的应用程序中,tolower() 通常“足够好”。
  • 我认为 ICU 可以正确处理它 (icu-project.org),但对于 OP 的目的来说这可能是矫枉过正。
  • @ereOn:如果没有包含所有歧义词的字典,实际上几乎是不可能的。在德语中,SS只有在说慢的时候才会变成ß,否则就应该变成ss。

标签: c++ tolower


【解决方案1】:

我有一个实现,我发现它比 std::transform 更快,在 g++ -03 Fedora 18 中编译。我的示例转换 std::string

以秒为单位的表演时间: 转换耗时:11 秒 我的实施耗时:2 s 测试数据大小 = 26*15*9999999 个字符
inline void tolowerPtr(char *p) ;

inline void tolowerStr(std::string& s)
{char* c=const_cast<char*>(s.c_str());
size_t l = s.size();
  for(char* c2=c;c2<c+l;c2++)tolowerPtr(c2); 
};

inline void tolowerPtr(char *p) 
{
switch(*p)
{
  case 'A':*p='a'; return;
  case 'B':*p='b'; return;
  case 'C':*p='c'; return;
  case 'D':*p='d'; return;
  case 'E':*p='e'; return;
  case 'F':*p='f'; return;
  case 'G':*p='g'; return;
  case 'H':*p='h'; return;
  case 'I':*p='i'; return;
  case 'J':*p='j'; return;
  case 'K':*p='k'; return;
  case 'L':*p='l'; return;
  case 'M':*p='m'; return;
  case 'N':*p='n'; return;
  case 'O':*p='o'; return;
  case 'P':*p='p'; return;
  case 'Q':*p='q'; return;
  case 'R':*p='r'; return;
  case 'S':*p='s'; return;
  case 'T':*p='t'; return;
  case 'U':*p='u'; return;
  case 'V':*p='v'; return;
  case 'W':*p='w'; return;
  case 'X':*p='x'; return;
  case 'Y':*p='y'; return;
  case 'Z':*p='z'; return;
};
return ;
}

void testtransform( std::string& word )
{
std::string word2=word; 
time_t t;
time_t t2;
time(&t);
std::cout << "testtransform: start " << "\n";
int i=0;
for(;i<9999999;i++) 
{    word2=word;
    std::transform(word2.begin(), word2.end(), word2.begin(), ::tolower);
}
time(&t2);
std::cout << word2 << "\n";
std::cout << "testtransform: end " << i << ":"<< t2-t << "\n";
}

void testmytolower( std::string& word )
{
std::string word2=word; 
time_t t;
time_t t2;
time(&t);
std::cout << "testmytolower: start " << "\n";
int i=0;
for(;i<9999999;i++)
{   word2=word;
    cstralgo::tolowerStr(word2);
}
time(&t2);
std::cout << word2 << "\n";
std::cout << "testmytolower: end " << i << ":"<< t2-t << "\n";
}

int main(int argc, char* argv[])
{
   std::string word ="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   word =word+word+word+word+word+word+word+word+word+word+word+word+word+word+word;
   testtransform( word);
   testmytolower( word);
   return 0;
}

我很高兴知道性能是否可以进一步提高。

【讨论】:

  • 你只是在这里覆盖 ASCII 字母,而且以一种非常可怕的方式。同样可以通过:if (*p &gt;= 'A' &amp;&amp; *p &lt;=Z) *p += 'a' - 'A' 来实现。而且您仍然可能缺少许多其他字母,例如'Á'。
【解决方案2】:

对于这个问题可以使用STL的transform方法来解决:

std::string str = "simple";
std::transform(str.begin(), str.end(), str.begin(), std::tolower);

【讨论】:

    【解决方案3】:
    std::transform(myString.begin(), myString.end(), myString.begin(), std::tolower);
    

    【讨论】:

    • 这个和其他 transform + tolower 答案应该考虑到这不一定会编译,具体取决于该文件中包含的标准头文件。在&lt;cctype&gt; 中有一个tolower,在&lt;locale&gt; 中有一个过载。如果两者都包含,您将收到编译器错误。例如:stackoverflow.com/questions/1350380/…
    • 请注意,此答案(以及所有其他 transform 答案)可能会导致未定义的行为,因为 cstdlibstd::tolower 需要非否定参数
    【解决方案4】:

    如果boost 是一个选项:

    #include <boost/algorithm/string.hpp>    
    
    std::string str = "wHatEver";
    boost::to_lower(str);
    

    否则,您可以使用std::transform

    std::string str = "wHatEver";
    std::transform(str.begin(), str.end(), str.begin(), ::tolower);
    

    如果您有一些自定义区域设置感知tolower,您也可以使用其他函数。

    【讨论】:

      【解决方案5】:

      就像ereOn 说的: std::transform(str.begin(), str.end(), str.begin(), std::tolower );

      或通过 for_each: std::for_each(str.begin(), str.end(), std::tolower );

      Transform 可能是两者中更好的选择。

      【讨论】:

      • 我敢打赌。 for_each 不会改变 str。
      • 它被立即注销。您可以使用 lamda 为每个字符调用 tolow。
      【解决方案6】:

      没有内置函数可以执行此操作,而且执行起来非常复杂,因为 locales 等。如果tolower 能满足您的需求,那可能是您最好的选择。

      【讨论】:

        猜你喜欢
        • 2015-06-21
        • 1970-01-01
        • 2018-06-19
        • 2013-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-15
        相关资源
        最近更新 更多