JavaEar 专注于收集分享传播有价值的技术资料

c++ convert from LPCTSTR to const char *

I have this problem in MSVC2008 MFC. I´m using unicode. I have a function prototype:

MyFunction(const char *)

and I'm calling it:

MyfunFunction(LPCTSTR wChar). 

error:Cannot Convert Parameter 1 From 'LPCTSTR' to 'const char *'

How to resolve it?

4个回答

    最佳答案
  1. Since you're using MFC, you can easily let CString do an automatic conversion from char to TCHAR:

    MyFunction(CString(wChar));
    

    This works whether your original string is char or wchar_t based.

    Edit: It seems my original answer was opposite of what you asked for. Easily fixed:

    MyFunction(CStringA(wChar));
    

    CStringA is a version of CString that specifically contains char characters, not TCHAR. There's also a CStringW which holds wchar_t.

  2. 参考答案2
  3. LPCTSTR is a pointer to const TCHAR and TCHAR is WCHAR and WCHAR is most probably wchar_t. Make your function take const wchar_t* if you can, or manually create a const char* buffer, copy the contents, and pass that.

  4. 参考答案3
  5. When UNICODE is defined for an MSVC project LPCTSTR is defined as const wchar_t *; simply changing the function signature will not work because whatever code within the function is using the input parameter expects a const char *.

    I'd suggest you leave the function signature alone; instead call a conversion function such as WideCharToMultiByte to convert the string before calling your function. If your function is called several times and it is too tedious to add the conversion before every call, create an overload MyFunction(const wchar_t *wChar). This one can then perform the conversion and call the original version with the result.

  6. 参考答案4
  7. This may not be totally on topic, but I wrote a couple of generic helper functions for my proposed wmain framework, so perhaps they're useful for someone.

    Make sure to call std::setlocale(LC_CTYPE, ""); in your main() before doing any stringy stuff!

    #include <string>
    #include <vector>
    #include <clocale>
    #include <cassert>
    
    std::string get_locale_string(const std::wstring & s)
    {
      const wchar_t * cs = s.c_str();
      const size_t wn = wcsrtombs(NULL, &cs, 0, NULL);
    
      if (wn == size_t(-1))
      {
        std::cout << "Error in wcsrtombs(): " << errno << std::endl;
        return "";
      }
    
      std::vector<char> buf(wn + 1);
      const size_t wn_again = wcsrtombs(&buf[0], &cs, wn + 1, NULL);
    
      if (wn_again == size_t(-1))
      {
        std::cout << "Error in wcsrtombs(): " << errno << std::endl;
        return "";
      }
    
      assert(cs == NULL); // successful conversion
    
      return std::string(&buf[0], wn);
    }
    
    std::wstring get_wstring(const std::string & s)
    {
      const char * cs = s.c_str();
      const size_t wn = mbsrtowcs(NULL, &cs, 0, NULL);
    
      if (wn == size_t(-1))
      {
        std::cout << "Error in mbsrtowcs(): " << errno << std::endl;
        return L"";
      }
    
      std::vector<wchar_t> buf(wn + 1);
      const size_t wn_again = mbsrtowcs(&buf[0], &cs, wn + 1, NULL);
    
      if (wn_again == size_t(-1))
      {
        std::cout << "Error in mbsrtowcs(): " << errno << std::endl;
        return L"";
      }
    
      assert(cs == NULL); // successful conversion
    
      return std::wstring(&buf[0], wn);
    }
    

    You could provide "dummy" overloads:

    inline std::string get_locale_string(const std::string & s) { return s; }
    inline std::wstring get_wstring(const std::wstring & s) { return s; }
    

    Now, if you have an LPCTSTR x, you can always call get_locale_string(x).c_str() to get a char-string.


    If you're curious, here's the rest of the framework:

    #include <vector>
    
    std::vector<std::wstring> parse_args_from_char_to_wchar(int argc, char const * const argv[])
    {
      assert(argc > 0);
    
      std::vector<std::wstring> args;
      args.reserve(argc);
    
      for (int i = 0; i < argc; ++i)
      {
        const std::wstring arg = get_wstring(argv[i]);
        if (!arg.empty()) args.push_back(std::move(arg));
      }
    
      return args;
    }
    

    Now the main() -- your new entry point is always int wmain(const std::vector<std::wstring> args):

    #ifdef WIN32
    
    #include <windows.h>
    
    extern "C" int main()
    {
      std::setlocale(LC_CTYPE, "");
    
      int argc;
      wchar_t * const * const argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
    
      return wmain(std::vector<std::wstring>(argv, argv + argc));
    }
    
    #else // WIN32
    
    extern "C" int main(int argc, char *argv[])
    {
      LOCALE = std::setlocale(LC_CTYPE, "");
    
      if (LOCALE == NULL)
      {
        LOCALE = std::setlocale(LC_CTYPE, "en_US.utf8");
      }
    
      if (LOCALE == NULL)
      {
        std::cout << "Failed to set any reasonable locale; not parsing command line arguments." << std::endl;
        return wmain(std::vector<std::wstring>());
      }
    
      std::cout << "Locale set to " << LOCALE << ". Your character type has "
                << 8 * sizeof(std::wstring::value_type) << " bits." << std::endl;
    
      return wmain(parse_args_from_char_to_wchar(argc, argv));
    }
    
    #endif