How to concatenate an integer variable to a string literal - c++

I want to concatenate an int variable to a string literal.String literal is a path.
This is the code
bitmap.Save(L"D:\\screen.jpeg", &clsid);
In this code,i would like to add int variable after screen.I have tried this
bitmap.Save(L"D:\\screen"+k+L".jpeg", &clsid);// where k is the integer variable.
Unfortunately, it did not worked for me.The error was
"error C2110: '+' : cannot add two pointers"

If you're in C++11, use std::to_wstring.
bitmap.Save(L"D:\\screen" + std::to_wstring(k) + L".jpeg", &clsid);
If you're not in C++11 unfortunately, you can use std::wstringstream.
std::wstringstream strm;
strm << L"D:\\screen" << k << L".jpeg";
bitmap.Save(strm.str());

You can use a std::wstring, but you need to call .c_str() in order to use it with API that expect wchar_t *.
std::wstring filename = L"D:\\screen" + std::to_wstring(k) + L".jpeg";
bitmap.Save(filename.c_str(), &clsid);

The compiler complains, because L"D:\\screen.jpeg" is of type wchar[] and k is int (probably).
The simplest way would be to explicitely convert int to wstring (or string) using std::to_wstring (or std::to_string) method.
bitmap.Save((L"D:\\screen" + std::to_wstring(k) + L".jpeg").c_str(), &clsid);

Related

How to concatenate a variable between strings in an LPSTR?

I do have this function defined in windows playsoundapi.h.
PlaySound(L"D:\\resources\\English\\A.wav", NULL, SND_LOOP);
I want to concatenate a variable to replace "A.wav" in c++.
The variable is of type char*
Can anyone suggest a solution to this please? Much appreciated.
In C++17 or above use std::filesystem::path which is more handy for such scenario:
using std::filesystem::path;
path file = ...; // L"A.wav" // here can be wide characters things and regular character things - proper conversion is done implicitly
path base{L"D:\\resources\\English"};
PlaySound((base / file).c_str(), NULL, SND_LOOP);
Note that std::filesystem::path::c_str() returns const wchar_t* on Windows and const char * on other platforms.
Return value
The native string representation of the pathname, using native syntax, native character type, and native character encoding. This string is suitable for use with OS APIs.
Simple enough
std::wstring var = ...;
PlaySound((L"D:\\resources\\English\\" + var).c_str(), NULL, SND_LOOP);
But if your variable is something other than a std::wstring, then that is a different question. Please add more details if that is the case.
EDIT
It seems the variable is type char*. One possible solution is to make a std::wstring variable from the char* variable
char* var = ...;
std::wstring tmp(var, var + strlen(var));
PlaySound((L"D:\\resources\\English\\" + tmp).c_str(), NULL, SND_LOOP);
This does assume that there are no encoding issues in copying from char to wchar_t but again that's a detail not provided in the question.
Also you should consider why the variable is char* in the first place. You are working with an API that requires wide characters, so why not use wide characters in your code?
Assign your char* string to a std::string, which you can then concatenate with your base path, and then use the std::string::c_str() method to get a const char* pointer that you can pass to PlaySound(), eg:
std::string fileName = "A.wav";
PlaySoundA(("D:\\resources\\English\\" + fileName).c_str(), NULL, SND_LOOP);

strstr - string.h miscommunication error?

I am trying to compare the file name against a list of strings to see if they match up and if they do then return accordingly
I am using the following condition:
if (strstr(file, str) != NULL) {
return 1;
}
Though MSVC++2012 prompts me with the following error on strstr:
Error: no instance of overloaded function "strstr" matches the argument list
argument types are: (WCHAR [260], char *)
The question is: what is the meaning of the error above and how could it be fixed?
The problem you have got comes out from the fact that the strstr function expects to see two char pointers (char *) as its arguments, but it receives the WCHAR array instead as the first argument.
Unlike the usual 8-bit char, WCHAR represents a 16-bit Unicode character.
The one way to fix your error is to convert your Unicode file name to the char array as following:
char cfile[260];
char DefChar = ' ';
WideCharToMultiByte(CP_ACP, 0, file, -1, cfile, 260, &DefChar, NULL);
And then use cfile instead of file.
But this approach will only work with ASCII characters.
For that reason, you could consider using another string comparison method, suitable for the WCHAR strings (wstring).
The following code might help you with that second approach:
// Initialize the wstring for file
std::wstring wsfile (file);
// Initialize the string for str
std::string sstr(str);
// Initialize the wstring for str
std::wstring wstr(sstr.begin(), sstr.end());
// Try to find the wstr in the wsfile
int index = wsfile.find(wstr);
// Check if something was found
if(index != wstring::npos) {
return 1;
}
The good SO answer about usage of the find method in std::wsting: Find method in std::wstring.
More on converting string to wstring: Mijalko: Convert std::string to std::wstring.
Please leave some feedback in comments if it does not help.

Conversion of ATL CString to character array

