2

Well, I'll try to explain. I have a Class named Calc that evaluate a string or const char* numeric expresion, like "2*(3/5)" or similars.

Now I am trying to build a calculator in Qt, using those class to evaluate the input of a QLineEdit.

The class works like that:

Calc(const std::string &sExpresion);
Calc(const char* cExpresion);

and

void anadirExpresion(const std::string &sExpresion);
void anadirExpresion(const char* cExpresion);

And I try to use it in Qt like that:

void Calculadora::evaluar()
{
    QLocale locale;
    QByteArray cadena = ui->pantalla->text().toLocal8Bit();
    const char* expresionAEvaluar = cadena.data();
    qDebug()<<"Cadena a evaluar: "<<cadena;
    std::cout<<"Cadena: "<<expresionAEvaluar<<std::endl;
    evaluador.anadirExpresion(expresionAEvaluar); //evaluador is the class Calc instance
    float resultado=evaluador.CalcularExpresion();
    qDebug()<<"Resultado: "<<resultado;
    ui->pantalla->setText(QString::number(resultado));    
}

This is a try to use the Class with a const char* expression

And this is the try with a std::string expression

void Calculadora::evaluar()
{
    //std::string cadena = ui->pantalla->text().toStdString();
    //qDebug()<<"Cadena a evaluar: "<<ui->pantalla->text();
    std::cout<<"Cadena: "<<ui->pantalla->text().toStdString()<<std::endl;
    evaluador.anadirExpresion(ui->pantalla->text().toStdString());
    float resultado=evaluador.CalcularExpresion();
    qDebug()<<"Resultado: "<<resultado;
    ui->pantalla->setText(QString::number(resultado));    
}

the problem is that I lose the data after "." character. If I have "2.3" the calculator perfoms "2" Furthermore, this problem is only in Linux, because in Qt under Windows it runs properly. And it works fine in console mode under Linux and Windows.

Also, the output in Qt console of qDebug() and std::cout show a properly string.

Suggestions?

Sorry for my poor english and thanks in advanced.

***Updating:

Definitively, I think that this error is because the function atof() compiled under Qt under linux doesn't works properly. I can sound senseless but, I was following the "2.5" value to looking for where it was changed, and it changed after that (into a member function of Calc)

EP[t].OP.operando=atof(aux);
std::cout<<"changed? "<<aux<<std::endl;
std::cout<<"changed: "<<EP[t].OP.operando<<std::endl;

Under console, EP[t].OP.operando value is "2.5" after atof() function. In Windows too. But in Linux, I get "2" value.

Now I have another try:

char cad[]="2.5";
EP[t].OP.operando=atof(cad);
std::cout<<"changed: "<<EP[t].OP.operando<<std::endl;

Under console, EP[t].OP.operando value = 2.5 , but under Qt is 2

Maybe a bug? Anyone to confirm that?

Thank you

2
  • you could parse the string for '.', store the parts separately, and then add them to a float variable. This would make the code work OK regardless of Windows, Linux etc. Commented Jun 12, 2014 at 8:52
  • I think that those problems could be fixed working with QStrings, but I would like to keep the original code of Class Calc. If not, probably with a depth adaptation, it would work fine in both platforms Commented Jun 12, 2014 at 10:05

3 Answers 3

1

I'm suspecting that locale kicks in. Probably your system locale is some European language where decimal separator is a comma, not a dot.

To verify my suspensions you can:

  • try use comma (,) as decimal separator during testing or
  • temporarily change your system locale to US (or other language where dot is decimal separator) and then rerun your software.
  • you can print in logs value of this variable (see documentation):

    qDebug() << "Decimal separator: " << localeconv()->decimal_point;
    

If I'm right then this is not a bug but a feature :).


I wrote some test application to verify my suspensions, and I was right, I wrote this slot:

void MainWindow::processText(const QString &txt)
{
    std::string s = txt.toStdString();
    std::stringstream stream(s);
    double x;
    x = std::atof(s.c_str());
    emit atofResultString(QString::number(x));
    if (stream >> x) {
        emit stdstreamResult(QString::number(x));
    }
}

I've tested this on Ubuntu 12.04 with Polish locale set. Result is that atof takes system locale into account.

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

1 Comment

That was my first guess.
0

Can you please tell whether the function evaluar() works fine when you have done:

QByteArray cadena = ui->pantalla->text().toLocal8Bit(); const char* expresionAEvaluar = cadena.data();

If it is working then I would suggest that you use same function for std::string also. This can be done using std::string::c_str().

So you can write ui->pantalla->text().toStdString().c_str().

However, converting between QString and const char* works best when you use the toLocal8bit() function as you have already done once.

2 Comments

Hello: function evaluar() doesn't works properly in both versions if there are decimals. I have try your suggestion to convert the std::string to const char* with c_str() method, but it doesn't work. The strings and const char* looks correctly. Even I write "2.5+Enter" and I get "Cadena: 2.5" (std::cout<<"Cadena: "<<ui->pantalla->text().toStdString()<<std::endl; or evaluador.anadirExpresion(ui->pantalla->text().toStdString().c_str()); and "Resultado: 2" (qDebug()<<"Resultado: "<<resultado;)
Also, QStrings can be converted to double directly. So use toDouble() method and then send use these values for calculations.
0

Thank you for you answer.

I tried to changed the environment of my program, adding a QLocale pointer and making that in the constuctor:

valor = new QLocale (QLocale::C,QLocale::UnitedStates);//valor is a QLocale pointer

I have changed this value for my country in explicit way:

valor = new QLocale (QLocale::Spanish,QLocale::Spain);

Also I tried to change between "." and "," for decimal points in both environment (Spain and USA)

After another headaches, you gave me the idea, for getting the float valor from a stringstream object, and not using atof() function.

std::stringstream ss(aux);
ss>>EP[t].OP.operando;

And now it works fine. Actually I haven't solve the problem (the Locale problem) but I get around that for fix it. Must I mark the post like SOLVED?

Thank you again!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.