Simple Character Validation in C++ - c++

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.

Related

Mysql.h 0 results after query

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)
}

Logic error when getting output from encrypting string program.

I have made a program that takes a string into a class EncryptedString then encrypts said string removing anything that is not a space or a lower or uppercase letter. Everything seems to be working fine until I enter a string with something like 496496#####!#!!!4 then it deletes some, and keeps others. I have some examples of what is supposed to be output.
Input: Hello World!
Expected Decrypted: Hello World
Expected Encrypted: Ifmmp Xpsme
Output Decrypted: Hello World
Output Encrypted: Ifmmp Xpsme
Hello World works, just fine and deletes the !
However when I try to do "A apple ran away in autumn z!!14? I get this
Input: A apple ran away in autumn z!!14?
Expected Decrypted: A apple ran away in autumn z
Expected Encrypted: B bqqmf sbo bxbz jo bvuvno a
Output Decrypted: A apple ran away in autumn z 3
Output Encrypted: B bqqmf sbo bxbz jo bvuvno a!4
And here is one more example.
Input: Emily Dickinson1152163!!!#####!!!
Expected Decrypted: Emily Dickinson
Expected Encrypted: Fnjmz Ejeljotpo
Output Decrypted: Emily Dickinson015 ??
Output Encrypted: Fnjmz Ejdljotpo126!!##!!
I thought it may be that when I am iterating the code over decrypt.length() and enCry.length() it's going over the elements? However, I felt like it wasn't that as it's able to delete other numbers and symbols just fine but for some reason, some are staying. Is there something wrong with my code below during my iterations that can cause this?
//This function takes the phrase,word or sentence and encrypts it, removing any illegal characters aside from ' ' and then proceeds to decrypt it then output them to the get functions.
void EncryptedString::set(string str)
{
char chBase = 'A';
string enCry = str;
for (int i = 0; i < enCry.length(); i++)
{
char ch = enCry[i];
if (enCry[i] < chBase && enCry[i] != ' ')
{
enCry.erase(enCry.begin() + i);
}
else if (enCry[i] > chBase + 25 && enCry[i] < tolower(chBase) && enCry[i] != ' ')
{
enCry.erase(enCry.begin() + i);
}
else if (enCry[i] > tolower(chBase + 25) && enCry[i] != ' ')
{
enCry.erase(enCry.begin() + i);
}
else
{
if (enCry[i] == chBase + 25)
{
enCry[i] = 'A';
}
else if (enCry[i] == tolower(chBase) + 25)
{
enCry[i] = 'a';
}
else if (enCry[i] == ' ')
{
enCry[i] = ' ';
}
else
{
enCry[i] = ch + 1;
}
}
}
EncryptedString::encryption = enCry;
string decrypt = enCry;
for (int i = 0; i < decrypt.length(); i++)
{
char ch = decrypt[i];
if (decrypt[i] == 'A')
{
decrypt[i] = 'Z';
}
else if (decrypt[i] == 'a')
{
decrypt[i] = 'z';
}
else if (decrypt[i] == ' ')
{
decrypt[i] = ' ';
}
else
{
decrypt[i] = ch - 1;
}
}
decrypted = decrypt;
}
//This function outputs the decryption after the phrase was encrypted.
const string EncryptedString::get()
{
return decrypted;
}
//This function outputs the encryption of the phrase.
const string EncryptedString::getEncrypted()
{
return EncryptedString::encryption;
}
As some more information here is what is in main.cpp where I am using these functions. I thought maybe it was because I was setting it twice in test2 but I tested test1 by adding numbers to hello world and that output just kept some of the numbers with it. If you need to see that example I will provide.
#include "EncryptedString.h"
#include <windows.h>
int main()
{
cout << "TEST 1" << endl << endl;
EncryptedString test1("Hello World!");
cout << test1.get();
cout << endl << endl;
cout << test1.getEncrypted();
cout << endl << endl << "TEST 2" << endl << endl;
EncryptedString test2;
test2.set("A apple ran away in autumn z!!14?");
cout << endl << endl;
cout << test2.get();
cout << endl << endl;
cout << test2.getEncrypted();
cout << endl << endl;
test2.set("Emily Dickson1152163!!!#####!!!");
cout << test2.get() << endl << endl << test2.getEncrypted();
//being used for me to see the output.
Sleep(15000);
}
If someone can see where I went wrong or if maybe something is off with my iteration I'd be grateful. Thank anyone for reading all of this as I know it's probably a lot and thank you for any help that you can give me. Also would this be considered a logic error or structure error? I believe logic but I could be wrong and I would like to know so I don't make that mistake in the future when asking for help.

missing data in popen call

