Cannot save filepath to database from c++ - c++

I am trying to save an image path to a mysql database from c++. The insertion takes place but the path is saved in this form:
C:Usersakrs.aDesktopatch_1images 01aa1363659036.jpg
rather than
C:\Users\akrs.a\Desktop\batch_1\images\001aa1363659036.jpg
so it is omitting '\','\b' and '\0'.
The code for the insertion in c++ is:
for (int i = 0 ; i < 2; i++)
{
std::string imgpath=dresses[i]->imgPath->data(); //gets the path
std::ostringstream querydb;
querydb<<"insert into base_table(imgPath,store,apparelType) values('"<< imgpath <<"','testdb','dress')";
mysql_query(connect,querydb.str().c_str());
}
mysql_close(connect);
I tried to print out the querydb too and the imagepath is sent correctly.How can I solve this problem?

try to replace all "\" with "\\" in "imgpath" variable.

Related

C++/MFC. Insert Image in CSV file Using MFC

Hello I'm studying MFC and I wanna know how to insert some images un csv file.
The file structure is as follows:The result folder contains 1.jpg, 2.jpg files.
In csv file, at the top "Index, Name, Age, Picture" must be included and "Index, Name, Age" are in the List Control.
I've finished entering the information in the csv file using the code below. However, I can't figure out how to insert the images in csv file.
`
CString _FilePath = theApp.m_ResultDir + _T("Result.csv"); //m_ResultDir : result folder Location
std::ofstream File(_FilePath,'w');
File << "Index, Name, Age, Picture\n";
CHeaderCtrl* pHeader = (CHeaderCtrl*)m_ListControl.GetHeaderCtrl();
int nRow = m_ListControl.GetItemCount();
int nCol = pHeader->GetItemCount();
CString text;
for (int i = 0; i < nRow; i++)
{
text = "";
for (int j = 0; j < nCol; j++)
{
text = text+ m_ListControl.GetItemText(i, j) + _T(", ");
}
File << text + "\n";
}
File.close();
`
It would be easy problem, but I'd appreciate it if you understand because it's my first time doing this.
This are what I tried.
First, I tried using TypeLib and select excel.exe and i contained some header files. However, I wanna make it csv file not xlsx file.
Second, using result folder location, I tried to add images. but failed.
`
CString image;
image.Format(theApp.m_ResultDir+_T("%d.jpg"), i+1);
text += image;
`
First argument to CString::Format is a format specification, followed by the arguments to be formatted. So something like that would work:
image.Format(_T("%s%d.jpg"), theApp.m_ResultDir, i+1);

Write vector values into multiple files at once in C++

I have the data in my vector. I am trying to write each vector value, say vector_name[0] into "examplezero.h" , vector_name[1] into "exampleone.h" and so on. The below code shows how I have created the files.
int co = 80;
string name ="example";
std::ofstream output_file[80];
for (int i = 0; i < co; i++)
{
output_file[i].open(name + std::to_string(i) + ".h");
output_file[i].close();
}
I am trying to iterate over my vector and trying to write to my files.
std::vector<string> rowname; //This has all the values
for (auto i = rowname.begin(); i != rowname.end(); ++i)
{
std::ostream_iterator<std::string> \
output_iterator(output_file[80], "\n");
std::copy(rowname.begin(), rowname.end(), output_iterator);
}
When I am trying to write to the files it is crashing. Can you let me know what's wrong? I know the basics of C++ and trying to learn the advanced concepts.
Thanks
Your program is likely crashing because you wrote this code:
std::ostream_iterator<std::string> \
output_iterator(output_file[80], "\n");
...and output_file[80] is one element past the end of the array. You declared it as:
std::ofstream output_file[80];
The first element of that array is output_file[0] and the last element of that array is output_file[79].
There are more things wrong
As #walnut pointed out, if your code is really as you posted it, then it appears to close each file immediately after opening it, without writing anything to the file.
for (int i = 0; i < co; i++)
{
output_file[i].open(name + std::to_string(i) + ".h");
output_file[i].close(); // Leaving so soon?
}
Writing to an ofstream that has been closed does not crash the program, but sets an error condition on the ofstream (badbit). So this will appear to be a silent failure to you.
To fix
To fix your problem you'll have to write to your file after you open it, but before you close it.
You'll also have to decide exactly which output_file you actually want to write to and provide the correct array index. It's not obviously clear from your sample code what your intent was. You'll have to decide which file(s) (of the 80 that you opened) you want to write each element of your rowname vector into.
The std::copy as you have written it will write all strings in the rowname vector to the same stream. If your intent was to write each element to its own file, then you'll have to set it up substantially differently.
Something more along the lines of:
#include <fstream>
#include <vector>
#include <string>
int main() {
std::vector<std::string> rowname = { "alpha", "bravo", "charlie" }; // example data
std::string name = "example"; // base filename
for (size_t i = 0; i < rowname.size(); ++i) {
std::ofstream output_file;
std::string filename = name + std::to_string(i) + ".h"; // e.g.: "example0.h"
output_file.open(filename);
output_file << rowname[i]; // write the string to the file
output_file.close(); // if you want
}
}
This writes the text alpha into example0.h, bravo into example1.h, and charlie into example2.h.

Adding to the name of a file

I'm working on an application that processes text files, and I want to create a new file with a similar name to that file, but slightly modified.
So for instance, I have a function that takes a string fileName as a parameter and creates a new file with the word "PROCESSED" added before ".txt."
so if fileName = "testFile.txt"
the new file should be named "testFilePROCESSED.txt"
string newFile = filename + "PROCESSED"; obviously doesn't work since the filename would be "testFile.txtPROCESSED" in this case.
You just need more practice with strings:
int ii = filename.rfind('.');
filename.insert(ii, "PROCESSED");
Let's keep it simple, I assume fileName is a string.
`#include <sstream>`
using namespace std;
stringstream ss;
fileName.erase(name.end()-4, name.end()); //Extension removal.
ss << name << "PROCESSED.txt";
string newFileName = ss.str();

