Qt doesn't read a string properly in Linux - c++

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

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.

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.

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!

Related

QString variable changed to QCharRef when i use pointers in method

Hello everyone I am trying to get to know pointers better and I stumbled into a Qt type change. I have made a QString array and gave the pointer to the array to a method. But when I try to use a QString functions it give a error and says that it is a QCharRef which does not have the member function isEmpty().
The code:
QString data_array[2][3] =
{
{"11:28:8","Room 1","Presence detected"},
{"11:38:8","Room 1","No presence"}
}
bool method(QString *_data_array)
{
QString *data_array = _data_array;
return data_array[0][1].isEmpty(); /* changed to QCharRef */
}
My question is why does this happen and how can I prevent it or change it?
The reason for which you are getting QCharRef is due to how QString is built. The [] operator returns one character from a QString (QString is built up from QChars, much like strings in C/C++ are character arrays). From the Qt documentation:
The return value is of type QCharRef, a helper class for QString. When you get an object of type QCharRef, you can use it as if it were a QChar &. If you assign to it, the assignment will apply to the character in the QString from which you got the reference.
So what that means for you is that when you use the lovely square bracket operators, you are no longer using a QString, you are using a QChar reference.
As for how to change it, QChar's isNull() seems like it would fit your uses. so instead try return data_array[0][1].isNull(); and that should work.
I would also look into QStringList if you're doing things with lists of strings

Trash characters when using buffers in c++

