If query is empty code never executes. I tried this with multiple variations. Here is simple code.
mysqlpp::Query query = conn.query();
query << "SELECT * FROM users WHERE username= "
<< mysqlpp::quote_only << username
<< "AND password= "
<< mysqlpp::quote_only << password;
mysqlpp::StoreQueryResult res = query.store();
mysqlpp::StoreQueryResult::const_iterator it;
for (it = res.begin(); it != res.end(); ++it)
{
mysqlpp::Row row = *it;
if (!row.empty())
{
// user name and password match, log them in
std::cout << "You are logged" << std::endl;
// rest of code goes here
}
else if (row.empty()) // even just 'else' doesnt get executed
{
// no username or password that matches with user input
std::cout << "Wrong username or password" << std::endl;
// rest of code goes here
// this never get executed, and i have no idea why
}
}
How to check if row is empty? I tried almost anything i found in their reference manual, still nothing.
Related
I made this:
int querystate;
std::string pol;
std::string login;
std::cout << "login: ";
std::cin >> login;
pol = "select * from table where login = '" + login + "';";
querystate = mysql_query(conn, pol.c_str());
if (querystate != 0)
{
std::cout << mysql_error(conn);
}
res = mysql_store_result(conn);
while ((row = mysql_fetch_row(res)) != NULL)
{
std::cout << row[0] << " " << row[1] << " " << row[2];
}
It is possible to make something like this?
if (res == 0)
{
cout<<"there is 0 results";
}
I want to output text when query returns 0 results, for example:
there is no such login in the database.
First, your code is open to an SQL injection attack. You need to escape the login string using mysql_real_escape_string_quote(), eg:
std::string escapeStr(MYSQL *mysql, const std::string &str, char quoteChar)
{
std::string out((str.size()*2)+1, '\0');
unsigned long len = mysql_real_escape_string_quote(mysql, out.data(), str.c_str(), str.size(), quoteChar);
out.resize(len);
return out;
}
std::string pol = "select * from table where login = '" + escapeStr(conn, login, '\'') + "';";
Though, you really should be using a prepared statement instead, let MySQL handle the escaping for you.
Second, the mysql_query() documentation says:
To determine whether a statement returns a result set, call mysql_field_count(). See Section 5.4.23, “mysql_field_count()”.
Where the mysql_field_count() documentation says:
The normal use of this function is when mysql_store_result() returned NULL (and thus you have no result set pointer). In this case, you can call mysql_field_count() to determine whether mysql_store_result() should have produced a nonempty result. This enables the client program to take proper action without knowing whether the query was a SELECT (or SELECT-like) statement. The example shown here illustrates how this may be done.
See Section 3.6.8, “NULL mysql_store_result() Return After mysql_query() Success”.
And that last document says:
It is possible for mysql_store_result() to return NULL following a successful call to to the server using mysql_real_query() or mysql_query(). When this happens, it means one of the following conditions occurred:
There was a malloc() failure (for example, if the result set was too large).
The data could not be read (an error occurred on the connection).
The query returned no data (for example, it was an INSERT, UPDATE, or DELETE).
You can always check whether the statement should have produced a nonempty result by calling mysql_field_count(). If mysql_field_count() returns zero, the result is empty and the last query was a statement that does not return values (for example, an INSERT or a DELETE). If mysql_field_count() returns a nonzero value, the statement should have produced a nonempty result. See the description of the mysql_field_count() function for an example.
So, for example:
std::string login;
std::cout << "login: ";
std::cin >> login;
std::string pol = "select * from table where login = '" + escapeStr(conn, login, '\'') + "';";
if (mysql_query(conn, pol.c_str()) != 0)
{
std::cout << mysql_error(conn);
}
else if ((res = mysql_store_result(conn)) != NULL)
{
while ((row = mysql_fetch_row(res)) != NULL)
{
std::cout << row[0] << " " << row[1] << " " << row[2];
}
mysql_free_result(res);
}
else if (mysql_field_count(conn) == 0)
{
std::cout << "there are 0 results";
}
else
{
std::cout << mysql_error(conn);
}
Alternatively, the documentation also says:
An alternative is to replace the mysql_field_count(&mysql) call with mysql_errno(&mysql). In this case, you are checking directly for an error from mysql_store_result() rather than inferring from the value of mysql_field_count() whether the statement was a SELECT.
std::string login;
std::cout << "login: ";
std::cin >> login;
std::string pol = "select * from table where login = '" + escapeStr(conn, login, '\'') + "';";
if (mysql_query(conn, pol.c_str()) != 0)
{
std::cout << mysql_error(conn);
}
else if ((res = mysql_store_result(conn)) != NULL)
{
while ((row = mysql_fetch_row(res)) != NULL)
{
std::cout << row[0] << " " << row[1] << " " << row[2];
}
mysql_free_result(res);
}
else if (mysql_errno(conn) == 0)
{
std::cout << "there are 0 results";
}
else
{
std::cout << mysql_error(conn);
}
From the documentation available in this site https://dev.mysql.com/doc/c-api/5.7/en/mysql-fetch-row.html
When used after mysql_store_result(), mysql_fetch_row() returns NULL if there are no more rows to retrieve.
so use that to verify whether the data has rows or not. Since doing this once would have fetched a row already, you need to print them immediately before trying to get another row from the DB.
row = mysql_fetch_row(res)
if( row == NULL ) // This verifies whether data is NULL or not
cout << " There is no Results "<<endl
else {
do
{
std::cout << row[0] << " " << row[1] << " " << row[2];
}
while (row = mysql_fetch_row(res)) != NULL)
}
I am a beginning programmer and new to C++, and am looking to learn. This is what I have so far:
This psuedo-code version an instructor provided me:
if str.find("#")==string::npos OR <-- # not found
str.find(".")==string::npos OR <-- . not found
str.find(" ")!=string::npos) <-- space found
And my understanding of the function's requirements:
check emails for #, ., or space function,
if # exists, no output
if # doesn't exist, output "This (email) is invalid."
if . exists, no output
if ' ' exists, output "This (email) is invalid."
Here is my sorry attempt that doesn't work:
void Roster::printIncorrectEmails()
{
char at = '#';
char pd = '.';
char sp = ' ';
for (int i = 0; i < sizeof(RepoArray); i++) {
string email = Student::RepoArray.getEmailAddress();
size_t found = email.find(at, pd);
if (found != string::npos)
{
cout << "Invalid Email: " << email << '\n';
}
found = email.find(sp);
if (found == string::npos)
{
cout << "Invalid Email: " << email << '\n';
}
}
}
I've got plenty of other attempts too, if anyone cares to see them.
So I have been at this for days, and I have no idea why a BAD_ACCESS error is thrown. Sometimes it works, sometimes it doesn't.
void xmlParser::parseXML(string file){
tinyxml2::XMLDocument doc;
if(!doc.LoadFile(file.c_str()))
{
cout << "ERROR: TINYXML2 FAILED TO LOAD" << endl;
}
//XML FILE LAYOUT:
//<item>
// <type id="laserWeapon" name="Laser Rifle">
// <tooltip>
// <stats>
//</item>
//error seems to occur on this line
tinyxml2::XMLElement* elementType = doc.FirstChildElement("item")->FirstChildElement("type");
string id = elementType->Attribute("id");
string name = elementType->Attribute("name");
cout << "id: " << id << endl;
cout << "name: " << name << endl;
}
I use
xmlparser.parseXML(xmlparser.path+"laserRifle.xml");
to load the file. Should I be parsing this as a string, or is there some null ptr I'm neglecting? I've tried to do an 'if nullptr' clause, but it still turns out an error instead of skipping over it.
Any advice on what to do? I'm completely lost with this.
// item element can be missed and you'll get bad access. Do not chain your calls that way
tinyxml2::XMLElement* elementType = doc.FirstChildElement("item")->FirstChildElement("type");
// element type can be missed, as well as attributes id and name
string id = elementType->Attribute("id");
string name = elementType->Attribute("name");
cout << "id: " << id << endl;
cout << "name: " << name << endl;
}
Carefully check every element and attribute. Do not chain calls because every call can return null. If you check all nullptr cases you'll find your error
thanks for reading this question.
Basically I am trying to do a code that can achieve the following:
User will be shown a list of details like this
Terminal View:
Please select the department you want to add participant:
1. Admin
2. HR
3. Normal
4. Back to Main Menu
Selection: 3
normal's Department
UserID: 85 [ Name: Andrew, Department: normal ]
UserID: 86 [ Name: Jacky, Department: normal ]
UserID: 90 [ Name: Baoky, Department: normal ]
Current Selected Participant :
Usage:
Type exit to return to main menu
Type remove userid to remove participant
Type add userid to add participant
Selection:
Question is :
I want to be able to like let user add as many participant as he want until he decide to 'exit' to main menu, but how do i store it in a string participant.
How do I detect user input is 'remove userid'
or 'add userid' and then get the userid
e.g add 86
then he add 90
then he decided to remove 90
how do the string keep up with it
Below is my code:
do
{
cout << "Current Selected Participant : " << participant << endl;
cout << "" << endl;
do
{
if(counter>0)
{
//so it wont print twice
cout << "Usage: " << endl;
cout << "Type exit to return to main menu" << endl;
cout << "Type remove userid to remove participant" << endl;
cout << "Type add userid to add participant" << endl;
cout << "" << endl;
cout << "Selection: ";
}
getline(cin,buffer);
counter++;
}while(buffer=="");
if(buffer.find("remove"))
{
str2 = "remove ";
buffer.replace(buffer.find(str2),str2.length(),"");
if(participant.find(buffer))
{
//see if buffer is in participant list
buffer = buffer + ",";
participant.replace(participant.find(buffer),buffer.length(),"");
}
else
{
cout << "There no participant " << buffer << " in the list " << endl;
}
}//buffer find remove keyword
if(buffer=="exit")
{
done=true;
}
else
{
sendToServer = "check_account#"+buffer;
write (clientFd, sendToServer.c_str(), strlen (sendToServer.c_str()) + 1);
//see if server return found or not found
readFromServer = readServer (clientFd);
if(readFromServer=="found")
{
//add to participant list
participant += buffer;
participant += ",";
}
}//end if not exit
}while(done!=true);
Some users suggest i store in a string set, how do i store in a string set, and how do i make terminal able recognize keyword like 'remove' and 'add' in the selection
then get the user id which is seperate by a whitespace.
Next is how to remove if i store in a string set and how to push new value in.
Don't store it in a string. Store it in a collection that allows easy insertion and removal, like a std::set<int>. When the process has finished you can convert the set to whichever representation you feel you need.
Here's a very simple example (not checked to see if it compiles and runs; that's left as an exercise for the reader!)
void handle_command(const std::string& command, std::set<std::string>& userids)
{
if (command.substr(0, 4) == "add ")
{
std::string uid = command.substr(4);
if (userids.find(uid) == userids.end())
userids.insert(uid);
else
std::cout << "Uid already added" << std::endl;
return;
}
else
throw std::exception("Unsupported command, etc");
}
I have a map storing a "job" as a key and a "name" as the value it stores.
map<string, string>dutyAndJob;
map<string,string>::iterator it;
I'm basically trying to look through this map for a particular "name".
If the name isn't there, it shouldn't enter this loop, however, for some unknown reason, it always enters this loop:
string name = "Bob";
it = dutyAndJob.find(name);
if (it == dutyAndJob.end())
{
cout << "Testing : " << name << endl;
}
For some reason, it would still enter this loop even though there isn't a Bob stored in the map.
Any help would be greatly appreciated!
if (it == dutyAndJob.end())
{
cout << "Testing : " << name << endl;
}
should be:
if (it != dutyAndJob.end()) // Does it refer to a valid association
{
cout << "Testing : " << name << endl;
}
Notice the change from == to != indicating that the key was found in the map. The iterator it is only equal to dutyAndJob.end() if the key was not found.
Just realized that Job is the key, and Name is the data. The way you have it structured, you can only use find on the Job that will retrieve the Name.
string job = "Cashier";
it = dutyAndJob.find(job);
if (it == dutyAndJob.end())
{
cout << "Testing : " << job<< endl;
}
If you actually wanted to search by Name, maybe the Name should be the key, and the Job should be the data?