How to convert std::string to lower case?

后端 未结 26 2043
旧时难觅i
旧时难觅i 2020-11-22 00:01

I want to convert a std::string to lowercase. I am aware of the function tolower(), however in the past I have had issues with this function and it

相关标签:
26条回答
  • 2020-11-22 00:22

    This could be another simple version to convert uppercase to lowercase and vice versa. I used VS2017 community version to compile this source code.

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

    Note: if there are special characters then need to be handled using condition check.

    0 讨论(0)
  • 2020-11-22 00:23

    std::ctype::tolower() from the standard C++ Localization library will correctly do this for you. Here is an example extracted from the 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";
    }
    
    0 讨论(0)
  • 2020-11-22 00:23

    Here's a macro technique if you want something simple:

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

    However, note that @AndreasSpindler's comment on this answer still is an important consideration, however, if you're working on something that isn't just ASCII characters.

    0 讨论(0)
  • 2020-11-22 00:24

    Since none of the answers mentioned the upcoming Ranges library, which is available in the standard library since C++20, and currently separately available on GitHub as range-v3, I would like to add a way to perform this conversion using it.

    To modify the string in-place:

    str |= action::transform([](unsigned char c){ return std::tolower(c); });
    

    To generate a new string:

    auto new_string = original_string
        | view::transform([](unsigned char c){ return std::tolower(c); });
    

    (Don't forget to #include <cctype> and the required Ranges headers.)

    Note: the use of unsigned char as the argument to the lambda is inspired by cppreference, which states:

    Like all other functions from <cctype>, the behavior of std::tolower is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. To use these functions safely with plain chars (or signed chars), the argument should first be converted to unsigned char:

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

    Similarly, they should not be directly used with standard algorithms when the iterator's value type is char or signed char. Instead, convert the value to unsigned char first:

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 00:25

    An alternative to Boost is POCO (pocoproject.org).

    POCO provides two variants:

    1. The first variant makes a copy without altering the original string.
    2. The second variant changes the original string in place.
      "In Place" versions always have "InPlace" in the name.

    Both versions are demonstrated below:

    #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);
    
    0 讨论(0)
  • 2020-11-22 00:26

    Copy because it was disallowed to improve answer. Thanks SO


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

    Explanation:

    for(auto& c : test) is a range-based for loop of the kind
    for (range_declaration:range_expression)loop_statement:

    1. range_declaration: auto& c
      Here the auto specifier is used for for automatic type deduction. So the type gets deducted from the variables initializer.

    2. range_expression: test
      The range in this case are the characters of string test.

    The characters of the string test are available as a reference inside the for loop through identifier c.

    0 讨论(0)
提交回复
热议问题