I am working on an old app written in Visual C++ 6.0. I am trying to display an int variable in a MessageBox for debugging reasons. Here is my code, I thought this would be a simple process, but I am just learning C++. The two lines that are commented I have tried as well with similar errors. Below is the error I am getting.
int index1 = 1;
char test1 = index1;
// char var1[] = index1;
// char *varGo1 = index1;
MessageBox(NULL, test1, "testx", MB_OK);
error C2664: 'MessageBoxA' : cannot convert parameter 2 from 'char' to 'const char *'
Why bother with C-style strings if you tagged C++?
Although Mark Ransom provided MFC solution (which is perfectly valid), here is a Standard C++ one:
int index1 = 1;
std::string test1 = std::to_string(index1);
MessageBoxA(NULL, test1.c_str(), "testx", MB_OK);
References:
std::to_string();
Arrays are evil
Use boost::format for more sophisticated formatting.
int index1 = 1;
char buf[10];
itoa(index1,buf,10);
MessageBox(NULL,buf,"Caption",MB_OK);
Can try this
CString str1;
str1.Format(_T("%d"), index1);
MessageBox(NULL, str1, "testx", MB_OK);
CString's Format works just like printf to populate the string with the parameter list.
The second parameter of MessageBox needs to be a pointer to a string of chars, terminated with NULL. Passing a char will not work.
But, learning to use a debugger is an integral part to learning a language. Why not build a debug build and set a breakpoint on char test1 = index1; instead? You do that by pressing F9 when the cursor is on that line.
For what it's worth, I prefer to use a manipulator for this:
#include <sstream>
#include <iostream>
#include <windows.h>
using std::ostringstream;
using std::ostream;
ostream &msg_box(ostream &s) {
ostringstream &os = dynamic_cast<ostringstream &>(s);
MessageBox(NULL, os.str().c_str(), "testx", MB_OK);
return s;
}
int main() {
ostringstream msg;
msg << "The number is: " << 10 << msg_box;
return 0;
}
This maintains (mostly) the same interface nearly everybody's already accustomed to with iostreams, avoids the type-unsafe CString::Format, and avoids having several lines of distraction everywhere you're going to display a little information for debugging. The other obvious good point is that if you've overloaded operator<< for your own type, that overload will work with this as well.
Acording to your error, you should declare a const pointer on the second parameter.
Like this,
const char * test1= new char();
or use
std::string test1= "";
MessageBox(NULL, test1.c_str(), "testx", MB_OK);
Also using just "Text" will work.
Here is the pure C solution using sprintf method to store all input in buffer and passing that buffer to MessageBox.
#include <stdio.h>
#include <windows.h>
int main(void)
{
int intVal = 50;
float fltVal = 5.5;
char *str = "Test String";
char buf[1024] = {'\0'};//buffer to store formatted input.
//convert formatted input into buffer.
sprintf(buf,"Int value : %d\nFloat value : %f\nString : %s\n",intVal,fltVal,str);
//display whole buffer.
MessageBox(NULL,buf,"INFO",MB_ICONINFORMATION);
return 0;
}
Related
After getting a struct from C# to C++ using C++/CLI:
public value struct SampleObject
{
LPWSTR a;
};
I want to print its instance:
printf(sampleObject->a);
but I got this error:
Error 1 error C2664: 'printf' : cannot convert parameter 1 from
'LPWSTR' to 'const char *'
How can I convert from LPWSTR to char*?
Thanks in advance.
Use the wcstombs() function, which is located in <stdlib.h>. Here's how to use it:
LPWSTR wideStr = L"Some message";
char buffer[500];
// First arg is the pointer to destination char, second arg is
// the pointer to source wchar_t, last arg is the size of char buffer
wcstombs(buffer, wideStr, 500);
printf("%s", buffer);
Hope this helped someone! This function saved me from a lot of frustration.
Just use printf("%ls", sampleObject->a). The use of l in %ls means that you can pass a wchar_t[] such as L"Wide String".
(No, I don't know why the L and w prefixes are mixed all the time)
int length = WideCharToMultiByte(cp, 0, sampleObject->a, -1, 0, 0, NULL, NULL);
char* output = new char[length];
WideCharToMultiByte(cp, 0, sampleObject->a, -1, output , length, NULL, NULL);
printf(output);
delete[] output;
use WideCharToMultiByte() method to convert multi-byte character.
Here is example of converting from LPWSTR to char*
or wide character to character.
/*LPWSTR to char* example.c */
#include <stdio.h>
#include <windows.h>
void LPWSTR_2_CHAR(LPWSTR,LPSTR,size_t);
int main(void)
{
wchar_t w_char_str[] = {L"This is wide character string test!"};
size_t w_len = wcslen(w_char_str);
char char_str[w_len + 1];
memset(char_str,'\0',w_len * sizeof(char));
LPWSTR_2_CHAR(w_char_str,char_str,w_len);
puts(char_str);
return 0;
}
void LPWSTR_2_CHAR(LPWSTR in_char,LPSTR out_char,size_t str_len)
{
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,in_char,-1,out_char,str_len,NULL,NULL);
}
Here is a Simple Solution. Check wsprintf
LPWSTR wideStr = "some text";
char* resultStr = new char [wcslen(wideStr) + 1];
wsprintfA ( resultStr, "%S", wideStr);
The "%S" will implicitly convert UNICODE to ANSI.
Don't convert.
Use wprintf instead of printf:
wprintf
See the examples which explains how to use it.
Alternatively, you can use std::wcout as:
wchar_t *wstr1= L"string";
LPWSTR wstr2= L"string"; //same as above
std::wcout << wstr1 << L", " << wstr2;
Similarly, use functions which are designed for wide-char, and forget the idea of converting wchar_t to char, as it may loss data.
Have a look at the functions which deal with wide-char here:
Unicode in Visual C++
I want to replace a specific character wchar_t. as a result it return memory address. is there a way to return replaced wchar_t?
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <Psapi.h>
using namespace std;
int main()
{
wchar_t processPath[MAX_PATH];
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 3820);
GetProcessImageFileName(hProcess, processPath, MAX_PATH);
CloseHandle(hProcess);
wchar_t * pwc;
pwc = wcsstr(processPath, L"\\Device\\HardiskVolume1");
wcscpy_s(pwc, 100, L"C:", 100);
wcout << processPath;
return 0;
}
Thank you
I suggest that you use std::wstring, and then .replace, there isn't really a good 'replace' function when using c-strings:
LPCWSTR pwszReplace = L"string-of-interest";
std::size_t len = wcslen(pwszReplace);
std::wstring path(processPath),
std::size_t ndx = path.find(pwszReplace);
if(std::wstring::npos!=ndx)
{
path.replace(ndx, len, L"new-string");
}
std::wcout << L"path is now: " << path << std::endl;
Use GetModuleFileNameEx Windows XP and higher. Or QueryFullProcessImageName for Vista and higher.
Otherwise, you can't assume "\\Device\\HardiskVolume1" is always "C:"
See also this SO Q&A: Convert HarddiskVolume path to normal path
Start by changing "\Device" to "\\?":
`"\\Device\\HardiskVolume1\\path.exe"` //to
`"\\\\?\\HardiskVolume1\\path.exe"`
wchar_t buf[MAX_PATH];
wchar_t *ptr = wcsstr(processPath, L"\\Device");
if(ptr)
{
wcscpy_s(buf, L"\\\\?");
wcscat_s(buf, ptr + wcslen(L"\\Device"));
}
Now you can open buf in CreateFile, then use GetFinalPathNameByHandle to get
`"\\\\?\\C:\\path.exe"`
Note that wcsstr returns NULL if search string is not found. If search string was found and copy was successful, you end up overwriting processPath the way you have done that. Moreover, wcscpy_s is the secure version of wcscpy. If you don't want to use wcscpy_s correctly then just use wcscpy without using a random number like 100 as the argument.
This question already has answers here:
How do I properly compare strings in C?
(10 answers)
Closed 7 years ago.
I'm learning win32 programming with C/C++. In the process of learning, my teacher wanted I write a simple program that it can shows the name of the computer which It runs on it and Then, if the name of the target computer was "USER", shows a warning in the output console. I written the following code, but It doesn't work.
myFunction Code :
tchar * getComputerName() {
bufCharCount = INFO_BUFFER_SIZE;
if (!GetComputerName(infoBuf, &bufCharCount))
printError(TEXT("GetComputerName"));
return (TCHAR*)infoBuf;
}
calling code :
if (getComputerName() == (TCHAR*)"USER") {
printf("Target OS Detected \n");
}
how can i fix this issue?
There are several issues with the code as posted. The most blatant one is the use of TCHARs. TCHAR was invented, before Win9x had Unicode support, in an attempt to keep code source code compatible between Win9x and Windows NT (the latter uses Unicode with UTF-16LE throughout). Today, there is no reason to use TCHARs at all. Simply use wchar_t and the Windows API calls with a W suffix.
The C-style casts (e.g. return (TCHAR*)infoBuf) are another error waiting to happen. If the code doesn't compile without a cast in this case, this means, you are using incompatible types (char vs. wchar_t).
Plus, there's a logical error: When using C-style strings (represented through pointers to a sequence of zero-terminated characters), you cannot use operator== to compare the string contents. It will compare the pointers instead. The solution to this is to either invoke an explicit string comparison (strcmp), or use a C++ string instead. The latter overloads operator== to perform a case-sensitive string compare.
A fixed version might look like this:
#include <windows.h>
#include <string>
#include <iostream>
#include <stdexcept>
std::wstring getComputerName() {
wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0};
DWORD cchBufferSize = sizeof(buffer) / sizeof(buffer[0]);
if (!GetComputerNameW(buffer, &cchBufferSize))
throw std::runtime_error("GetComputerName() failed.");
return std::wstring(&buffer[0]);
}
int main() {
const std::wstring compName = getComputerName();
if ( compName == L"USER" ) {
std::wcout << L"Print your message" << std::endl;
}
}
The following code works for me:
#include <windows.h>
// ...
std::string get_computer_name()
{
const int buffer_size = MAX_COMPUTERNAME_LENGTH + 1;
char buffer[buffer_size];
DWORD lpnSize = buffer_size;
if (GetComputerNameA(buffer, &lpnSize) == FALSE)
throw std::runtime_error("Something went wrong.");
return std::string{ buffer };
}
You can't compare two string pointers to compare the string.
DWORD dw_computer_name = MAX_COMPUTERNAME_LENGTH;
TCHAR computer_name[MAX_COMPUTERNAME_LENGTH+1];
if ( 0 != GetComputerName( computer_name, &dw_computer_name ) )
{
printError( TEXT( "GetComputerName" ) );
if ( 0 == _tcscmp( computer_name, _T("HOST") )
{
printf( "Target OS Detected \n" );
}
}
I would like to convert a string variable to wstring due to some german characters that cause problem when doing a substr over the variable. The start position is falsified when any these special characters is present before it. (For instance: for "ä" size() returns 2 instead of 1)
I know that the following conversion works:
wstring ws = L"ä";
Since, I am trying to convert a variable, I would like to know if there is an alternative way for it such as
wstring wstr = L"%s"+str //this is syntaxically wrong, but wanted sth alike
Beside that, I have already tried the following example to convert string to wstring:
string foo("ä");
wstring_convert<codecvt_utf8<wchar_t>> converter;
wstring wfoo = converter.from_bytes(foo.data());
cout << foo.size() << endl;
cout << wfoo.size() << endl;
, but I get errors like
‘wstring_convert’ was not declared in this scope
I am using ubuntu 14.04 and my main.cpp is compiled with cmake. Thanks for your help!
The solution from "hahakubile" worked for me:
std::wstring s2ws(const std::string& s) {
std::string curLocale = setlocale(LC_ALL, "");
const char* _Source = s.c_str();
size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1;
wchar_t *_Dest = new wchar_t[_Dsize];
wmemset(_Dest, 0, _Dsize);
mbstowcs(_Dest,_Source,_Dsize);
std::wstring result = _Dest;
delete []_Dest;
setlocale(LC_ALL, curLocale.c_str());
return result;
}
But the return value is not 100% correct:
string s = "101446012MaßnStörfall PAt #Maßnahme Störfall 00810000100121000102000020100000000000000";
wstring ws2 = s2ws(s);
cout << ws2.size() << endl; // returns 110 which is correct
wcout << ws2.substr(29,40) << endl; // returns #Ma�nahme St�rfall with symbols
I am wondering why it replaced german characters with symbols.
Thanks again!
If you are using Windows/Visual Studio and need to convert a string to wstring you should use:
#include <AtlBase.h>
#include <atlconv.h>
...
string s = "some string";
CA2W ca2w(s.c_str());
wstring w = ca2w;
printf("%s = %ls", s.c_str(), w.c_str());
Same procedure for converting a wstring to string (sometimes you will need to specify a codepage):
#include <AtlBase.h>
#include <atlconv.h>
...
wstring w = L"some wstring";
CW2A cw2a(w.c_str());
string s = cw2a;
printf("%s = %ls", s.c_str(), w.c_str());
You could specify a codepage and even UTF8 (that's pretty nice when working with JNI/Java).
CA2W ca2w(str, CP_UTF8);
If you want to know more about codepages there is an interesting article on Joel on Software: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets.
These CA2W (Convert Ansi to Wide=unicode) macros are part of ATL and MFC String Conversion Macros, samples included.
Sometimes you will need to disable the security warning #4995', I don't know of other workaround (to me it happen when I compiled for WindowsXp in VS2012).
#pragma warning(push)
#pragma warning(disable: 4995)
#include <AtlBase.h>
#include <atlconv.h>
#pragma warning(pop)
Edit:
Well, according to this article the article by Joel appears to be: "while entertaining, it is pretty light on actual technical details". Article: What Every Programmer Absolutely, Positively Needs To Know About Encoding And Character Sets To Work With Text.
The main point is that
string foo("ä")
Is already an error. Start from here and read all answers. And beware, one is very wrong :)
I want to create folders in a directory by naming them in a sequence like myfolder1, myfolder2. i tried doing it with mkdir() function using a for loop but it doesn't take 'integer variables' and only takes 'const char values'. what to do now? is there any other function which do that or can mkdir() do that?
I'm not aware of any library calls that take an integer like you are asking. What you need to do is embed the number into the string before passing it to mkdir(). Since you tagged this question with 'c++' I've demonstrated a C++ oriented way of accomplishing this below.
#include <sstream> // for std::ostringstream
#include <string> // for std::string
const std::string baseFolderName = "myfolder";
for (int i = 1; i < 20; ++i)
{
std::ostringstream folderName;
folderName << baseFolderName << i;
mode_t mode = 0; //TBD: whatever is appropriate
mkdir(folderName.str().c_str(), mode);
}
If you really want this, you can use itoa(...)
Lets say
i = 20;
char buffer [33];
itoa (i,buffer,10); //10 means decimal
Now buffer = "20\0"
After this conversion you can add buffer to your default string.
So, all in all, you can use:
std::string str = "string";
char buffer[33] ;
itoa(20, buffer, 10);
str.append(buffer);
mkdir(str.c_str());