How to prevent C6284 when using CString::Format? - visual-c++

The following code is generating warning C6284 when compiled with /analyze on MSVC 2008 : object passed as parameter '%s' when string is required in call to function.
CString strTmp, str;
str = L"aaa.txt"
strTmp.Format (L"File: %s", str);
I'm looking for a nice solution for this that would not require static_cast

Microsoft describes the usage of CString with variable argument functions here:
CString kindOfFruit = "bananas";
int howmany = 25;
printf_s( "You have %d %s\n", howmany, (LPCTSTR)kindOfFruit );
As an alternative you can also use the method PCXSTR CString::GetString() const; to try to fix the warning:
CString strTmp, str;
str = L"aaa.txt"
strTmp.Format (L"File: %s", str.GetString());

One of CString's design flaws, err, features is that it features an implicit conversion to LPCTSTR which makes the warning not that meaningful IMHO. But anyway, if you look at the Microsoft documentation, they actually use casts in their own example. I don't really see the need to avoid a static_cast here, in fact I would welcome it as it does make the implicit conversion more explicit and thus easier to spot.

Related

C++ override quotes

Ok, so I'm using C++ to make a library that'd help me to print lines into a console.
So, I want to override " "(quote operators) to create an std::string instead of the string literal, to make it easier for me to append other data types to that string I want to output.
I've seen this done before in the wxWidgets with their wxString, but I have no idea how I can do that myself.
Is that possible and how would I go about doing it?
I've already tried using this code, but with no luck:
class PString{
std::string operator""(const char* text, std::size_t len) {
return std::string(text, len);
}
};
I get this error:
error: expected suffix identifier
std::string operator""(const char* text, std::size_t len) {
^~
which, I'd assume, want me to add a suffix after the "", but I don't want that. I want to only use ""(quotes).
Thanks!
You can't use "" without defining a suffix. "" is a const char* by itself either with a prefix (like L"", u"", U"", u8"", R"()") or followed by suffixes like (""s, ""sv, ...) which can be overloaded.
The way that wxString works is set and implicit constructor wxString::wxString(const char*); so that when you pass "some string" into a function it is essentially the same as wxString("some string").
Overriding operator ""X yields string literals as the other answer.

VC++: how-to convert CString to TCHAR*

VC++: how-to convert CString value to TCHAR*.One method is GetBuffer(..) function. Is there any other way we can convert CString to TCHAR*.
CString::GetBuffer() doesn't make any conversion, it gives direct access to string.
To make a copy of CString:
TCHAR* buf = _tcsdup(str);
free(buf);
or
TCHAR* buf = new TCHAR[str.GetLength() + 1];
_tcscpy_s(buf, str.GetLength() + 1, str);
delete[]buf;
However the above code is usually not useful. You might want to modify it like so:
TCHAR buf[300];
_tcscpy_s(buf, TEXT("text"));
Usually you need to this to read data in to buffer, so you want to make the buffer size larger than the current size.
Or you can just use CString::GetBuffer(), again you might want to make the buffer size bigger.
GetWindowText(hwnd, str.GetBuffer(300), 300);
str.ReleaseBuffer(); //release immediately
TRACE(TEXT("%s\n"), str);
In other cases you need only const cast const TCHAR* cstr = str;
Lastly, TCHAR is not very useful. If your code is compatible with both ANSI and unicode then you might as well make it unicode only. But that's just a suggestion.
This depends on why you need a non-const TCHAR*. There are two main scenarios:
Manual update of the contents of a CString object:In that case you will have to call CSimpleStringT::GetBuffer (specifying the minimal length of the final string), update the contents, and call CSimpleStringT::ReleaseBuffer. Calling ReleaseBuffer is mandatory, as it updates internal state. Failure to call ReleaseBuffer can lead to the string exposing unexpected behavior.
Failure to expose const-correctness at an interface:If this is the case you can either update the interface to take a const TCHAR* instead of a TCHAR*, and invoke CSimpleStringT::operator PCXSTR by passing the CString object.If you cannot update the interface, you are best advised to make a copy into a TCHAR array and pass a pointer to this copy.If you can make sure that the implementation will not ever modify the contents referenced through the TCHAR* parameter, you could use a const_cast instead. This is not recommended, as it can introduce bugs in the future, by modifying unrelated code.

C++ Convert Sytem::String^ to LPCOLESTR

I write in mixed mode (C++/CLI) and I can not resolve this problem:
String ^progID = "Matrikon.OPC.Server";
CLSID clsid;
HRESULT result = CLSIDFromProgID(progID, &clsid);
error C2664: 'CLSIDFromProgID' : cannot convert parameter 1 from 'System::String ^' to 'LPCOLESTR'
How can I convert String^ to LPCOLESTR ?
Thanks!
I made another way:
// 1.
pin_ptr<const WCHAR> str = PtrToStringChars(progID);
LPCOLESTR coleString = (LPWSTR)str;
I have found that pin_ptr will be released if goes out of scope Define the Scope of Pinning Pointers and pin_ptr (C++/CLI)
This code works well for me:
// 2. this is the same like (1.)
String ^progID2 = "Matrikon.OPC.Simulation.1";// This is example of dynamic string
pin_ptr<const WCHAR> PINprogID2 = PtrToStringChars(progID2);
CLSID clsid2;
HRESULT result2 = CLSIDFromProgID(PINprogID2, &clsid2); //(LPCOLESTR, &CLSID)
Another example:
// 3.
pin_ptr<const WCHAR> sclsid3 = PtrToStringChars("{63D5F432-CFE4-11d1-B2C8-0060083BA1FB}");
CLSID clsid3;
CLSIDFromString((WCHAR*)sclsid3, &clsid3); //(LPOLESTR, &CLSID)
I am not much experienced and I am not sure if there are some lack of memory, but I think those codes are correct.
Avoid using the hammer for every nail. C++/CLI lets you just as easily use native types. So it is simply:
LPCOLESTR progid = L"Matrikon.OPC.Server";
// etc..
Non-zero odds (always say why) that you can simply use Type::GetTypeFromProgID().
First, lets convert System::String to char*
IntPtr p = Marshal::StringToHGlobalAnsi(progID);
char *pNewCharStr = static_cast<char*>(p.ToPointer());
second, casting char * to LPCOLESTR using ATL conversion macro:
LPCOLESTR converted_string = A2COLE(pNewCharStr);

Listing files in directory

I have created a windows form in c++ which, upon a button click, opens a dialog box for folder selection.
Now what I would like to do is get the list of files in that directory so that I can process them one by one.
I have googled it in many ways, and found many ways which include external libraries (such as boost and diren.h). I would not like to use external resources, but the ones at my disposal, the default ones.
I've read about FindFirstFile and FindNextFile, but couldnt get that combination to work.
Could you please assist?
Thanks a lot,
Idan.
Here is the updated code:
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
FolderBrowserDialog^ folderBrowserDialog1 = gcnew FolderBrowserDialog;
if (folderBrowserDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
String ^ selected = folderBrowserDialog1->SelectedPath;
selected += "\\*";
char* stringPointer = (char*) Marshal::StringToHGlobalAnsi(selected).ToPointer();
hFind = FindFirstFile((LPCWSTR)stringPointer, &FindFileData);
while(hFind != INVALID_HANDLE_VALUE)
{
printf("Found file: %s\r\n", FindFileData.cFileName);
if(FindNextFile(hFind, &FindFileData) == FALSE)
break;
}
}
You obviously compile for UNICODE (wide char) since you need to cast the newStr for the lpFileName parameter of FindFirstFile. But since you pass an ANSI string, you probable won't get a useful result. Youd didn't write, what you expect to find.
In the code beforer FindFirstFile you manually convert the SelectedPath value to ANSI char. That makes no sense, when you need a wide char string anyway. Get the LPCWSTR from the String selected with the StringToHGlobalUni method. This looks somehow like this (not tested):
LPCWSTR stringPointer = Marshal::StringToHGlobalAnsi(selected).ToPointer();
hFind = FindFirstFile(stringPointer, &FindFileData);
In general: Don't use casts except when you need to adapt a bad designed interface. Use it only when you know exactly what you are doing.
Further you don't check the hFind result of FindFirstFile. It will be INVALID_HANDLE_VALUE if you pass a pointer to the wrong string format.

Visual C++: displaying integer in a text Box

I want to write
int i=4;
textBox1->Text = i;
But it is giving compilation error for type mismatch. How to do box or typecast this?
Sorry for answering the quesition myself. But I just got it while searching.
There is a very easy method
int i=4;
textBox1->Text = Convert::ToString(i);
Instead you could use: textBox1->Text = i.ToString();.
There is a very easy method
int i=4;
textBox1->Text = ""+i;
You need conversion, not a cast. Use itoa() or itow() depending on whether you compile for Unicode.
if you are using CString you can use Format method, or use old c function itoa
example:
CString str;
str.Format("%d",i);
also do not forget to call UpdateData method to update the GUI controls
Convert integer to string and set as value for Text.
CString textVal;
textVal.Format(_T("%d"), i);
textBox1->Text = textVal;

Resources