Is there an inbuilt function to convert C++ string from upper case letters to lowercase letters ? If not converting it to cstring and using tolower on each char is the only option ?
Thank you very much in advance.
Is there an inbuilt function to convert C++ string from upper case letters to lowercase letters ? If not converting it to cstring and using tolower on each char is the only option ?
Thank you very much in advance.
If boost is an option:
#include <boost/algorithm/string.hpp> std::string str = "wHatEver"; boost::to_lower(str); Otherwise, you may use std::transform:
std::string str = "wHatEver"; std::transform(str.begin(), str.end(), str.begin(), ::tolower); You can also use another function if you have some custom locale-aware tolower.
tolower with a parameter that can't be cast to unsigned char results in UB. So what you probably want is something like: std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c){ return std::tolower(c); });std::transform(myString.begin(), myString.end(), myString.begin(), std::tolower); tolower in <cctype> and an overload in <locale>. If both get included, you'll get a compiler error. See for example: stackoverflow.com/questions/1350380/…transform answers) potentially cause undefined behaviour, because cstdlib's std::tolower requires a non-negative argumentLike ereOn says: std::transform(str.begin(), str.end(), str.begin(), std::tolower );
Or via for_each: std::for_each(str.begin(), str.end(), std::tolower );
Transform is probably better of the two.
I have an implementation I found it faster than std::transform , Compiled in g++ -03 Fedora 18. my example converts std::string
performance time in seconds : transform took : 11 s my implementation took : 2 s Test data size = 26*15*9999999 chars
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; } I will be glad to know if performance can be improved further.
if (*p >= 'A' && *p <=Z) *p += 'a' - 'A'. And you are still potentially missing many other letters e.g. 'Á'.cat /dev/urandom | LC_CTYPE=C tr -dc '[:alpha:]' | fold -w ${1:-100000000} | head -n 1, and you function is only a bit (10% faster than transform). Use the suggested if (*p >= 'A' && *p <=Z) *p += 'a' - 'A' and get 45-48% faster. Pass the char parameter by reference (not pinter) and get an additional 5% faster.