ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

如果不遍历列表,您将如何将任何内容列表的每个元素转换为其他内容?字符串只是一个字符列表,如果您需要对每个字符应用一些函数,您将不得不遍历字符串。没办法。
为什么这个问题会降低评级?我在遍历我的字符串时没有问题,但我想问除了 tolower()、toupper() 等之外是否还有其他函数。
如果你有一个 C 风格的 char 数组,那么我想你可以将 ox20202020 添加到每个 4 个字符的块中(前提是它们都已经是大写的),一次将 4 个字符转换为小写。
@Dan:如果它们可能已经是小写字母,但绝对是 AZ 或 az,您可以使用 0x20 或而不是添加。几乎不值得的那些如此聪明的可能愚蠢的优化之一......
我不知道为什么它会被否决......当然它的措辞有点奇怪(因为你必须以某种方式遍历每个项目),但这是一个有效的问题

D
Deduplicator

改编自 Not So Frequently Asked Questions

#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 这样的多字节编码时。


(可能是旧的,有问题的算法变化不大)@Stefan Mai:调用 STL 算法有什么样的“大量开销”?这些函数相当精简(即简单的 for 循环)并且经常内联,因为您很少在同一个编译单元中对具有相同模板参数的同一个函数进行多次调用。
每次你假设字符是 ASCII 时,上帝就会杀死一只小猫。 :(
您的第一个示例可能具有未定义的行为(将 char 传递给 ::tolower(int)。)您需要确保不传递负值。
-1 这种使用 ::tolower 可能会崩溃,它是非 ASCII 输入的 UB。
在 tolower 之前需要 :: 以表明它在最外层的命名空间中。如果您在另一个命名空间中使用此代码,则可能会有不同的(可能不相关的) tolower 定义,最终会在没有 :: 的情况下被优先选择。
D
Deduplicator

Boost provides a string algorithm for this

#include <boost/algorithm/string.hpp>

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

Or, for non-in-place

#include <boost/algorithm/string.hpp>

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

非 ASCII-7 失败。
这很慢,请参阅此基准:godbolt.org/z/neM5jsva1
@prehistoricpenguin 慢?好吧,调试代码很慢,因为你自己的实现有一个错误,因为它比调用 boost 库更复杂;)如果代码很关键,比如调用了很多并且提供了瓶颈,那么,好吧,它可以是值得考虑缓慢
D
DevSolar

tl;博士

使用ICU library如果您不这样做,您的转换例程将在您可能甚至不知道存在的情况下静默中断。

首先您必须回答一个问题:您的 std::string编码是什么?是 ISO-8859-1 吗?或者也许是 ISO-8859-8?还是 Windows 代码页 1252? 您用于将大写转换为小写的任何东西都知道吗?(或者对于超过 0x7f 的字符它是否会失败?)

如果您使用 UTF-8 (the only sane choice among the 8-bit encodings) 和 std::string 作为容器,那么如果您认为您仍然可以控制事物,那么您已经在欺骗自己了。您将多字节字符序列存储在不了解多字节概念的容器中,并且您可以对其执行的大多数操作也不是!即使像 .substr() 这样简单的东西也可能导致无效(子)字符串,因为您在多字节序列的中间进行拆分。

一旦您尝试使用 any 编码的 std::toupper( 'ß' )std::tolower( 'Σ' ) 之类的东西,您就有麻烦了。因为 1),标准一次只对一个字符进行操作,所以它根本无法将 ß 转换为 SS 是正确的。并且 2),该标准一次只对一个字符进行操作,因此它无法确定 Σ 是在单词的中间(其中 σ 是正确的),还是在末尾(ς) .另一个示例是 std::tolower( 'I' ),它应该会产生不同的结果取决于区域设置 - 几乎在您期望的任何地方 i,但在土耳其 ı(拉丁小写字母 DOTLESS I)是正确答案(同样,在 UTF-8 编码中超过一个字节)。

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

然后有一点是,标准库的能力取决于运行您的软件的机器上支持哪些语言环境......如果您的目标语言环境不受支持,您会怎么做在您客户的机器上?

所以您真正要寻找的是一个能够正确处理所有这些问题的字符串类,不是任何std::basic_string<>变体< /强>。

(C++11 注意:std::u16stringstd::u32string 更好,但仍然不完美。C++20 带来了 std::u8string,但所有这些都是指定 encoding< /em>。在许多其他方面,他们仍然对 Unicode 机制一无所知,例如规范化、排序规则……)

