Using a variable in a mysql query, in a C++ MFC program - c++

After extensive trawling of the internet, I still haven't found any solution for this problem.
I'm writing a small C++ app that connects to an online database and outputs the data in a listbox.
I need to enable a search function using an edit box, but I can't get the query to work while using a variable.
My code is:
res = mysql_perform_query (conn, "select distinct artist from Artists");
//res = mysql_perform_query (conn, "select album from Artists where artist = ' ' ");
while((row = mysql_fetch_row(res)) != NULL){
CString str;
UpdateData();
str = ("%s\n", row[0]);
UpdateData(FALSE);
m_list_control.AddString(str);
}
The first "res =" line is working fine, but I need the second one to work. I have a member variable m_search_edit set up for the edit box, but any way that I try to include it in the sql statement causes errors.
eg.
res = mysql_perform_query (conn, "select album from Artists where artist = '"+m_search_edit+" ' ");
causes this error:
error C2664: 'mysql_perform_query' : cannot convert parameter 2 from 'class CString' to 'char *'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called"
And when I convert m_search_edit to a char* it gives me a " Cannot add 2 pointers" error.
Is there any way around this?

The problem here is that you are probably building for Unicode, which means that CString consists of wide characters. You can't directly concatenate an ASCII string with a wide character string (and you can't concatenate string literals with the + operator either).
I think the clearest way to build the query string here is by using the CT2CA macro to convert the contents of the edit control from Unicode to ASCII and CStringA::Format to insert them in the string
CStringA query;
query.Format("select album from Artists where artist = '%s'", CT2CA(m_search_edit));
res = mysql_perform_query(conn, query);
And as Thomas pointed out, you should be aware that this leaves the door open for SQL injection...
EDIT: I'm not sure where this mysql_perform_query API comes from, but from the error message you posted it looks like it also requires a writable buffer (char * instead of const char *). Since I can't find documentation for it, I don't know how big it expects that buffer to be, but to get a modifiable buffer out of a CString, look into the GetBuffer() and ReleaseBuffer() methods:
CStringA query;
query.Format(...); // Replace ... with parameters from above
char * buffer = query.GetBuffer(MAX_STRING_LENGTH); // make length big enough for mysql
res = mysql_perform_query(conn, buffer)
query.ReleaseBuffer();
EDIT2 (in response to latest comment):
Thank you for providing the definition of your mysql_perform_query function. When asking questions in the future, keep in mind it's helpful to know when you've created helper functions like this one.
In this case, your mysql_perform_query function never modifies the query string -- the only thing it does is pass it to mysql_query, which takes a const char *, so there's no reason you shouldn't declare its parameter const too. Once you do that, you'll find my first answer works (no need for GetBuffer/ReleaseBuffer):
MYSQL_RES *mysql_perform_query(MYSQL *conn, const char * query)
{
// Body as written in comment.
}

Related

Converting v8 args to std::string

My goal is to run a function in Node.js and provide a string as parameter/argument:
const myAddon = require('path'); myAddon.myFunc(otherData, "Hello World");
What I've tried, according to a Stack Overflow answer, was the following:
v8::String::Utf8Value STR_ARG(args[1]->ToString());
std::string USER_MESSAGE = std::string(*STR_ARG);
This didn't work and I got this error Message:
ToString Function doesn't accept 0 Arguments.
Am I supposed to give the function any input and if so, what?
The Solution I tried to approach in my Question didnt work properly. If it doesnt work for you either, here is the Code that Worked for me.
v8::Local<v8::String> argsINPUT;
argsINPUT = args[0].As<v8::String>();
//Having a Second Argument to determine the Buffer Size is Optional but Optimal
//new char[insert any int] is also okay, but it should be large enough to hold the Data
char* args_buffer = new char[args[1].As<Number>()->Value()];
//If the Next Line thows an Error try out '(argsINPUT*)' instead of 'argsINPUT'
argsINPUT->WriteUtf8(isolate, args_buffer);
static std::string finalString;
finalString.assign(args_buffer);
delete args_buffer;
args.GetReturnValue().Set(String::NewFromUtf8(
isolate, finalString.c_str()).ToLocalChecked());
Credits to Cybafelo:
Convert std::string to v8::string and viceversa?
And Botje for helping me out with my Original Approach
Edit: Reason why args[1].As<Number>()->Value() might be optimal as Buffer Size:
js code example:
const myAddon = require('path');
const myString = "Hello World";
myAddon.myFunc(myString, myString.length + 1);
As you can see and probably know, Js provides us with properties and functions, one of them is the length Property, so we can just Directly create a perfectly size Buffer. The +1 is at the end because Im not sure if we need also space for "\0"

C++ SNAP Library convert std::string to TStr