How to separate a executing path to file path and parameter?

There are such lines as
C:\Program Files\Realtek\Audio\HDA\RAVCpl64.exe -s
in the registry key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Now I want to separate the absolute path and parameters from the line.
If the line is
C:\Space Dir\Dot.Dir\Sample Name.Dot.exe param path."C:\Space Dir\Dot.Dir\Sample Name.Dot.exe"
Which separator should I use to deal with this line? Is there any Windows API function to solve this problem?
The function you want is in the standard C library that you can use in Windows.
char theDrive[5],thePath[MAX_PATH],theFilename[MAX_PATH],theExtension[MAX_PATH];
_splitpath(theSCTDataFilename,theDrive,thePath,theFilename,theExtension);
You can also use a more general tokenizing function like this which takes any string, a char and a CStringArray..
void tokenizeString(CString theString, TCHAR theToken, CStringArray *theParameters)
{
CString temp = "";
int i = 0;
for(i = 0; i < theString.GetLength(); i++ )
{
if (theString.GetAt(i) != theToken)
{
temp += theString.GetAt(i);
}
else
{
theParameters->Add(temp);
temp = "";
}
if(i == theString.GetLength()-1)
theParameters->Add(temp);
}
}
CStringArray thePathParts;
tokenizeString("your\complex\path\of\strings\separated\by\slashes",'/',&thePathParts);
This will give you an array of CString (CStringArray object) that contains each section of the input string. You can use this function to parse the major chunks then the minor ones as long as you know the seperator charactor you want to split the string on.

Changing last 5 char of array

I have a program that encrypts files, but adds the extension ".safe" to the end. So the end result is something like "file.txt.safe"
When I go to decrypt the file, the user enters the file name again: "file.txt.safe" which is saved to a char. Now I want to remove ".safe" and rename the file to its original name.
I have tried the following, but nothing seems to happen and there are no errors.
Decrypt (myFile); //decrypts myFile
char * tmp = myFile;
char * newFile;
newFile = strstr (tmp,".safe"); //search tmp for ".safe"
strncpy (newFile,"",5); //replace .safe with ""
rename (myFile, newFile);
I'm sure I'm missing something obvious, but if this approach doesn't work, I'm looking for any simple method.
Edited to add:
(copied by moderator from poster's response to K-ballo)
Thanks everyone. I took the std::string approach and found this to work:
Decrypt(myFile);
string str = myFile;
size_t pos = str.find(".safe");
str.replace(pos,5,"");
rename(myFile, str.c_str());
For what you want to do, simply changing the strncpy line to this will work:
*newFile = '\0';
This would still have problems if the filename contains an early .safe (like in file.safest.txt.safe), or if it does not contain the substring .safe at all. You would be better of searching from the end of the array, and making sure you do find something.
This seems like a better approach (although in C++ it would be better to just go with std::string):
char* filename = ...;
size_t filename_length = strlen( filename );
int safe_ext_pos = filename_length - 5; // 5 == length of ".safe"
if( safe_ext_pos > 0 && strcmp( ".safe", filename + safe_ext_pos ) == 0 )
filename[ safe_ext_pos ] = '\0';
This is the std::string version of the code:
std::string filename = ...;
int safe_ext_pos = filename.length() - 5; // 5 == length of ".safe"
if( safe_ext_pos > 0 && filename.compare( safe_ext_pos, 5, ".safe" ) == 0 )
filename.erase( safe_ext_pos );
You should take care:
my.safe.file.txt.safe
Instead of just searching for '.safe' and removing it or truncating the filename at the first one, you should ensure that it's actually at the end of the string:
std::string myfile = ...
Decrypt(myFile);
const std::string extension_to_remove = ".safe";
if (decryption is successful &&
myfile.size() >= extension_to_remove.size() &&
myfile.substr(myfile.size()-5) == extension_to_remove)
{
std::string newFile = myfile.substr(0, myfile.size()-5);
rename(myFile, newFile);
}
Also a note on filename extensions. It's really a pretty awful practice for software to identify file types using a special format in the filename.* It's fine for humans to organize their files with special naming conventions, but software should by and large be oblivious to it, except perhaps to make it easy for humans to use the conventions they want.
So your code for decrypting a file shouldn't be doing this task. Instead your decryption code should take a file to decrypt and a file to contain the output. Then your code for computing the output filename from the encrypted file's name should exist somewhere else, such as in the user interface where the user tells you the output filename. Your code would remove '.safe' if it exists and supply the modified name as the default output filename, to be confirmed by the user.
void perform_decryption(std::string const &encrypted, std::string const &decrypted) {
Decrypt(encrypted);
if (decryption is successful && encrypted!=decrypted)
rename(encrypted, decrypted);
}
std::string default_decrypted_name(std::string const &filename) {
const std::string extension_to_remove = ".safe";
if (filename.size() >= extension_to_remove.size() &&
filename.substr(filename.size()-extension_to_remove.size()) == extension_to_remove)
{
return filename.substr(0, filename.size()-extension_to_remove.size());
}
return filename + ".decrypted";
}
* here are some reasons against filename extensions:
filename extensions are not unique, in some circumstances causing conflicts where a file's type cannot be positively identified. (the fact that they can't even perform their intended purpose really ought to be enough...)
It degrades the usability of the filename for organizing. When 'myfile.txt' is renamed to 'myfile.txt.old' it's no longer seen as a text file.
It's caused security issues because fake type metadata can be mistaken for real type metadata when the real type metadata is hidden.
and more...