Function retruns string / assign function value to label
-
hi,
I have a function declare in my studentlist.h file:
@...
void studentName_Fun(QString nameV)
{
QSqlDatabase st1 = QSqlDatabase::database("con1");
if (st1.open())
{
QSqlQuery stQry(st1);
stQry.exec("SELECT name FROM students INNER JOIN selectedstudent ON selectedstudent.idstudent = student.idstudent;");
stQry.first();
QString nameV = stQry.value(0).toString();
qDebug()<< "value selected "<<nameV; // returns the name value; works, value is listed
}}
...@
and in my studentlist.cpp I would like to assign the value returned by my function to a qlabel. I checked the documentation and some other questions already addressed on the forum, but my function somehow doesn't return any value when it's called:
I call it using:
@...
QString nameStud;
studentName_Fun(nameStud);
ui->lbName->nameStud;
qDebug()<<"value returned "<<nameStud; //returns nil value and "QSqlQuery::value: not positioned on a valid record" repeated for more than 10 times
...@what could be wrong? thanks for your time
-
There are at least two problems here:
Using "void studentName_Fun(QString nameV)" creates a copy of the passed parameter'. So whateve you do within the function won't be visible to the outside.
Moreover, you have a local temporary variable names 'nameV' like the parameter, in the 'if' block even hiding that copy you already passed in.
You operate on three strings when you only want one.
To make that work, you need to pass a reference to the string you want to modify (i.e. " void studentName_Fun(QString & nameV)", note the "&"), and to avoid the shadow, i.e. use only "nameV = stQry.value(0).toString();", without the "QString " in front, which defines a new object.
-
andrep is right, but
@
nameV = stQry.value(0).toString();
@
will most certainly not work I guess, because you are trying to change the reference and not the value of that reference you pass to that function!?Best solution would be to just return a plain QString, since QString will only do a shallow copy it doesn't matter if even is the string is long.
If you prefer to use a reference or pointer parameter as the return value, just use the provided QString, e.g.
@
nameV.clear();
nameV.append(stQry.value(0).toString());
@ -
thank you both for your feedback.
passing the reference did the job; also I understand the difference between append and value(0).toString() and I will use it from now on;"QSqlQuery::value: not positioned on a valid record" error appeared because I didn't have data in my tables. - that's solved now.
if I would like to push a bit more this function and instead of having one parameters, I would like to have two, something like:
-
text2 to be the output of the function, and that could be name, first name, age, etc, everything to be returned from the same table using the same function
-
text1 to be the input: used from the .cpp file where the function is call.
my function proposal:
@...
void studentName_Fun(QString & text2, QString & text1)
{
QSqlDatabase st1 = QSqlDatabase::database("con1");
if (st1.open())
{
QSqlQuery stQry(st1);
stQry.exec("SELECT '"+text1+"' FROM students INNER JOIN selectedstudent ON selectedstudent.idstudent = student.idstudent;");
stQry.first();
text2.clear();
text2.append(stQry.value(0).toString());
qDebug()<< "value selected "<<text2; // for testing only
}}
...@
my function call:
@...
QString text3, text4;
text4 = "firstname";
studentName_Fun(text3, text4);
ui->lbRegistration->setText(text3);
qDebug()<<"value returned"<<text3; //for testing only
...@if I do this, the value selected and returned will be "firstname"; the query will not read and use my string.
who this should be done?the idea in the end is to use the same function for all the fields I would like to call, only by writing the call function steps in my .cpp file having the code simplified and all other advantages that comes with functions usability.
once again, thank you for your input.
-
-
If you need to return more fields, you should think about returning a data structure like a simple struct or class instead of values by reference. That would also be more readable if you have a struct with the matching members names instead of text1, text2, text3, text4.. very confusing. :D
why your function is not working for your "firstname" I don't know.
I've never used QSqlQuery myself, but I think there should be a better way to build queries with parameters and stuff you need, maybe use a prepares SQL statement. Just an idea it improves readable of your SQL query and code and also offers better performance.
-
Hi, I've used the prepare statement and it makes no difference in my example, not now.
I used text1, 2, etc, because I would like to have two parameters to call "name or first name or age or etc", anything in the function call that match this query join.
bq. " returning a data structure like a simple struct or class instead of values by reference. "
I'm not sure if I understand. could you please indicate me some details where I could find this?
is there a reason why not to call ref. values? and how exactly this could work in my case. thank you
-
Well returning multiple values with a structure or class is like the way to go in c++ (or many other languages) and is mostly done like this I think. I don't know how much experience you have with c++ or other object oriented programming languages?
maybe a very short and easy example:
@
// example struct to hold your data
struct Data {
QString name;
int age;
};// your modified function
Data studentName_Fun(const QString &query) const {
Data data;
// query your data and set it like this
data.name = "foo";
data.age = 123;
return data;
}// call the function
Data d = studentName_Fun("firstname");
qDebug() << d.name << d.age;
@
this method is more readable and flexible if you have to return more than 1 data type.
Also if you use reference parameters to return the values you need to create objects outside of the function and need to know their state and other things.. but if you want you can do it as you like. :)