In the SNAP Library there's a method that allows me to save a file in my pc here it is:
TSnap::SaveEdgeList(G, q, "Edge list format");`
in this function the 2nd argument its type is TStr which represents string types in SNAP library
I have a string variable that contains a full directory of where I want to put my file like this:
string filedir = openFileDialog1->FileName;
What I want to do is to give the content of a string variable to a TStr variable like this:
TStr q = filedir;
But unfortunately it gives an error.
So i was wondering if anyone has an alternative solution or something Thank you
Quick googling revealed that TStr can be constructed from a C-string via TStr(const char* CStr) constructor.
So, following will work:
TStr q = filedir.c_str();
Alternatively, you can pass filedir.c_str() directly as an argument.

Getting the address of a pointer and convert it in a wxString

I'm trying to convert the address of a pointer to a wxString of the wxWidgets library.
I have this book that presents a console based example to explain the input/output stream system in C++. Here we can print the address of some pointers without much complications using
const char *const variable = "again";
cout << static_cast<void*>(variable);
So far I can understand the example but (Now the complication)I want to make some GUI off the examples to train myself and explore the wxWidgets classes along with the book. I've successfully made some conversions with the As() method of the wxAny class and even compiled it without warnings or errors. But in execution time I get an "Assert failure" when trying to convert the types.
If I let the program continue it prints in my wxTextCtrl things like:
ﻌњ̎X(
Any ideas??
(btw I use CodeBlocks with Mingw32 and wxWidgets 3.0 in a windows 7 system)
this is the code that gives me the assert failure:
void ConsoleFrame::OnbtnFrase2Click(wxCommandEvent& event)
{
string chaine2("Value of the pointer: ");
void* puntero = &chaine2;
wxAny anyThing= puntero;
consoleText->AppendText(anyThing.As<wxString>());
}
This is the method that gives me the assert failure error.
Thanks to #Grady for correcting the code before.
Seems that I cannot convert a void* to a wxString. I have a gist of what may the problem be but, I cannot find a solution to the original problem of printing the address of a pointer in a text control (NOT the console screen)
A common way to do what you want in C++ is using std::stringstream (you need to #include <sstream>). The body of your function would then look like this:
string chaine2("Value of the pointer: ");
void* puntero = &chaine2;
stringstream tmpss;
tmpss << chaine2 << puntero;
consoleText->AppendText(tmpss.str());
If you just want to get a wxString containing everything that was output to that stream, you just do something like:
wxString mystr = tmpss.str();
I don't know what your question has to do with wxWidgets, but this works for me:
const char * dog = "dog";
std::cout << &dog;
I am no C++ expert.. but to me that looks like "output address of variable dog"
and if you want that as a string you could use a C++ string stream or just happy old C sprintf
char * addrString = (char *)malloc(sizeof(void *) * 2 + 3); // *2 bytes for hex rep, +3 for "0x" and null
sprintf(addrString, "%p",dog);
There is a difference between the address of a pointer and the contents of the pointer, especially with C-style (nul terminated sequence of characters).
For example:
const char * const text = "Some Text\n";
The variable text is a pointer to a string literal. The contents of the pointer is the location where the string literal resides; often called an address.
The expression, &text, represents the location or the address of the pointer. So if the pointer is residing at address 0x4000, the expression &text would return 0x4000; not the content of the pointer.
There are examples on StackOverflow for printing the address of a variable and the contents or the C-Style string.
So, do you want a wxString containing the address of a pointer or the string literal that the pointer points to?
At last!!
The answer to my question was here:
http://docs.wxwidgets.org/trunk/classwx_text_ctrl.html
This is the documentation of the text control. I just had to REDIRECT the output stream to the text control with:
wxStreamToTextRedirector redirect(myTextControl);
And now I use the cout object normally,
cout<<puntero;
and the output will be presented in the text control instead of a console screen. I could not create the wxString containing the address but so far this can at least show it. I know that from here on I can create a string from the contents of the text control and the member functions of it. If any of you guys have a better answer, I will gladly accep it. It is funny how the chapter of the book where I am is in/out streams and the solution to my problem is not presented in the book.

How to concatenate string in ROOT,c++?

I want to concatenate two string and I did in my program like String Filename = name+ "" + extension where extension is an integer value that I read just above this line and name is the path that is already defined.
But in ROOT I am getting error like Error: + illegal operator for pointer 1
What went wrong here? Is there any other method?
If extension is an integer, then convert it to a string first.
std::string Filename = name+ "" + std::to_string(extension);
+""+ does nothing, btw
The TString class in ROOT has a function called "Format" which you can use to concatenate strings the same way you format a print statement. Here is the documentation for the Format method: https://root.cern.ch/root/html/TString.html#TString:Format
and here is the documentation for how the formatting works http://www.cplusplus.com/reference/cstdio/printf/
I'm going to go ahead and assume the 'name' is a char*.
Char const* name = "john";
Char const* space = " ";
Here name and space are 2 pointers to character arrays.
When you add try to add these 2 together, the compiler tries to add the value of the 2 pointer together. This makes no sense to the compiler. You can obviously only add an offset to a pointer.
The solution to this is to make sure that one of the 2 things you are adding is a std::string and not 'c string'.

Select statement and implicit conversion only gives me the first character of a string

I'm using OLEDB to connect to my local Oracle 11gR2 database in VC++. I'm using CCommand::Open to Select rows from my database, which should contain strings.
When I'm using GetValue to get my data though, I only get the first character.
Here are my attempts at getting that data. Note that the same behavior happens in "GetValue" and in "GetColumnName".
char* test = (CHAR*)cmd.GetColumnName(2);
cout << (CHAR*)cmd.GetColumnName(2) << endl;
printf_s( "%s", (CHAR*)cmd.GetColumnName(2));
printf_s( "%S", (CHAR*)cmd.GetColumnName(2)); //This one works,
//but I really need to store my data, not just print it.
I'm thinking this is a conversion problem from SQL to C++ data types, but I can't put my finger on it. Help?
LPOLESTR is a wchar_t* string (thanks LRiO for confirming that) which is basically unsigned short*. The reason you are getting just the first character is because each character takes up two bytes, and english letters happen to be a NULL byte followed by the ASCII code for that letter, which, when stored in a little-endian format, makes it a C-string with one character (because the bytes are stored backwards).
You need to use wcout to print it:
wcout << cmd.GetColumnName(2);
You can store it like this (along with its length via wcslen):
LPOLESTR ostr = cmd.GetColumnName(2);
size_t ostrlen = wcslen(ostr);