14

I have noticed, Qt (4.8) changes the behaviour of sscanf(). Without Qt sscanf() works as usual, but with, it takes only localized strings.

Here's a minimized example:


Without Qt (plain C++)

int main(int argc, char *argv[])
{
    float f;
    sscanf("0.83", "%f", &f);

    std::cout << f << "\t-->\t" << typeid("0.83").name() << std::endl;

    return 0;
}

Output:

0.83    -->     A5_c

(given string is a 5x char-array, result correct)


With Qt

int main(int argc, char *argv[])
{
    /*
     * This breaks sscanf() for the whole (!) project
     * and linked libraries too!
     */
    QApplication(argc, argv);

    float f;
    sscanf("0.83", "%f", &f);

    std::cout << f << "\t-->\t" << typeid("0.83").name() << std::endl;

    return 0;
}

Output:

0       -->     A5_c

(Given string still a 5x char-array, but result is wrong)


While 0.83 fails, using 0,83 (my locale format) works fine with Qt - but fails without Qt (default behaviour). As shown by typeid(), there's no QString used - only plain old C(++) char-arrays. Btw., same happens to std::string.

Beside this, using a std::stringstream keeps working as normal:

std::stringstream ss;
ss << "0.83"; // But the value into the stream
ss >> f;      // Get a float out of it

Result:

0.83

And here comes the question: Why are char-array strings and sscanf() calls affected by Qt? I understand why QString's are localized, but breakingsscanf() (and potentially other stdio.h functions) sounds evil to me.

Background: I linked a (non-Qt) library, containing a sscanf() somewhere deep in the code, to a Qt project. Result: Some code failed in this project, while it worked everywhere else … (took some time to find the cause …)

ollo
  • 24,797
  • 14
  • 106
  • 155

3 Answers3

9

In general terms if you get a function, in the standard library, that has something to do with streams or I/O operations, chances are that it's gonna be affected by your locale settings.

This is true for sscanf and in your case Qt is overriding the default C locale that you usually get when using the default C/C++ configuration.

you should use

setlocale(LC_NUMERIC,"C")

right after initializing your Qt environment, in this case after QApplication.

https://qt-project.org/doc/qt-5/qcoreapplication.html#locale-settings

to set things back to what you expect .

user2485710
  • 9,451
  • 13
  • 58
  • 102
  • I see ... in some cases it may be a good thing, if locales are set per default, but in my case this caused *a conflict with POSIX functions* (as said in your link). However, setting back the locale works fine and doesn't brake gui components on the other hand. Thanks for this answer! – ollo Dec 13 '13 at 15:05
  • 1
    No, don't do that. Just call uselocale() before reading and writing saved data if you're using an ad-hoc text based format parsed by the standard C-library functions & then set it back to the user locale afterwards. – Phil Armstrong Oct 28 '14 at 20:59
2

I suspect QT sets the locale automatically based on your system locale. There's actually a standard localization library.

Setting the C locale changes the behavior of a bunch of functions, listed on this page.

Note however, that C++ streams do not automatically pick up the C locale, which is why your std::stringstream is behaving normally.

Collin
  • 11,977
  • 2
  • 46
  • 60
  • Very good point! I thought (string-)streams would use locales too, so this looked all odd to me. So is it in general safer to use those streams instead of e.g. `sscanf()` for such parsing things (which are not using any local format)? – ollo Dec 13 '13 at 15:09
  • 1
    You can always check the C locale if you need. Honestly, I have very little experience dealing with localized code, so I'm not sure of the pitfalls you might find. – Collin Dec 16 '13 at 13:58
2

Qt is calling setlocale to set the C runtuime to use your locale. You could try setting it back with setlocale(LC_ALL, “C”); but I'm not sure how that would affect the rest of Qt.

Roland Rabien
  • 8,750
  • 7
  • 50
  • 67
  • Thank you for this hint! I just checked gui components (like double spinboxes), they seem to keep their local format, while `sscanf()` works (again). – ollo Dec 13 '13 at 14:58