1

I have created my custom function to turn a wstring into lower case. However, it is pretty slow in DebugMode. Yes, I know ReleaseMode is what counts, but anyway it is pretty unnerving.

wstring wstringToLower(wstring u) { wstring s; for (int i=0;i<u.size();i++) { wstring sChar; sChar=u.substr(i,1); int iChar=static_cast<int>(sChar[0]); int iNewChar=charCodeToLower(iChar); wstring sNewChar=wstring(1,iNewChar); s.append(sNewChar); } return s; } 

Does anybody see anything obvious that I could improve to speed up the code, even in DebugMode?

Thank you!

4
  • 2
    stackoverflow.com/questions/313970/stl-string-to-lower-case - I'm afraid your function is about 50 times too complicated for what it does. Commented Nov 25, 2013 at 18:47
  • 2
    How about just using tolower for each character? Commented Nov 25, 2013 at 18:47
  • This belongs on codereview.stackexchange.com Commented Nov 25, 2013 at 18:47
  • @0x499602D2 I need to handle Unicode characters. Standard functions only handle ASCII. Commented Nov 25, 2013 at 18:48

3 Answers 3

7

There's no need to make temporary strings.

So, for start, instead of:

 wstring sNewChar=wstring(1,iNewChar); s.append(sNewChar); 

This should do the trick:

 s.push_back(iNewChar); 

Then, instead of:

 wstring sChar; sChar=u.substr(i,1); int iChar=static_cast<int>(sChar[0]); 

This should work:

 int iChar=static_cast<int>(u[i]); 

And, of course, as noted by Marcel, you can do everything on the passed copy, avoiding the extra string allocation.

Also, as noted in the comments: How to convert std::string to lower case? . Also, read all answers (and comments) here: how to Make lower case letters for unicode characters :

#include <algorithm> #include <string> #include <iostream> using namespace std; int main() { ::setlocale(LC_ALL,""); std::wstring data = L"НЕМАЊА БОРИЋ"; // Wide chars std::transform(data.begin(), data.end(), data.begin(), ::towlower); // prints немања борић std::wcout << data << std::endl; return 0; } 

http://en.cppreference.com/w/cpp/string/wide/towlower

Sign up to request clarification or add additional context in comments.

3 Comments

There is actually no need for s at all. He could do all the operations on u and return it and avoid the extra copy.
@ZacHowland you're totally right, I don't know how I missed it - just saw it in Marcel's answer.
@NemanjaBoric Thank you. ::setlocale(LC_ALL,""); You are great!
3

First of all I would avoid to allocate memory for variables each run, since allocating is a heavy operation.

Then do not call u.size() in the for-loop declaration. It will be called every loop otherwise. Every function call less that you call in a loop is a good win for performance.

Next everything Nemanja Boric said in the other answer.

And since the variable u is passed as copy, you can use it as return value and operate directly on it.

wstring wstringToLower(wstring u) { int size = u.size(); for (int i = 0; i < size; ++i) { u[i] = charCodeToLower(static_cast<int>(u[i])); } return u; } 

Conclusion: Basically avoid to allocate memory or calling functions in loops. Do just as much as you really have to.

Comments

0

There is actually no need for the wstringToLower function at all. You can use <algorithm> to do most of the work:

std::wstring str = "Some String"; std::transform(str.begin(), str.end(), str.begin(), ::towlower); 

If you are trying to localize it, you may want to modify it slightly:

std::wstring str = "Some String"; std::locale loc; // set your locale std::transform(str.begin(), str.end(), str.begin(), [](wchar_t c) { return use_facet<ctype<wchar_t>>(loc).tolower(c); }); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.