This is a text-only version of the following page on https://raymii.org: --- Title : std::string to lowercase or uppercase in C++ Author : Remy van Elst Date : 07-11-2019 URL : https://raymii.org/s/snippets/std_string_to_lowercase_or_uppercase_in_cpp.html Format : Markdown/HTML --- I'm using [codewars][9] to practice my development skills. Today I learned a method to transform a std::string's casing, either to uppercase or lowercase. It uses a lambda and does loop over all characters in the string. Researching it further, I also found out how to do unicode strings with Boost. This article also includes a mini howto on installing Boost on Windows 10 via `mingw` for use with CLion.

Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below:

I'm developing an open source monitoring app called Leaf Node Monitoring, for windows, linux & android. Go check it out!

Consider sponsoring me on Github. It means the world to me if you show your appreciation and you'll help pay the server costs.

You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $200 credit for 60 days. Spend $25 after your credit expires and I'll get $25!

### Case transformation for ascii The codewars assignment was to count unique lowercase characters in a string, then return the character which was found the most. For the string "hello" this would be `l` since it's found twice. To do this I first needed to convert the string to lowercase. This is the code I used to lowercase the string for the codewars practice: int main() { std::string inStr = "UPPERCASE"; std::transform(inStr.begin(), inStr.end(), inStr.begin(), [](unsigned char c){ return std::tolower(c); }); std::cout << inStr << std::endl; return 0; } Example output: #C:\Users\Remy\CLionProjects\test1\cmake-build-debug\src\example.exe uppercase For uppercase: int main() { std::string inStr = "lowercase"; std::transform(inStr.begin(), inStr.end(), inStr.begin(), [](unsigned char c){ return std::toupper(c); }); std::cout << inStr << std::endl; return 0; } Example output: #C:\Users\Remy\CLionProjects\test1\cmake-build-debug\src\example.exe LOWERCASE ### Non-ASCII Remember: everytime you assume text is ASCII, a kitten dies somewhere. The code above does not work with [Emoji's][1]: std::string inStr = "\U0001F4A9 "; std::transform(inStr.begin(), inStr.end(), inStr.begin(), [](unsigned char c){ return std::tolower(c); }); std::cout << inStr << std::endl; This won't give the expected result. I'm using an image since your browser will probably not render this correctly: ![img][3] A unicode string like [a common german word][7] will also not work, same kind of weird output. But, with Boost and ICU you can get this to work. The setup is difficult, but when you have it compiling and working, it's a pleasure to work with. You can just pass entire strings instead of looping over every character. ### Boost Boost is a set of libraries for C++ development, of which most end up in the standard library after a few years. To include Boost in your [cmake project][2], either install it with your package manager or download it manually. #### Installing Boost on Windows 10 or Ubuntu On Ubuntu 18.04 it's as simple as: apt-get install libboost-dev-all TL;DR: On Windows 10 use [this mingw build][6] or __be warned. Here be dragons.__ It cost me multiple hours of troubleshooting and debugging. Appearantly `mingw` and Boost on Windows are not the best of friends. Especially not if you also need `Locale`, then `libICU` is required as well. If you use Visual Studio and MSVC or CLion with MSVC instead of `Mingw` it all should be less problematic. `libICU` provides downloads for `MSVC`, for `MinGW` you're on your own, good luck with compiling. Open a cmd, navigate to the folder and build Boost. If you have visual studio installed you can use that, I use `mingw` so I have to specify that and I have to run a `mingw` cmd prompt (via the .bat file provided by mingw). Make sure to have `g++` available as command: C:\Users\Remy\Downloads\boost_1_71_0\boost_1_71_0>g++ --version g++ (i686-posix-sjlj, built by strawberryperl.com project) 4.9.2 Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Bootstrap: C:\Users\Remy\Downloads\boost_1_71_0\boost_1_71_0>bootstrap.bat gcc Building Boost.Build engine Generating Boost.Build configuration in project-config.jam for msvc... Bootstrapping is done. To build, run: .\b2 [...] Build: b2 toolset=gcc [lots and lots of compiling later] 1 file(s) copied. ...failed updating 666 targets... ...skipped 204 targets... ...updated 1573 targets... Install: b2 toolset=gcc install This will install into `C:\Boost` and the `findBoost` cmake package will detect it. If you specify a different folder, you need to set `BOOST_ROOT` as environment variable or pass it to cmake. In your `CMakeLists.txt` file the following options might help with debugging if you get errors: set (Boost_DEBUG ON) set (Boost_ARCHITECTURE "-x32") set (Boost_USE_STATIC_LIBS ON) set (Boost_USE_MULTITHREADED ON) set (Boost_DETAILED_FAILURE_MSG ON) Do note that I spent a few hours fiddling and trying to get the `boost.Locale` library to compile. I ended with a linker error: C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/ ../../../../i686-w64-mingw32/lib/../lib/libiconv.a(localcharset.o):localcharset.c :(.text+0x73): undefined reference to `_imp__GetACP@0' Due to not having `libicu` installed. As stated earlier, I gave up due to ICU as far as I could find only providing MSVC compatible builds, not `MinGW` builds. Continue on with this guide on a Linux system if you want to follow along, or use CLion with MSVC instead of MinGW. __Update after another few hours of debugging:__ when using [this build of mingw][6] by Stephan T. Lavavej, the code and cmake does compile and link without errors. #### Boost in your CMakeLists file If you've followed [my setup guide for CMake][2] then you should add this to the main root-folder `CMakeLists.txt` file right before `include_directories`: find_package(Boost REQUIRED COMPONENTS locale) if(Boost_FOUND) include_directories(${Boost_INCLUDE_DIR}) message("-- Boost found: ${Boost_VERSION_STRING}") else() message(FATAL_ERROR "Boost not found!") endif() In the `src/CMakeLists.txt` file, add the following at the bottom: if(Boost_FOUND) target_link_libraries (${BINARY} ${Boost_LIBRARIES}) message("-- Boost link to: ${Boost_VERSION_STRING}") else() message(FATAL_ERROR "Boost not found!") endif() If all went well, your CMake output should include the two new messages: -- Boost found: 1.71.0 -- Boost link to: 1.71.0 -- Configuring done -- Generating done -- Build files have been written to: C:/Users/Remy/CLionProjects/test1/cmake-build-debug ### Boost locale conversion code This is the code I used with Boost to convert uppercase to lowercase: boost::locale::generator gen; std::locale loc=gen(""); std::locale::global(loc); std::cout.imbue(loc); std::string grussen = "grussEN"; std::string poopla = "\U0001F4A9"; std::cout <<"Upper "<< boost::locale::to_upper(grussen) << std::endl <<"Lower "<< boost::locale::to_lower(grussen) << std::endl <<"Title "<< boost::locale::to_title(grussen) << std::endl <<"Fold "<< boost::locale::fold_case(grussen) << std::endl <<"Poop "<< boost::locale::to_lower(poopla) << std::endl; It's mostly [example code from Boost][8]. My static site generator doesn't like the german S and U, it will not render it correctly. Here's a picture of the code: ![boost1][4] The result works as you would expect: ![boost2][5] [1]: https://xn--ls8h.la/ [2]: /s/tutorials/Cpp_project_setup_with_cmake_and_unit_tests.html [3]: /s/inc/img/boost-fail1.png [4]: /s/inc/img/boost-fail3.png [5]: /s/inc/img/boost-fail2.png [6]: https://nuwen.net/mingw.html [7]: https://en.wiktionary.org/wiki/gr%C3%BC%C3%9Fen [8]: https://www.boost.org/doc/libs/1_71_0/libs/locale/doc/html/conversions_8cpp-example.html [9]: https://www.codewars.com/r/KjbvJA --- License: All the text on this website is free as in freedom unless stated otherwise. This means you can use it in any way you want, you can copy it, change it the way you like and republish it, as long as you release the (modified) content under the same license to give others the same freedoms you've got and place my name and a link to this site with the article as source. This site uses Google Analytics for statistics and Google Adwords for advertisements. You are tracked and Google knows everything about you. Use an adblocker like ublock-origin if you don't want it. All the code on this website is licensed under the GNU GPL v3 license unless already licensed under a license which does not allows this form of licensing or if another license is stated on that page / in that software: This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Just to be clear, the information on this website is for meant for educational purposes and you use it at your own risk. I do not take responsibility if you screw something up. Use common sense, do not 'rm -rf /' as root for example. If you have any questions then do not hesitate to contact me. See https://raymii.org/s/static/About.html for details.