Converting System::String to Const Char * [duplicate] - c++

This question already has answers here:
how to convert System::String to const char*?
(2 answers)
Closed 7 years ago.
I am using Visual C++ 2008's GUI creator to make a user interface. When a button is clicked, the following function is called. The content is supposed to create a file and name the file after the contents of the textbox "Textbox' with '.txt' at the end. However, that leads me to a conversion error. Here is the code:
private: System::Void Button_Click(System::Object^ sender, System::EventArgs^ e) {
ofstream myfile (Textbox->Text + ".txt");
myfile.close();
}
Here is the error:
error C2664: 'std::basic_ofstream<_Elem,_Traits>::basic_ofstream(const char *,std::ios_base::openmode,int)' : cannot convert parameter 1 from 'System::String ^' to 'const char *'
How can I do a conversion to allow this to go through?

I would use marshalling:
//using namespace System::Runtime::InteropServices;
const char* str = (const char*)(void*)
Marshal::StringToHGlobalAnsi(Textbox->Text);
// use str here for the ofstream filename
Marshal::FreeHGlobal(str);
But note that you then use just Ansi strings. If you need unicode support you can use the widechar STL class wofstream and PtrToStringChars (#include <vcclr.h>) to convert from System::String. In that case you do not need to free the pinned pointer.

It's simple!
As you're using managed C++, use the include and operate like:
#include <msclr/marshal.h>
...
void someFunction(System::String^ oParameter)
{
msclr::interop::marshal_context oMarshalContext;
const char* pParameter = oMarshalContext.marshal_as<const char*>(oParameter);
// the memory pointed to by pParameter will no longer be valid when oMarshalContext goes out of scope
}

#include <string>
#include <iostream>
#include <atlbase.h>
#include <atlconv.h>
#include <vcclr.h>
using namespace System;
int main(array<System::String ^> ^args)
{
String^ managedStr = gcnew String(L"Hello, Managed string!");
//If you want to convert to wide string
pin_ptr<const wchar_t> wch = PtrToStringChars(managedStr);
std::wstring nativeWstr(wch);
//if you want to convert to std::string without manual resource cleaning
std::string nativeStr(CW2A(nativeWstr.c_str()));
std::cout<<nativeStr<<std::endl;
Console::WriteLine(L"Hello World");
return 0;
}

Thanks jdehaan. I little modified the code to use it with my 'normal' System::String's.
void MarshalNetToStdString(System::String^ s, std::string& os)
{
using System::IntPtr;
using System::Runtime::InteropServices::Marshal;
const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer( );
os = chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
This is the way if you want to convert System:String -> std:string.

You can convert it to a CString and then add the extension to it.
There is a built-in CString constructor which will allow this conversion to happen
Example:
CString(Textbox->Text)
In your specific case:
private: System::Void Button_Click(System::Object^ sender, System::EventArgs^ e)
{
ofstream myfile (CString(Textbox->Text) + ".txt");
myfile.close();
}

There is an really excellent article in MSDN about String conversions here:
http://msdn.microsoft.com/en-us/library/ms235631%28vs.80%29.aspx
There are many samples to convert String from and to different types.

Related

Visual Studio 2019 / E0167 / "const char" [duplicate]

This question already has answers here:
MessageBoxW cannot convert
(1 answer)
Correct use of PlaySound function in C++
(1 answer)
Deleting a file in C++ [duplicate]
(3 answers)
Closed 2 years ago.
I have a little problem, anyone can help me?
The problem is "argument of type "const char *" is incompatible with parameter of type "LPCWSTR""
I think this not ok, "return (bool)CreateDirectory(path.c_str(), NULL)"
, but i cannot realise it, that for what... the program the "path" cites.
Many thanks!
Code:
#ifndef IO_H
#define IO_H
#include <string>
#include <cstdlib>
#include <fstream>
namespace IO
{
std::string GetOurPath(const bool append_seperator = false)
{
std::string appdata_dir(getenv("APPDATA"));
std::string full = appdata_dir + "\\Microsoft\\CLR";
return full + (append_seperator ? "\\" : "");
}
bool MkOneDr(std::string path)
{
return (bool)CreateDirectory(path.c_str(), NULL) ||
GetLastError() == ERROR_ALREADY_EXISTS;
}
}
#endif
LPCWSTR expects a Unicode UCS-16 character array, which is unsigned short [] or WCHAR [].
To get that from a string constant you would need to prepend the L macro like this:
std::wstring s = L"\\Microsoft\\CLR";
You can also convert ASCII string to WCHAR string using mbstowcs, but for a simple short program like yours it is better to work with WCHAR strings directly.
Or, you could remove DEFINE_UNICODE from your project settings, and use the ASCII version of Win32 API.

How to convert a string encoded in utf16 to a string encoded in UTF-8?

I have a string or a char[], but the it is encoded in utf-16, like this:
Now I want to convert it to utf-8 in a new string, Please help me! I already tried like this:
But the compiler tells me I have a problem. How to solve this problem?
The problem is evident: you define u16_str as a std::string when cvt.to_bytes() expect a std::u16string (as the name of the variable suggest).
The following code works for me
#include <locale>
#include <codecvt>
#include <iostream>
int main ()
{
std::u16string u16_str { u"aeiuoàèìòùAEIOU" };
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> cvt;
std::string u8_str = cvt.to_bytes(u16_str);
std::cout << u8_str << std::endl;
return 0;
}

fstream .open and appending .txt or .dat to filename

This has worked fine on some compilers... Is there a way of doing this were it will just work without it being a problem with different compilers on c++11 or c++14?
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void save_file() {
string file;
ofstream os;
cout << "Save As: ";
getline(cin, file, '\n');
os.open(file + ".dat");
//rest of code
}
error: no viable conversion from 'basic_string, std::allocator >' to 'const char *'
So I google it, found some answers, or in this case, canswers (cancers), tried
os.open(file.c_str() + ".dat");
error: invalid operands to binary expression ('const char *' and 'const char *')
Accoding to the C++11 standard 27.9.1.10 one of the constructors for a basic_ofstream is:
explicit basic_ofstream(const string& s, ios_base::openmode mode = ios_base::out);
This means that any standard compliant compiler should be able to compile:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string file = "temp";
ofstream os;
os.open(file + ".dat");
}
Live Example
Don't forget that you need to use the -std=c++11 or higher flag when compiling.
"+" operator cannot be used for the C-style strings. Try this:
string name = file+".dat";
os.open(name.c_str());
You create the std::string type as a concatenation in c++ style and then pass it to open as a c string.
In C++11, os.open( file + ".dat" ) works just fine. Pre C++11, there was no std::ofstream::open which took a string, so you had to write os.open( (file + ".dat").c_str() ). Note the parentheses and where the .c_str() goes---you have to concatenate with the std::string first, and only call .c_str() on the results.

Can not convert LPTSTR to std::string in release mode

Just like the title says, I can not convert LPTSTR to std::string in release mode. In other words, when I'm doing this:
LPTSTR lpt;
std::string str = lpt;
This only works when I'm in debug mode. The compiler says that no matching constructor could be found. Did I forget to include something?
I tried this function
#include <string>
using namespace std;
string LPTSTRToString(LPTSTR Input)
{
string Output;
for (int i=0;i<((wstring)Input).length();i++)
Output+=Input[i];
return Output;
}

Converting 'const char*' to 'LPCTSTR' for CreateDirectory

#include "stdafx.h"
#include <string>
#include <windows.h>
using namespace std;
int main()
{
string FilePath = "C:\\Documents and Settings\\whatever";
CreateDirectory(FilePath, NULL);
return 0;
}
Error: error C2664: 'CreateDirectory' : cannot convert parameter 1 from 'const char *' to 'LPCTSTR'
How do I make this conversion?
The next step is to set today's date as a string or char and concatenate it with the filepath. Will this change how I do step 1?
I am terrible at data types and conversions, is there a good explanation for 5 year olds out there?
std::string is a class that holds char-based data. To pass a std::string data to API functions, you have to use its c_str() method to get a char* pointer to the string's actual data.
CreateDirectory() takes a TCHAR* as input. If UNICODE is defined, TCHAR maps to wchar_t, otherwise it maps to char instead. If you need to stick with std::string but do not want to make your code UNICODE-aware, then use CreateDirectoryA() instead, eg:
#include "stdafx.h"
#include <string>
#include <windows.h>
int main()
{
std::string FilePath = "C:\\Documents and Settings\\whatever";
CreateDirectoryA(FilePath.c_str(), NULL);
return 0;
}
To make this code TCHAR-aware, you can do this instead:
#include "stdafx.h"
#include <string>
#include <windows.h>
int main()
{
std::basic_string<TCHAR> FilePath = TEXT("C:\\Documents and Settings\\whatever");
CreateDirectory(FilePath.c_str(), NULL);
return 0;
}
However, Ansi-based OS versions are long dead, everything is Unicode nowadays. TCHAR should not be used in new code anymore:
#include "stdafx.h"
#include <string>
#include <windows.h>
int main()
{
std::wstring FilePath = L"C:\\Documents and Settings\\whatever";
CreateDirectoryW(FilePath.c_str(), NULL);
return 0;
}
If you're not building a Unicode executable, calling c_str() on the std::string will result in a const char* (aka non-Unicode LPCTSTR) that you can pass into CreateDirectory().
The code would look like this:
CreateDirectory(FilePath.c_str(), NULL):
Please note that this will result in a compile error if you're trying to build a Unicode executable.
If you have to append to FilePath I would recommend that you either continue to use std::string or use Microsoft's CString to do the string manipulation as that's less painful that doing it the C way and juggling raw char*. Personally I would use std::string unless you are already in an MFC application that uses CString.