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

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.

Related

getenv in C++ returns wrong values

I would like to write my program in 2 different paths. So, I proceeded like that :
std::string path1 = strcat(std::getenv("APPDATA"),"\\myprog.exe") ;
std::string path2 = strcat(std::getenv("APPDATA"),"\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\myprog.exe") ;
When I print, I get :
C:\Users\thispc\AppData\Roaming\myprog.exe
C:\Users\thispc\AppData\Roaming\myprog.exe\Microsoft\Windows\Start Menu\Programs\Startup\myprog.exe
instead of :
C:\Users\thispc\AppData\Roaming\myprog.exe
C:\Users\thispc\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\myprog.exe
Solution by Dietmar Kühl :
std::string path1 = std::getenv("APPDATA") + std::string("\\myprog.exe");
Explanation by Oliver Charlesworth :
strcat() changes the 1st variable
What is happening here is that std::getenv("APPDATA") gives you a pointer to a already written string somewhere in memory, that means the pointer returned by this function will always be the same.
Thus when you do strcat(std::getenv("APPDATA"),"\\myprog.exe") you basically concatenate that stored string in memory with "\\myprog.exe". So when you make a second call of std::getenv("APPDATA") you will get the concatenated string.
To solve this problem you should copy the string at std::getenv("APPDATA")

How can I assign boost::filesystem::directory_entry::path() value to a string?

I'm trying to write an algorithm that iterates recursively through a directory and compares each folder, sub-folder and file name to a user-defined regex object.
I've found this piece of code for the iteration part:
path p(FilePath);
for (directory_entry& x : recursive_directory_iterator(p))
std::cout << x.path() << '\n';
Where Filepath is the directory path defined by the user at runtime.
It works great to print out paths on the console, but I can't figure out a way to use path() to do what I want, which would be to assign its value to a string and then compare that string to my regex object.
I've been looking at other member function in boost::filesystem::directory_entry but I'm not really having any luck so far.
Could anyone point me in the right direction?
Thanks.
EDIT:
I'm dumb.
It works great to print out paths on the console, but I can't figure
out a way to use path() to do what I want, which would be to assign
its value to a string and then compare that string to my regex object.
boost::path has got a string member that either performs a conversion to a string type, or returns a const reference to the underlying storage mechanism (typically std::string) (see boost path documentation). Therefore, just call:
x.path().string()
Also, you might want to add some braces behind your for loop:
path p(FilePath);
std::string temppath;
for (directory_entry& x : recursive_directory_iterator(p))
{
temppath = x.path().string();
std::cout << temppath << std::endl;
}
The way you structured the code, std::cout would not be called as part of the loop, but only after the loop completed in its entirety... classic bug!!!

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'.

How to append to a string without changing original value when passing as a parameter?

I am making a PONG clone in C++/SDL, and I have all of my images in the directory in which the program starts. I am successfully able to find that path using GetCurrentDirectory() and open the file using strcat() to append the actual image and it will load fine, but this will change the original value, which makes it useless when I try to load the next image. How would I pass the path without changing the original value, or another way to work around this problem.
My current code:
TCHAR openingdirectorytemp [MAX_PATH];
bgtexturesurf = SDL_LoadBMP(strcat(openingdirectorytemp, "\\bg.bmp"));
Use actual C++ strings:
#include <string>
using std::string;
void child(const string str)
{
str += ".suffix"; // parameter str is a copy of argument
}
void parent()
{
string parents_string = "abc";
child(parents_string);
// parents_string is not modified
}
If you must work with TCHAR in the Windows API world, use std::basic_string<TCHAR>:
typedef std::basic_string<TCHAR> str_t; // now use str_t everywhere
and so the code becomes something like
void my_class::load_bg_bmp(const str_t &dir_path)
{
str_t file_path = dir_path + _T("\\bg.bmp")l
bgtexturesurf = SDL_LoadBMP(file_path.c_str()));
// ...
}
The TCHAR type allows for build times switching between narrow and wide characters. It is pointless to use TCHAR, but then use unwrapped narrow character string literals like "\\bg.tmp".
Also, note that strcat to an uninitialized array invokes undefined behavior. The first argument to strcat must be a string: a pointer to the first-element of a null terminated character array. An uninitialized array is not a string.
We can avoid such low-level nasties by using the C++ string class.
Although you can use C++ string as suggested by other answers, you can still keep your C approach.
What you need to do is just to create another string by copying the contents from the original, and use it for strcat:
TCHAR openingdirectorytemp [MAX_PATH];
TCHAR path [MAX_PATH];
strcpy(path, openingdirectorytemp);
bgtexturesurf = SDL_LoadBMP(strcat(path, "\\bg.bmp"));
By doing so, you create string path with a separate memory space, so strcat won't affect openingdirectorytemp
You need to make a copy of the string before concatenating if you are worried about things getting changed. In other words
string1 = "abc"
string2 = "def"
strcat(string1, string2);
Results in
string1 = "abcdef"
since that is what you asked the program to do. Instead, add
strcpy(string3, string1)
strcat(string3, string2);
Now you will have
string1 = "abc"
string3 = "abcdef"
Of course you need to make sure enough space is allocated, etc.
Once you are using c++, you can use string to compose your final pathname:
string pathname(path);
pathname += "\\bg.bmp";
bgtexturesurf = SDL_LoadBMP(pathname.c_str());

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

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