my program compiles without error and appears to run through all of the steps correctly. It is supposed to make a php call and return data. tcpdump does show the request going out so popen is being executed, but the receiving party never updates.
The only discrepancy I can find, is that the command variable appears to be missing data.
# .trol.o
market max price is 0.00638671 at position 0
php coin.php 155 0.006387
0.00638672
the second line in the output is the command I am sending to popen
cout << command << endl; -> php coin.php 155 0.006387
that number is supposed to be the same as the one under it 0.00638672
The number 6 and the number 2 have been chopped off somehow.
How do I get the correct data into my popen command?
code:
void mngr(){
//vector defs
vector<std::string> buydat;
vector<std::string> markdat;
vector<std::string> pricedat;
vector<std::string> purchaseid;
vector<double> doublePdat;
vector<double> doubleMdat;
doublePdat.reserve(pricedat.size());
doubleMdat.reserve(markdat.size());
char buybuff[BUFSIZ];
char command[70];
char sendbuy[12];
buydat = getmyData();
markdat = getmarketbuyData();
//string match "Buy" and send results to new vector with pricedat.push_back()
for(int b = 2; b < buydat.size(); b+=7){
if ( buydat[b] == "Buy" ) {
pricedat.push_back(buydat[b+1]);
}
}
transform(pricedat.begin(), pricedat.end(), back_inserter(doublePdat), [](string const& val) {return stod(val);});
transform(markdat.begin(), markdat.end(), back_inserter(doubleMdat), [](string const& val) {return stod(val);});
auto biggestMy = std::max_element(std::begin(doublePdat), std::end(doublePdat));
std::cout << "my max price is " << *biggestMy << " at position " << std::distance(std::begin(doublePdat), biggestMy) << std::endl;
auto biggestMark = std::max_element(std::begin(doubleMdat), std::end(doubleMdat));
std::cout << "market max price is " << *biggestMark << " at position " << std::distance(std::begin(doubleMdat), biggestMark) << std::endl;
if (biggestMy > biggestMark){
cout << "Biggest is Mine!" << endl;
}
else if (biggestMy < biggestMark){
//cout << "Biggest is market!";
*biggestMark += 0.00000001;
sprintf(sendbuy,"%f",*biggestMark);
sprintf(command, "php coin.php 155 %s",sendbuy);
FILE *markbuy = popen(command, "r");
if (markbuy == NULL) perror ("Error opening file");
while(fgets(buybuff, sizeof(buybuff), markbuy) != NULL){
size_t h = strlen(buybuff);
//clean '\0' from fgets
if (h && buybuff[h - 1] == '\n') buybuff[h - 1] = '\0';
if (buybuff[0] != '\0') purchaseid.push_back(buybuff);
}
cout << command << endl;
cout << *biggestMark << endl;
}
}
I would try to use long float format instead of float as the type of biggestMark should be evaluated as iterator across doubles. I mean try to change sprintf(sendbuy,"%f",*biggestMark); to sprintf(sendbuy,"%lf",*biggestMark);. Hope this would help.

c++ mysql++ if query is empty code never executes, but it should

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.

const char * changing value during loop

I have a function that iterates through a const char * and uses the character to add objects to an instance of std::map if it is one of series of recognized characters.
#define CHARSEQ const char*
void compile(CHARSEQ s) throw (BFCompilationError)
{
std::cout << "#Receive call " << s << std::endl;
for(int i = 0; s[i] != '\0'; i++)
{
if (std::string("<>-+.,[]").find_first_of(s[i]) == std::string::npos)
{
throw BFCompilationError("Unknown operator",*s,i);
}
std::cout << "#Compiling: " << s[i] << std::endl;
std::cout << "#address s " << (void*)s << std::endl;
std::cout << "#var s " << s << std::endl;
controlstack.top().push_back(opmap[s[i]]);
}
}
The character sequence passed is "++++++++++."
For the first three iterations, the print statements display the expected values of '+', '+', and '+', and the value of s continues to be "+++++++++++.". However, on the fourth iteration, s becomes mangled, producing bizarre values such as 'Ð', 'öê', 'cR ', 'œk' and many other character sequences. If the line that throws the exception is removed and the loop is allowed to continue, the value of s does not change after again.
Other functions have access to s but since this is not a multithreaded program I don't see why that would matter. I am not so much confused about why s is changing but why it only changes on the fourth iteration.
I have searched SO and the only post that seems at all relevant is this one but it still doesn't answer my question. (Research has been difficult because searching "const char* changing value" or similar terms just comes up with hundreds of posts about what part of is is const).
Lastly, I know I should probably be using std::string, which I will if no answers come forth, but I would still like to understand this behavior.
EDIT:
Here is the code that calls this function.
CHARSEQ text = load(s);
std::cout << "#Receive load " << text << std::endl;
try
{
compile(text);
}
catch(BFCompilationError& err)
{
std::cerr << "\nError in bf code: caught BFCompilationError #" << err.getIndex() << " in file " << s << ":\n";
std::cerr << text << '\n';
for(int i = 0; i < err.getIndex(); i++)
{
std::cerr << " ";
}
std::cerr << "^\n";
std::cerr << err.what() << err.getProblemChar() << std::endl;
return 1;
}
Where load is:
CHARSEQ load(CHARSEQ fname)
{
std::ifstream infile (fname);
std::string data(""), line;
if (infile.is_open())
{
while(infile.good())
{
std::getline(infile,line);
std::cout << "#loading: "<< line << '\n';
data += line;
}
infile.close();
}
else
{
std::cerr << "Error: unable to open file: " << fname << std::endl;
}
return std::trim(data).c_str();
}
and the file fname is ++++++++++. spread such that there is one character per line.
EDIT 2:
Here is an example of console output:
#loading: +
#loading: +
#loading: +
#loading: +
#loading: +
#loading: +
#loading: +
#loading: +
#loading: +
#loading: +
#loading: .
#Receive load ++++++++++.
#Receive call ++++++++++.
#Compiling: +
#address s 0x7513e4
#var s ++++++++++.
#Compiling: +
#address s 0x7513e4
#var s ++++++++++.
#Compiling: +
#address s 0x7513e4
#var s ++++++++++.
#Compiling:
#address s 0x7513e4
#var s ßu
Error in bf code: caught BFCompilationError #4 in file bf_src/Hello.txt:
ßu
^
Unknown operatorß
Your load function is flawed. The const char* pointer returned by c_str() is valid only until the underlying std::string object exists. But data is a local variable in load and is cleared after return. Its buffer is not overwritten by zeroes but left as it were as free memory. Therefore printing out the value immediately after returning is likely to work but your program may put new values there and the value pointed by your pointer will change.
I suggest to use std::string as the return value of load as a workaround.