I want to convert a CString into a char[]. Some body tell me how to do this?
My code is like this :
CString strCamIP1 = _T("");
char g_acCameraip[16][17];
strCamIP1 = theApp.GetProfileString(strSection, _T("IP1"), NULL);
g_acCameraip[0] = strCamIP1;
This seems to be along the right lines; http://msdn.microsoft.com/en-us/library/awkwbzyc.aspx
CString aCString = "A string";
char myString[256];
strcpy(myString, (LPCTSTR)aString);
which in your case would be along the lines of
strcpy(g_acCameraip[0], (LPCTSTR)strCamIP1);
From MSDN site:
// Convert to a char* string from CStringA string
// and display the result.
CStringA origa("Hello, World!");
const size_t newsizea = (origa.GetLength() + 1);
char *nstringa = new char[newsizea];
strcpy_s(nstringa, newsizea, origa);
cout << nstringa << " (char *)" << endl;
CString is based on TCHAR so if don't compile with _UNICODE it's CStringA or if you do compile with _UNICODE then it is CStringW.
In case of CStringW conversion looks little bit different (example also from MSDN):
// Convert to a char* string from a wide character
// CStringW string. To be safe, we allocate two bytes for each
// character in the original string, including the terminating
// null.
const size_t newsizew = (origw.GetLength() + 1)*2;
char *nstringw = new char[newsizew];
size_t convertedCharsw = 0;
wcstombs_s(&convertedCharsw, nstringw, newsizew, origw, _TRUNCATE );
cout << nstringw << " (char *)" << endl;
You could use wcstombs_s:
// Convert CString to Char By Quintin Immelman.
//
CString DummyString;
// Size Can be anything, just adjust the 100 to suit.
const size_t StringSize = 100;
// The number of characters in the string can be
// less than String Size. Null terminating character added at end.
size_t CharactersConverted = 0;
char DummyToChar[StringSize];
wcstombs_s(&CharactersConverted, DummyToChar,
DummyString.GetLength()+1, DummyString,
_TRUNCATE);
//Always Enter the length as 1 greater else
//the last character is Truncated
If you are using ATL you could use one of the conversion macros. CString stores data as tchar, so you would use CT2A() (C in macro name stands for const):
CString from("text");
char* pStr = CT2A((LPCTSTR)from);
Those macros are smart, if tchar represents ascii (no _UNICODE defined), they just pass the pointer over and do nothing.
More info below, under ATL String-Conversion Classes section:
http://www.369o.com/data/books/atl/index.html?page=0321159624%2Fch05.html
CStringA/W is cheaply and implicitly convertible to const char/wchar_t *. Whenever you need C-style string, just pass CString object itself (or the result of .GetString() which is the same). The pointer will stay valid as long as string object is alive and unmodified.
strcpy(g_acCameraip[0], strCamIP1);
// OR
strcpy(g_acCameraip[0], strCamIP1.GetString());
If you need writable (non-const) buffer, use .GetBuffer() with optional maximum length argument.
If you have CStringW but you need const char* and vice versa, you can use a temporary CStringA object:
strcpy(g_acCameraip[0], CStringA(strCamIP1).GetString());
But a much better way would be to have array of CStrings. You can use them whereever you need null-terminated string, but they will also manage string's memory for you.
std::vector<CString> g_acCameraip(16);
g_acCameraip[0] = theApp.GetProfileString(strSection, _T("IP1"), NULL);
Use memcpy .
char c [25];
Cstring cstr = "123";
memcpy(c,cstr,cstr.GetLength());
Do you really have to copy the CString objects into fixed char arrays?
enum { COUNT=16 };
CString Cameraip[COUNT];
Cameraip[0] = theApp.GetProfileString(strSection, _T("IP1"), NULL);
// add more entries...
...and then - later - when accessing the entries, for example like this
for (int i=0; i<COUNT; ++i) {
someOp(Cameraip[i]); // the someOp function takes const CString&
}
...you may convert them, if needed.
fopen is the function which needs char* param. so if you have CString as available string, you can just use bellow code.
be happy :)
Here, cFDlg.GetPathName().GetString(); basically returns CString in my code.
char*pp = (char*)cFDlg.GetPathName().GetString();
FILE *fp = ::fopen(pp,"w");
CString str;
//Do something
char* pGTA = (LPTSTR)(LPCTSTR)str;//Now the cast
Just (LPTSTR)(LPCTSTR). Hope this is what you need :)
char strPass[256];
strcpy_s( strPass, CStringA(strCommand).GetString() );
It's simple
ATL CStrings allow very simple usage without having to do a lot of conversions between types. You can most easily do:
CString cs = "Test";
const char* str = static_cast<LPCTSTR>(cs);
or in UNICODE environment:
CString cs = "Test";
const wchar_t* str = static_cast<LPCTSTR>(cs);
How it works
The static_cast (or alternatively C-Style cast) will trigger the CString::operator LPCTSTR, so you don't do any pointer reinterpretation yourself but rely on ATL code!
The documentation of this cast operator says:
This useful casting operator provides an efficient method to access the null-terminated C string contained in a CString object. No characters are copied; only a pointer is returned. Be careful with this operator. If you change a CString object after you have obtained the character pointer, you may cause a reallocation of memory that invalidates the pointer.
Modifiable Pointers
As mentioned in the above statement, the returned pointer by the cast operator is not meant to be modified. However, if you still need to use a modifiable pointer for some outdated C libraries, you can use a const_cast (if you are sure that function wont modify the pointer):
void Func(char* str) // or wchar_t* in Unicode environment
{
// your code here
}
// In your calling code:
CString cs = "Test";
Func(const_cast<LPTSTR>(static_cast<LPCTSTR>(test))); // Call your function with a modifiable pointer
If you wish to modify the pointer, you wont get around doing some kind of memory copying to modifiable memory, as mentioned by other answers.
There is a hardcoded method..
CString a = L"This is CString!";
char *dest = (char *)malloc(a.GetLength() + 1);
// +1 because of NULL char
dest[a.GetLength()] = 0; // setting null char
char *q = (char *)a.m_pszData;
//Here we cannot access the private member..
//The address of "m_pszData" private member is stored in first DWORD of &a...
//Therefore..
int address = *((int *)&a);
char *q = (char *)address;
// Now we can access the private data!, This is the real magic of C
// Size of CString's characters is 16bit...
// in cstring '1' will be stored as 0x31 0x00 (Hex)
// Here we just want even indexed chars..
for(int i = 0;i<(a.GetLength()*2);i += 2)
dest[i/2] = *(q+i);
// Now we can use it..
printf("%s", dest);