I have a DLL that I need to handle in C++. I'm using WxWidgets (standard compilation, but I also tried Unicode on/off) and NetBeans. I also tried dealing with this without WxWidgets (windows.h) and had same problems.
Here is how I access the DLL functions using WxWidgets:
// -------------------- POINTERS TO FUNCTIONS
typedef bool(*TYPE_DLL_SetLicense)(char*, char*);
typedef bool(*TYPE_DLL_PingConnection)(char*);
typedef char*(*TYPE_DLL_ERR_DESCRIPTION)(void);
class DLL_Library
{
public:
// pointers to functions inside dll
TYPE_DLL_SetLicense DLL_SetLicense; //initialize - will wor fine as it returns only true/false (buffer only provide data)
TYPE_DLL_PingConnection DLL_PingConnection; //ping to serwer. Will return trahs, becouse it uses buffer to provide data ang get answear back
TYPE_DLL_ERR_DESCRIPTION DLL_ERR_DESCRIPTION; //error description. No buffer, no trouble. Returns correct string.
wxDynamicLibrary dynLib2;
int initialize(void)
{
//patch to dll
wxString path = wxStandardPaths::Get().GetExecutablePath().BeforeLast('\\') + _("\\DLL_dll\\DLLMOK.dll");
if(!wxFile::Exists(path)) return -1;
//load dll
if(!dynLib2.Load(path)) return -2;
//Assign functions in dll to variable
DLL_SetLicense=(TYPE_DLL_SetLicense) dynLib2.GetSymbol(wxT("DLL_SetLicense"));
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
DLL_ERR_DESCRIPTION=(TYPE_DLL_ERR_DESCRIPTION) dynLib2.GetSymbol(wxT("DLL_ERROR_DESCRIPTION"));
return 0;
}
};
And here is the function I run. It should return and XML content, that I try to save to the file.
//DLL_PingConnection
//result ping to be save in file
wxFile file_ping_xml;
plik_ping_xml.Open(wxT("C:\\dll\\ping.xml"),wxFile::write);
char buffor_ping_xml[2000];
//I run the function here
bool is_ping = DLL_PingConnection(buffor_ping_xml);
if(is_ping)
{
tex_box->AppendText(wxT("DLL_PingConnection True\n"));
//we save result to file
bool is_write_ping_ok = file_ping_xml.Write(buffor_ping_xml,2000);
if (is_write_ping_ok){tex_box->AppendText(wxT("Save to file is ok ok\n"));}
else {tex_box->AppendText(wxT("Save to file failed :( \n"));}
}
else
{
tex_box->AppendText(wxT("DLL_PingConnection False\n"));
}
std::cout << "Error description: " << DLL_ERR_DESCRIPTION() << "\n"; //will work fine both in saving to file, and in streaming to screen.
The problem is that inside the file instead of good content I get rubbish like this:
NOTE that this only happens in functions that use buffers like:
char buffer[2000] //buffer will contain for example file xml
function do_sth_with_xml(buffer) //buffer containing xml will (should) be overwriten with xml results of the function - in our case DLL_PingCONNECTION should save in buffer xml with connection data
Documentation say that the DLL operates on Windows-1250. File ping.xml I have set to windows ANSI, but I don't think problem lies here.
EDIT: I have written problem without WxWidgets (I load DLL using windows.h) - same problems. Here is the code: Getting trash data in char* while using it as buffer in function . Please help :(
This
DLL_PingConnection=(TYPE_DLL_PingConnection)
shouldn't it be
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
?
seems otherwise you will not get a valid pointer to the function in the DLL.
as a general rule you should check return values, especially from a DLL
you load dynamically since it happens that you sometimes get another version
of the DLL which may have a function with same name but other signature or
where is missing entirely.
You named a function
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(....
and call it with
OSOZ.OSOZ_PingConnection(buffor_ping_xml);
you typedef a function
typedef bool(*TYPE_DLL_PingConnection)(char*);
you create a variable
char buffor_ping_xml[2000];
in your typedef it is char* and your buffor_ping_xml is char
how can that work ?
try
char *buffor_ping_xml = new char[2000];
/* or */
wchar_t *buffor_ping_xml = new wchar_t[2000];
/* or */
wxChar *buffor_ping_xml = new wxchar[2000];
bool is_ping = DLL_PingConnection(buffor_ping_xml);
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
write mystring to file.
To Do:
look in your wxwidgets\libs folder for your libs
are there libwxmsw29ud_* with a 'u' in the name (after version number here 29)?
If not You can not use unicode
If yes next steps
for all different test char *, wchar_t *, wxChar * give the files different name.
for example file_ping_xml.Open(wxT("C:\dll\ping_w_t_FromUTF8.xml"), ...
for wchar_t * in combination with
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
also in combination with
wxString mystring(buffor_ping_xml);
Then check out the look like, of the files in a browser .
To test you can go to your wxWidgets sample folder . Compile in the folder C:\wxWidgets\samples\docview\docview.cpp . Open with docview.exe a unicode file . How does it look.
Unicode download file
Unicode-related compilation settings
You should define wxUSE_UNICODE to 1 to compile your program in Unicode mode. This currently works for wxMSW, wxGTK, wxMac and wxX11. If you compile your program in ANSI mode you can still define wxUSE_WCHAR_T to get some limited support for wchar_t type.
Here is answear: Getting trash data in char* while using it as buffer in function.
Thanks everyone - expecially for patience.

ostringstream issues

when I use ostringstream, the only value that i get is : COM1
I have an application, which sends data.
I am using the code as :
std::ostringstream values;
values << someStruct.someValues;
...
...
std::string data
data << values.str();
But when I run this, all I get is an output saying COM1. My application is a DLL file.
But when I do this method below, I get the correct values
char *data;
char values[20];
sprintf(values, "%d",someStruct.someValue);
strcat(data,values);
But I don't want to use the above method as I have many variables that I need to fetch from the program. So someone please help.
std::string data;
data << values.str();
std::string is not a stream. It can't take operator<<. I'm surprised this code even compiles, but it almost certainly doesn't do something useful. What you want is this:
std::string data = values.str();

SFML add to sf::String?

So I've been using SFML lately and I was wondering how I could "add" to sf::String.
For example:
sf::String exampleText;
exampleText.SetText("I say: ");
exampleText += "Blah";
Result: "I say: Blah"
sf::string doesn't offer an append method which makes sense as it's intended to be a class for the graphical display of text rather than a traditional string class.
So you have to perform your string manipulation/append operations behind the scenes using your usual char array/string/stringstream classes and then call sf::string::SetText to update it.
sf::String exampleText;
exampleText.SetText("I say: ");
std::wstring toAppend(L"Blah");
exampleText.SetText(exampleText.GetUnicodeText() + toAppend);
Try that. I have never used sf though.
GetUnicodeText returns std::wstring. And by using the + it may work. Try it.
OR (now that I saw the sf docs better)
exampleText.SetText(exampleText.GetText() + "Blah");
GetText() returns std::string
SetText() Accepts both wstring and string

Qt tr does not seem to work on static constant members?

I'm working on translating our Qt gui at the moment.
I have the following code:
// header file
static const QString Foo;
// cpp file
const QString FooConstants::Foo = "foo";
// another cpp file
editMenu->addAction(tr(FooConstants::Foo));
This doesn't seem to work though.
That is, there is no entry in the .ts file for the above constant.
If I do this then it works:
// another cpp file
editMenu->addAction(tr("foo"));
However, this constant is used in many places, and I don't want to have to manually update each string literal. (if it were to change in the future)
Can anyone help?
Wrap your literal in the QT_TR_NOOP macro:
// cpp file
const QString FooConstants::Foo = QT_TR_NOOP("foo");
From the guide:
If you need to have translatable text completely outside a function, there are two macros to help: QT_TR_NOOP() and QT_TRANSLATE_NOOP(). They merely mark the text for extraction by the lupdate tool. The macros expand to just the text (without the context).
As Thomas mentioned, you have to use a macro.
The reason is that Qt doesn't know which strings to translate by default, it scans the files and looks for a set of patterns. One of them is tr("text"), but if you want to use a constant, you will have to mark it explicitly with QT_TRANSLATE_NOOP or QT_TR_NOOP when it's defined.
editMenu->addAction(tr(FooConstants::Foo));
I think your problem is that tr takes a char* argument, not a QString:
QString QObject::tr ( const char * sourceText, const char * disambiguation = 0, int n = -1 )
You could change the type of FooConstants::Foo, or convert it to a char* when you create the menu action, for example:
const QByteArray byteArray = FooConstants::Foo.toLatin1();
char *data = byteArray.data();
editMenu->addAction(tr(data));