虽然 Boost 看起来不错,但在 API 方面,Boost.Locale 基本上是对 ICU 的封装。 如果 Boost 是编译 ICU 支持...如果不是,Boost.Locale 仅限于为标准库编译的语言环境支持。

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

因此,我个人建议直接从马口中获得完整的 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> 的解决方案可以为您提供这一点。


这是一般情况下的正确答案。除了谎言和欺骗之外,该标准没有提供任何处理任何东西的东西,除了“ASCII”。它让你认为你也许可以处理 UTF-16,但你不能。正如这个答案所说,如果不进行自己的 unicode 处理,就无法获得 UTF-16 字符串的正确字符长度(不是字节长度)。如果您必须处理真实文本,请使用 ICU。谢谢,@DevSolar
ICU 是在 Ubuntu/Windows 上默认可用还是需要单独安装?另外这个答案怎么样:stackoverflow.com/a/35075839/207661
icu::UnicodeString::length() 从技术上讲也是在骗你(尽管频率较低),因为它报告的是 16 位代码单元的数量而不是代码点的数量。 ;-)
@masaers:完全公平地说,对于组合字符、零宽度连接符和从右到左标记之类的东西,代码点的数量相当没有意义。我将删除该评论。
@DevSolar 同意!长度的概念在文本上是毫无意义的(我们可以在违规者列表中添加连字)。也就是说,由于人们习惯于制表符和控制字符占用一个长度单位,因此代码点将是更直观的度量。哦,谢谢你给出正确的答案,很遗憾看到它这么远:-(
i
incises

使用 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);
}

但是,在法语机器上,该程序不会转换法语语言中允许的非 ASCII 字符。例如字符串'Test String123. É Ï\n' 将转换为:'test string123. É Ï\n' 尽管字符 É Ï 和它们的小写字母 'é' 和 'ï' 在法语中是允许的。该线程的其他消息似乎没有提供解决方案。
我认为您需要为此设置适当的语言环境。
@incises,然后有人发布了关于 ICU 的答案,这当然是要走的路。比尝试了解语言环境的大多数其他解决方案更容易。
我个人宁愿尽可能不使用外部库。
P
Patrick Ohly

如果字符串包含 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


一个工作的例子?
G
Gilson PJ

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

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

cout<<test<<endl;

我想它不适用于 UTF-8,是吗?
u
user2218467

这是 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;
}

这并没有为我将 Ä 调整为 ä
也可以在这里使用后插入迭代器而不是手动调整大小。
A
Atul Rokade

将字符串转换为小写而不用担心 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 之外的字符,则此代码为 UB。
R
Roger Stewart

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

POCO 提供了两种变体:

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

两个版本如下所示:

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

A
A-Sharabiani

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

#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.

B
Bo R

我自己的执行大写/小写的模板函数。

#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(), tolower);
    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(), toupper);
    return s2;
}

这就是我需要的。我只是将 towlower 用于支持 UTF-16 的宽字符。
a
akim

标准 C++ 本地化库中的 std::ctype::tolower() 将为您正确执行此操作。这是从 tolower reference page 中提取的示例

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

很好,只要您可以将字符转换到位。如果您的源字符串是 const 怎么办?这似乎使它有点混乱(例如,它看起来不像您可以使用 f.tolower() ),因为您需要将字符放入一个新字符串中。您会为运算符使用 transform() 和类似 std::bind1st( std::mem_fun() ) 的东西吗?
对于 const 字符串,我们可以只制作一个本地副本,然后将其转换到位。
是的,但是,制作副本会增加更多开销。
您可以将 std::transform 与不带指针的 ctype::tolower 版本一起使用。使用后插入迭代器适配器,您甚至无需担心预先调整输出字符串的大小。
太好了,特别是因为在 libstdc++ 的 tolowerlocale 参数中,对 use_facet 的隐式调用似乎是性能瓶颈。我的一位同事通过将 boost::iequals(存在此问题)替换为仅在循环外调用一次的版本,实现了 100% 的速度提升。
L
L. F.

由于没有一个答案提到即将推出的 Ranges 库,该库自 C++20 起在标准库中可用,并且目前作为 range-v3 单独提供 on GitHub,我想添加一种使用它执行此转换的方法。

要就地修改字符串:

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 启发的,它指出:

