tmighty
tmighty

Reputation: 11409

C++ Code optimization

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!

Upvotes: 1

Views: 199

Answers (3)

Marcel Blanck
Marcel Blanck

Reputation: 866

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.

Upvotes: 3

Zac Howland
Zac Howland

Reputation: 15870

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

Upvotes: 0

Nemanja Boric
Nemanja Boric

Reputation: 22187

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

Upvotes: 7

Related Questions