views:

998

answers:

4

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?

A: 

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(); 
}
Ruddy
Any clue why it's returning ''CString': identifier not found' when I have included string.h?
Reznor
CString is part of the MFC Libraries - is the project using MFC (i'm guessing its not)? (Project Properties/Configuration Properties/General/Use of MFC)
Ruddy
If I select 'Use MFC in a static library' then it returns: 'Command line error D8016 : '/MT' and '/clr:pure' command-line options are incompatible' Sorry, I'm somewhat of a beginner, and this is irritating me.
Reznor
Yea that Gem, in order to use MFC you'll have to change the /CLR setting and remove pure (Project Properties/Configuration Properties/General/Common Language Runtime Support) - this was not a problem in my case, if it is for your project you will not be able to MFC (as far as i know) - there is probably a similar wrapper somewhere that could be used without MFC but i don't know of it yet (rather than handling the marshaling directly as supplied by jdehaan - or you can write your own i guess).
Ruddy
This page http://msdn.microsoft.com/en-us/library/1b4az623.aspx may be of use - its converting from CLR String^ to STL string, which won't require any MFC and it encapsulates the conversion and memory handling.
Ruddy
+2  A: 

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.

jdehaan
Cool, that was the code I wrote! +1
leppie
+1 Exactly what I writing, except I prefer static_cast<const char*>(Marshal::StringToHGlobalAnsi(Textbox->Text).ToPointer())
James Hopkin
Good point James, better using C++ casts like you suggest!
jdehaan
A: 

@Rudy, if that constructor return a char* type, then CString(Textbox->Text) + ".txt" will throw a compilation error no operator+ defined for char* types.

erick2red
a constructor doesn't have a return type. The code as shown will compile and execute correctly in all my usage.
Ruddy
A: 
#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;
}
Sergey Teplyakov