QDoubleValidator accepts multiple decimal points - c++

I'm using a QDoubleValidator for my QLineEdit. The application locale (set in QtCreator) is QLocale::German.
Now when I enter a valid double (either using a dot or a comma as decimal separator) writing to the textedit as well as converting the string to a float works perfectly fine. But the validator also lets me write stuff with multiple decimal separators. Strings like 123.567,890 or ,,03.4... get validated but can't get converted into a float.
Is there a way to tell QDoubleValidator to only validate real numbers and not just strings without alphabetical characters?
I basically want to have a validator, that only validates strings, that can get converted to floats
using either the default locale or the german locale.

I have not used the QDoubleValidator so far but I could achieve such behaviour by using a QRegExpValidator:
QRegExpValidator* rxv = new QRegExpValidator(QRegExp("[+-]?\\d*[\\.,]?\\d+"), this);
lineedit->setValidator(rxv);

If you want only convert your content into the float and you don't want locale specifications, you can use QRegExpValidator with next deep regexp.
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?")));

Related

QLineEdit doubleValidator starting with point

I have a UI with a QLineEdit which only accepts float/double values with the help of a QDoubleValidator.
It only accepts values if I enter a leading number like: 0.234. But I'd prefer to be able to enter values directly without a leading number like .234. Unfortunately the QDoubleValidator does not accept a leading point. Is there any way to archive my goal with the help of the validator, or do I have to check every entered character myself? I'm using Qt 5.9.1 on Windows10.
QDoubleValidator* doubleValidator = new QDoubleValidator();
QLineEdit* lineEdit = new QLineEdit(frame);
lineEdit->setValidator(doubleValidator);
vbox->addWidget(lineEdit);
Unfortunately, QDoubleValidator is pretty limited, but you can use QRegExpValidator to get what you want with a regex describing a number, depending on the notation you expect.
// non-scientific floating-point numbers
QRegExp rx("[-+]?[0-9]*\\.?[0-9]+");
QRegExpValidator v(rx, 0);
QString s;
s = ".123";
v.validate(s, 0); // Returns Acceptable
This is much more extendable, and allows you to abstract it to any condition, with basic regular expression knowledge.

Decoding %E6%B0%94%E6%97%8B%E5%93%88%E5%88%A9.txt to a valid string

I am trying to decode a filename*= field of content disposition header. I get a string something like:
%E6%B0%94%E6%97%8B%E5%93%88%E5%88%A9.txt
What I have figured out that replacing % to \x works fine and I get the correct file name:
气旋哈利.txt
Is there a standard way of doing this in C++? Is there any library available to decode this?
I tried
boost::replace_all(name, "%x","\\x");
std::locale::generator gen;
std::locale locl = gen.generate("en_US.utf-8");
decoded_data = boost::locale::conv::from_utf( encoded_data, locl);
But it prints the replaced string instead of chinese characters.
\xE6\xB0\x94\xE6\x97\x8B\xE5\x93\x88\xE5\x88\xA9.txt
Any Idea where am I going wrong?
Replacing escape code like "\xE6" only work in string and character literals, not generally in strings. That's because it's handled by the compiler when it compiles the program.
However, it's not very hard to do yourself, using a simple loop that check for the '%' character, gets the next two characters and convert them to a number and use that number as a "character".

Why is _tcstod using my windows region settings when parsing a string?

Windows-related C++ question!
I'm trying to use _tcstod( ) to parse a string to obtain a float value. Normally, if I call
wchar_t* endPtr;
float result = static_cast<float>(_tcstod( "12.345678", &endPtr));
I get a float value of 12.345678 and endPtr behaves as expected. This actually misbehaves if I change my regional decimal delimiter in the Windows Region and Language settings. Specifically, if I change the decimal delimiter from "." to ",", suddenly _tcstod only returns a value of 12 rather than the whole thing. Anything after the . is chopped off.
Is there some way for me to parse the float value from the string while being agnostic to my Region settings?
Why is _tcstod using my windows region settings when parsing a string?
Because it is supposed to.
Is there some way for me to parse the float value from the string while being agnostic to my Region settings?
Of course. The simplest way, in C++, is to use a stringstream and imbue it with a default or "C" locale.

QLineEdit with no decimal point

I want the QLineEdit to accept only numbers without any decimal.e.g it should accept '456' but not '456.3434'.i.e. it should not allow decimal at all. Can anybody give some pointers that how can i do that.
I tried to use QIntValidator, but it still allows to enter decimal point, and when i convert the text from QLinEdit it returns zero (as it documentation says, if the conversion fails it will return zero).
I also tried to use QRegExpValidator( QRegExp("[0-9]"), but it allows only one number. There is no limit for the maximum number, how do i specify the QRegExp with minimum as 0 and maximum as undefined, if QRegExpValidator is the only way to achieve it ?
Thank you
You might try the following validator:
QLineEdit le;
le.setValidator(new QRegExpValidator(QRegExp("[0-9]+")));
le.show();
UPDATE
To allow input in exponential form you can try this:
le.setValidator(new QRegExpValidator( QRegExp("[0-9]+e[0-9]+")));

Incorrect conversion when decimal point embedded in VT_BSTR and German locale used

I have a piece of code(c++) that is writing some floating point values to excel like this:
...
values[ position ].bstrVal = formattedValue;
values[ position ].vt = VT_BSTR;
...
as you can see those floating point values are stored in the form of string and the decimal point is formatted in different ways, for example:
"110.000000", "20.11" etc. (this example is for English locale)
Now it works perfectly when English locale is used. However when I switch to German locale in the Control Panel the decimal point is changed to "," (and that's fine) but after passing those localized strings to Excel they are not correctly converted. For example in case of writing "110,000000" I'm getting 100 millions in excel. Other values like "20,11" stay as a text.
The only way to fix this is to overwrite the decimal point with "." in my program before writing to Excel. Any ideas why the conversion is not locale-aware when using VT_BSTR?
I should also add that I tried to switch the locale in my program from default one to German - still no luck.
Thank you in advance
It is never a good idea to let Excel guess at the value type. Do not use VT_BSTR, a currency value should be of variant type VT_CY. Assign the cyVal member with the value. It is an 8 byte integer value (int64 member of type LONGLONG), the currency amount multiplied by 10,000. Ten thousand :)