char array to LPCTSTR

May I know how I can perform the following conversion?
// el.strCap is char[50]
// InsertItem is expecting TCHAR pointer (LPCTSTR)
// How I can perform conversion?
// I do not have access in both "list" and "el" source code
// Hence, there is no way for me to modify their signature.
list.InsertItem(i, el.strCap);
And No. I do not want to use
WideCharToMultiByte
They are too cumbersome to be used.
If you're using ATL, then you can use the various macros and helper classes that it includes to do the conversion:
char *test = "Hello World";
CA2CT ct(test);
list.InsertItem(i, ct);
Though saying WideCharToMultiByte is too cumbersome is a bit disingenious, in my opinion. It's easy enough to wrap a call to WideCharToMultiByte and make it return an std::wstring or whatever you need. In fact, that's basically what CA2CT is doing under the covers...
If your character string is encoded as ISO-8859-1, it's easy to convert to UTF-16:
// Convert an ISO-8859-1 string to a UTF-16 string
wchar_t wstr[50];
for (int i = 0; i < 50; ++i)
{
wstr[i] = el.strCap[i];
if (!wstr[i])
break;
}
But if your data is anything other then ISO-8859-1 (or ASCII which is a subset), then you will need to handle a more complex conversion. Once you need to do that, you will find that MultiByteToWideChar is not that cumbersome in comparison.
You could also use CStringW i.e. list.InsertItem(i, CStringW("blah"));

I want to convert std::string into a const wchar_t *

Is there any method?
My computer is AMD64.
::std::string str;
BOOL loadU(const wchar_t* lpszPathName, int flag = 0);
When I used:
loadU(&str);
the VS2005 compiler says:
Error 7 error C2664:: cannot convert parameter 1 from 'std::string *__w64 ' to 'const wchar_t *'
How can I do it?
First convert it to std::wstring:
std::wstring widestr = std::wstring(str.begin(), str.end());
Then get the C string:
const wchar_t* widecstr = widestr.c_str();
This only works for ASCII strings, but it will not work if the underlying string is UTF-8 encoded. Using a conversion routine like MultiByteToWideChar() ensures that this scenario is handled properly.
If you have a std::wstring object, you can call c_str() on it to get a wchar_t*:
std::wstring name( L"Steve Nash" );
const wchar_t* szName = name.c_str();
Since you are operating on a narrow string, however, you would first need to widen it. There are various options here; one is to use Windows' built-in MultiByteToWideChar routine. That will give you an LPWSTR, which is equivalent to wchar_t*.
You can use the ATL text conversion macros to convert a narrow (char) string to a wide (wchar_t) one. For example, to convert a std::string:
#include <atlconv.h>
...
std::string str = "Hello, world!";
CA2W pszWide(str.c_str());
loadU(pszWide);
You can also specify a code page, so if your std::string contains UTF-8 chars you can use:
CA2W pszWide(str.c_str(), CP_UTF8);
Very useful but Windows only.
If you are on Linux/Unix have a look at mbstowcs() and wcstombs() defined in GNU C (from ISO C 90).
mbs stand for "Multi Bytes String" and is basically the usual zero terminated C string.
wcs stand for Wide Char String and is an array of wchar_t.
For more background details on wide chars have a look at glibc documentation here.
Need to pass a wchar_t string to a function and first be able to create the string from a literal string concantenated with an integer variable.
The original string looks like this, where 4 is the physical drive number, but I want that to be changeable to match whatever drive number I want to pass to the function
auto TargetDrive = L"\\\\.\\PhysicalDrive4";
The following works
int a = 4;
std::string stddrivestring = "\\\\.\\PhysicalDrive" + to_string(a);
std::wstring widedrivestring = std::wstring(stddrivestring.begin(), stddrivestring.end());
const wchar_t* TargetDrive = widedrivestring.c_str();