I'm having some difficulties with the PathCombine function. It does not seem to work correctly in conjunction with SHFileOperation(). My code is as follows:
//beginning of method
TCHAR* root = new TCHAR[MAX_PATH];
root = L"C:\\Users\\jhow\\Desktop\\\0";
//later on in the method
TCHAR* t1Dir = new TCHAR[MAX_PATH]; //root
TCHAR* t2Dir = new TCHAR[MAX_PATH]; //temp
PathCombine(t1Dir,root,L"Folder1\\%REPLACE_THIS%\\\0");
PathCombine(t2Dir,root,L"Folder1\\temp\0");
sf.pFrom = t1Dir;
//sf.pFrom = L"C:\\Users\\jhow\\Desktop\\Folder1\\%REPLACE_THIS%";
sf.pTo = temporaryDir;
//Copy files
int n = SHFileOperation(&sf);
When I have it like it is above, the method sees sf.pTo, but for some reason it does not see sf.pFrom (even after playing around with different combinations of the \ and \0 at the end of the path name). n becomes 2, which I think means file not found... But for example, when I comment out.
sf.pFrom = t1Dir;
and replace it with:
sf.pFrom = L"C:\\Users\\jhow\\Desktop\\Folder1\\%REPLACE_THIS%";
SHFileOperation() works... it returns zero and I can see that all the files are copied into the directory. I find this odd seeing as they appear to be the same exact string (even when I debug and hover over the variables)... Anyone happen to know why this is happening? Is there something wrong with my syntax or logic? Because I don't see it. I am using Visual Studio 2008. Thank you very much for your time.
You are allocating a buffer on the heap for your root variable, but then immediately pointing that variable to a read-only string literal instead, leaking the allocated buffer.
More importantly, you are not taking into account that SHFileOperation() operates on double-null-terminated strings, but PathCombine() returns a single-null-terminated string instead. You are trying to include an extra null in your input to PathCombine(), but that will not work since PathCombine() take single-null-terminated strings as input, so it will never see your extra nulls. You ned to allocate enough space in your output buffers to hold the extra null terminators, and then make sure they are set to zeros before passing those buffers to SHFileOperation().
Try this:
LPTSTR root = TEXT("C:\\Users\\jhow\\Desktop\\");
TCHAR t1Dir[MAX_PATH+2] = {0};
TCHAR t2Dir[MAX_PATH+2] = {0};
PathCombine(t1Dir, root, TEXT("Folder1\\%REPLACE_THIS%\\"));
PathCombine(t2Dir, root, TEXT("Folder1\\temp"));
sf.pFrom = t1Dir;
sf.pTo = t2Dir;
int n = SHFileOperation(&sf);
Related
I have a function to concatenate two LPCWSTRs together by converting them to wstrings, adding them, converting it back, and then returning that value (taken from: How to concatenate a LPCWSTR?)
LPCWSTR addLPCWSTRs(LPCWSTR lpcwstr1, LPCWSTR lpcwstr2) {
//Add the strings together
std::wstring wstringCombined = std::wstring(lpcwstr1) + std::wstring(lpcwstr2);
//Convert from wstring back to LPCWSTR
LPCWSTR lpcwstrCombined = wstringCombined.c_str();
return lpcwstrCombined;
}
LPCWSTR BaseURL = L"https://serpapi.com/search.json?tbm=isch?q=";
LPCWSTR imageQuery = L"baby+animals";
LPCWSTR URL = addLPCWSTRs(BaseURL, imageQuery);
Before the return statement, the lpcwstrCombined value is correct, when I break before the return statement the debugger shows the value also to be correct.
The correct value should be:
When I break on the ending curly brace, the value that lpcwstr turns into a bunch of squares before 1-5 random symbols from other languages, and it's always changing.
Examples:
And this is without changing any code, simply resetting the debugger and running again. I have done hours of research on this and so far haven't found anything. A somewhat similar issue with arrays said to use pointers instead of face values but that didn't make a difference. Why does the variable change value outside of the function as soon as it is returned??
Edit:
After reading the comments I changed it to:
std::wstring addLPCWSTRs(LPCWSTR lpcwstr1, LPCWSTR lpcwstr2) {
//Add the strings together
std::wstring wstringCombined = std::wstring(lpcwstr1) + std::wstring(lpcwstr2);
//Convert from wstring back to LPCWSTR
return wstringCombined;
}
LPCWSTR BaseURL = L"https://serpapi.com/search.json?tbm=isch?q=";
LPCWSTR imageQuery = L"baby+animals";
LPCWSTR URL = addLPCWSTRs(BaseURL, imageQuery).c_str();
And the same issue still happens!
The issue is a misunderstanding of the lifetime of your memory. In your first example you have a dangling pointer:
std::wstring combined = ...
// Here you create the string (importantly, its memory)
LPCWSTR lpcwstrCombined = wstringCombined.c_str();
// Make a pointer to the string
return lpcwstrCombined;
// return the pointer
} // end of function the string is destroyed, including it's memory being freed
In your second example you do the same thing, just in a different way:
LPCWSTR URL = addLPCWSTRs(BaseURL, imageQuery).c_str();
// ^ This is a temporary, at the end of this statement, it will be
// destroyed along with its memory.
You need to keep the wstring arround:
std::wstring string_storage = addLPCWSTRs(BaseURL, imageQuery);
LPCWSTR URL = string_storage.c_str();
You can then use the URL for the scope of the string.
That means don't do something like this:
LPCWSTR URL;
{
std::wstring string_storage = addLPCWSTRs(BaseURL, imageQuery);
URL = string_storage.c_str();
} // string is destoryed leaving a dangling pointer (just to get you a third
// time)
I receive file paths in the form of a CString. For Example: C:\Program Files\Program\Maps\World\North-America
I need to remove everything before Maps. I.e C:\Program Files\Program\ but this file path could be different.
I tried:
CString noPath = fullPath;
fullPath.Truncate(fullPath.ReverseFind('Maps'));
noPath.Replace(_T(fullPath),_T(""));
Which doesn't work consistently. It's cutting some file paths in the wrong place. The solution doesn't need to use Truncate/Replace but I'm not sure how else to do this
The CString I'm familiar with doesn't have a Truncate member and ReverseFind only works with single characters, not substrings; so fullPath's type is a mystery to me.
One thing I noticed: _T(fullPath) appears in your code, but the _T macro only works for literals (quoted strings or characters).
Anyway, here is a CString-only solution.
CString TruncatePath(CString path, CString subdir) {
CString sub = path;
const int index = sub.MakeReverse().Find(subdir.MakeReverse());
return index == -1 ? path : path.Right(index + subdir.GetLength());
}
...
CString path = _T("C:\\Program Files\\Program\\Maps\\World\\North-America");
CString sub_path = TruncatePath(path, _T("Maps\\"));
Gives you sub_path: Maps\World\North-America
You can use Delete function for this purpose.
for example:
CString path(_T("C:\\Program Files\\Program\\Maps\\World\\North-America"));
path.Delete(0, path.Find(_T("Maps"))); //pass first index and number of count to delete
Now variable path is having value Maps\\World\\North-America
I've just finished C++ The Complete Reference and I'm creating a few test classes to learn the language better. The first class I've made mimics the Java StringBuilder class and the method that returns the string is as follows:
char *copy = new char[index];
register int i;
for(i = 0; i <= index; i++) {
*(copy + i) = *(stringArray + i);
} //f
return copy;
stringArray is the array that holds the string that is being built, index represents the amount of characters that have been entered.
When the string returns there is some junk after it, such as if the string created is abcd the result is abcd with 10 random characters after it. Where is this junk coming from? If you need to see more of the code please ask.
You need to null terminate the string. That null character tells the computer when when string ends.
char * copy = new char[ length + 1];
for(int i = 0; i < length; ++i) copy[i] = stringArray[i];
copy[length] = 0; //null terminate it
Just a few things. Declare the int variable in the tighest scope possible for good practice. It is good practice so that unneeded scope wont' be populate, also easier on debugging and kepping track. And drop the 'register' keyword, let the compiler determine what needs to be optimized. Although the register keyword just hints, unless your code is really tight on performance, ignore stuff like that for now.
Does index contain the length of the string you're copying from including the terminating null character? If it doesn't then that's your problem right there.
If stringArrary isn't null-terminated - which can be fine under some circumstances - you need to ensure that you append the null terminator to the string you return, otherwise you don't have a valid C string and as you already noticed, you get a "bunch of junk characters" after it. That's actually a buffer overflow, so it's not quite as harmless as it seems.
You'll have to amend your code as follows:
char *copy = new char[index + 1];
And after the copy loop, you need to add the following line of code to add the null terminator:
copy[index] = '\0';
In general I would recommend to copy the string out of stringArray using strncpy() instead of hand rolling the loop - in most cases strncpy is optimized by the library vendor for maximum performance. You'll still have to ensure that the resulting string is null terminated, though.
I want to get int from cstring.
Here is Code.
CStringArray paramArray;
paramArray.Add((LPCSTR)"5");
paramArray.Add((LPCTSTR)"151");
pvarArguments = new CComVariant[2];
pvarArguments[0] = (LPCTSTR)paramArray[1];
CString str;
str = (CStringA)pvarArguments[0];
int nlen = _wtoi(str.GetBuffer());
When I run my program, I always get value 0, and I can't understand why it is.
Please help me.
From TFM (emphasis mine):
Each function returns the int value produced by interpreting the input
characters as a number. The return value is 0 for atoi and _wtoi, if
the input cannot be converted to a value of that type.
Print the string or examine it using a debugger. There may be invalid (including unprintable) characters in the string.
It's hard to tell even what you are trying to do. You do know that C++ arrays are 0-based, right? I ask because this line of code:
pvarArguments[0] = (LPCTSTR)paramArray[1];
is totally messed up. I don't understand why it's not throwing an exception when trying to index an element in a CStringArray that is equal to the count of elements. You can only index to count-1 ==>> which in this case is "0".
Your pvarArguments[0] will have junk in it--I have no idea why an exception wasn't thrown.
If you want to get a different type out of a variant, you can use VariantChangeType() and not mess with wcstoi or atoi. It will give an error code if it fails instead of just returning 0. If you are hell bent on using wcstoi or atoi on a CString, use _tstoi() which works whether you nave UNICODE defined or not.
CStringA implies ANSI string type which would require atoi not _wtoi.
I suggest:
CString str(pvarArguments[0]);
int nlen = atoi(str.GetString());
GetBuffer() is not ideal because you must remember to later ReleaseBuffer().
EDIT: In light of the new information, try this:
paramArray.Add(L"5");
paramArray.Add(L"151");
The L macro makes the string wchar_t aware. If L doesn't work try _T instead. And then use _wtoi or _tstoi.
CStringArray paramArray;
paramArray.Add(_T("5"));
paramArray.Add(_T("151"));
CComVariant *pvarArguments = new CComVariant[2];
pvarArguments[0] = (LPCTSTR)paramArray[1];
CString str;
str = pvarArguments[0].bstrVal;
int nlen = _ttoi(LPCTSTR(str));
per suggestion above, this compiles for me:
rs->GetFieldValueString(0).Left(1) == sBoroCode
&& (_ttoi(LPCTSTR(sLowHouseNo)) % 2) == (_ttoi(LPCTSTR(rs->GetFieldValueString(2))) % 2)
I have my socket comms pretty much working. The only thing that I'm not sure about is why I'm getting some garbage values at the end of my message. The first message I send contains some extra characters at the end, and every message after that is as expected...does anyone have any insight as to why this is happening?
Send:
CString string = "TEST STRING TO SEND";
char* szDest;
szDest = new char[string.GetLength()];
strcpy(szDest,string);
m_pClientSocket->Send(szDest,strlen(pMsg));
Receive: (this is using Qt)
char* temp;
int size = tcpSocket->bytesAvailable();
temp = new char[size];
tcpSocket->read(temp,size);
You will be missing the \0 in your temp after read, since it's not really transmitted (and probably shouldn't be)
You likely need to change the receive a little bit:
temp = new char[size + 1];
int realSize = tcpSocket->read(temp, size);
temp[realSize] = 0;
Btw, you would be better off with QTcpSocket::readAll() in this little snipped.
I don't know this CString class, but I see two bugs here:
Does GetLength() include the terminating NUL? If not, your char buffer is one byte smaller than it needs to be, and the strcpy is clobbering memory after the end of the buffer.
strlen(pMsg) is the length of something other than szDest. This is probably the immediate cause of your problem.
The char buffer appears to be unnecessary: why don't you just do
CString string = "TEST STRING TO SEND";
m_pClientSocket->Send(string, string.GetLength());
?