中的所有其他函数一样,如果参数的值既不能表示为 unsigned char 也不等于 EOF,则 std::tolower 的行为是未定义的。为了安全地使用普通字符(或有符号字符)这些函数,首先应将参数转换为无符号字符: char my_tolower(char ch) { return static_cast(std::tolower(static_cast(ch) ));同样,当迭代器的值类型是 char 或signed char 时,它们不应直接与标准算法一起使用。相反,首先将值转换为无符号字符: std::string str_tolower(std::string s) { std::transform(s.begin(), s.end(), s.begin(), // static_cast< int(*)(int)>(std::tolower) // 错误 // [](int c){ return std::tolower(c); } // 错误 // [](char c){ return std ::tolower(c); } // 错误 [](unsigned char c){ return std::tolower(c); } // 正确 );返回 s; }


h
hroptatyr

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

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

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

https://i.stack.imgur.com/DBIXl.png

代码看起来像这样......

#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 的方法相同。


“有一种方法可以在不进行 if 测试的情况下将大写字母转换为小写字母”听说过查找表吗?
负字符的未定义行为。
现代 CPU 的瓶颈是内存而不是 CPU。基准测试会很有趣。
A
Autodidact

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

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

C
Community

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

#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 对 this answer 的评论仍然是一个重要的考虑因素,但是,如果您正在处理的不仅仅是 ASCII 字符。


当存在完美的解决方案时,我不赞成使用宏来提供宏-您甚至可以提供这些解决方案。
宏技术意味着在编程中经常使用的东西的代码类型更少。为什么不使用它?否则,为什么有宏呢?
宏是 C 语言的遗留物,正在努力摆脱。如果要减少输入量,请使用函数或 lambda。 void strtoupper(std::string& x) { std::transform (x.begin(), x.end(), x.begin(), ::toupper); }
不,我不能。不过,Bjarne 在这个话题上的立场已经多次明确。此外,有很多理由不在 C 和 C++ 中使用宏。 x 可能是一个有效的表达式,它恰好编译正确,但由于宏的原因会给出完全虚假的结果。
@AquariusPower 我不同意。我还没有看到一个宏不能作为模板或 lambda 做得更好。
p
plugwash

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

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

字符串是如何编码的?纯ASCII? UTF-8?某种形式的扩展 ASCII 传统编码?无论如何,小写是什么意思?大小写映射规则因语言而异!你想要一些本地化到用户区域的东西吗?你想要在你的软件运行的所有系统上表现一致的东西吗?您是否只想将 ASCII 字符小写并通过其他所有字符?有哪些库可用?

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


9
9T9
// 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/


g
goulashsoup

复制,因为它不允许改进答案。谢谢所以

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

解释:

for(auto& c : test)
for (range_declaration:range_expression)loop_statement< /em>:

range_declaration: auto& c 这里的 auto 说明符用于自动类型推导。所以类型会从变量初始化器中扣除。 range_expression: test 本例中的范围是字符串test的字符。

字符串 test 的字符可通过标识符 c 用作 for 循环内的引用。


请澄清您从哪里复制答案。
D
Dmitry Kuzminov

C++ 没有为 std::string 实现 tolowertoupper 方法,但它可用于 char。可以轻松读取字符串的每个字符,将其转换为所需的大小写并将其放回字符串。不使用任何第三方库的示例代码:

#include<iostream>

int main(){
    std::string str = std::string("How IS The Josh");
    for(char &ch : str){
        ch = std::tolower(ch);
    }
    std::cout<<str<<std::endl;
    return 0;
}

对于字符串的基于字符的操作:For every character in string


B
Bu Saeed

试试这个功能:)

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;

}

这个功能很慢,不应该在实际项目中使用。
W
Waqar

使用 fplus 库中的 fplus::to_lower_case()

fplus API Search 中搜索 to_lower_case

例子:

fplus::to_lower_case(std::string("ABC")) == std::string("abc");

E
Edward Gaere

看看优秀的 c++17 cpp-unicodelib (GitHub)。它是单文件和仅标题。


#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à!

2022,c++17,一次又一次你必须访问stackoverflow检查另一个版本的tolower
D
DimanNe

Google 的 absl 库有 absl::AsciiStrToLower / absl::AsciiStrToUpper


r
rashedcs

代码片段

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

p
prehistoricpenguin

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

Facebook 的Folly

void toLowerAscii(char* str, size_t length)

谷歌的Abseil

void AsciiStrToLower(std::string* s);

T
The Oathman

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

#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

S
SHAYAK

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

#include<bits/stdc++.h>

using namespace std;

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


从不建议在 Stack Overflow 上的答案中使用 #include <bits/stdc++.h>。你会被否决。
P
Praveer Kumar

这可能是将大写转换为小写的另一个简单版本,反之亦然。我用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;
}

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


P
Phil

我尝试了 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;
}