std::string to LPCTSTR

22,964

Solution 1

Your problem here is the fact that LPCTSTR is resolved to wchar_t* or char* based on whether your build supports unicode (unicode flag set or not).

To explicitly call the char* version, call CreateDirectoryA().

Solution 2

Try to look at this page: What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc. If you are using MSVC, than you may have set Unicode for project and LPCSTR is "translated" to const wchar_t *, which is not compatible with const char *

By doing this: (LPCTSTR)path.c_str() you are taking two chars from original string and create from them one unicode wchar_t letter. Thats way you are getting "chinese" characters.

Solution 3

As this question pops up when you try to find "(std::) string to LPCTSTR"

Here's a way how to convert&pass std::string as LPCTSTR using wstring

string path_str = "Yay!"; //your string containing path
wstring path_wstr( path_str.begin(), path_str.end() );
//then this should work:
CreateDirectory(path_wstr.c_str(),NULL);

IMPORTANT Note by Adrian McCarthy:

This is fine if the source string is ASCII or if it's ANSI and the current code page is Windows-1252 (which is very similar to Latin-1). If the source is UTF-8 or another code page, then this just hides the problem.

Solution 4

You are compiling for Unicode which means that CreateDirectory is an alias for CreateDirectoryW, the wide character version. However, the text in your program is encoded using ANSI. This means that your program cannot handle internationalization properly.

The compiler is telling you that there is a mismatch between the text encoding that CreateDirectoryW expects, and the text encoding that you are supplying. It's true that you could call CreateDirectoryA to resolve that mis-match, but that is only going to perpetuate the root problem, the fact that you are using ANSI text in your program.

So, the best solution is to start encoding all your text as Unicode. Stop using string and start using wstring. Once you change path to wstring then

CreateDirectory(path.c_str(),NULL);

is correct.

Solution 5

Use CreateDirectoryA instead. CreateDirectory is a macro that expands to either CreateDirectoryA or CreateDirectoryW depending on the build configuration; They take respectively LPCSTR and LPCWSTR. If you know you have a LPCSTR (which is what c_str() gives you), use the first one.

Share:
22,964

Related videos on Youtube

Ander Biguri
Author by

Ander Biguri

Research Associate on Tomographic reconstruction with Machine Learning at University of Cambridge. Mostly have done a lot of X-ray tomography (Check out TIGRE toolbox, created in collaboration with CERN!) a fair amount of Positron Emission Tomography, and a little bit of Electrical Impedance Tomography. "Matlab can even make your dinner, if you know how to use it" (OK, starting to think that python can too, but MATLAB is still quite good) My email/facebook/linkedin are not the correct places to contact me about anything related to Stackoverflow. email: My name, with a dot in the middle and the google mail system.

Updated on July 09, 2022

Comments

  • Ander Biguri
    Ander Biguri almost 2 years

    New version of the typical question of how to convert from std::string to LPCTSTR.

    Reading from different SO posts I learnt that I should do this:

    CreateDirectory(path.c_str(),NULL);
    

    And still the compiler gives error because cannot convert from const char * to LPCTSTR.

    I tried:

    CreateDirectory((LPCTSTR)path.c_str(),NULL);
    

    No errors!

    Still the directory created (in the correct place) is called:

    D:\\something\\㩄ぜ弲久䅓余屓䱆彄湡敤屲䵉ⴱ㠶ⴰⵃㅇ㉜洰⵭就䥄牃獥汵獴촀췍췍췍췍췍췍췍﷍﷽꯽ꮫꮫꮫﺫﻮﻮ
    

    which is not exactly what I wanted, as you can guess...

    So what am I missing? Is it something related with UNICODE/ANSI? How can I resolve this?

    • David Heffernan
      David Heffernan almost 11 years
      The lesson to learn from this is not to cast. Casting blindly is just you telling the compiler to shut up. Try to listen to the compiler.
    • Ander Biguri
      Ander Biguri almost 11 years
      @DavidHeffernan I will listen to the all-knowing master compiler!
  • Ander Biguri
    Ander Biguri almost 11 years
    Yeah, but I will only use it once in the hole program, so as changing from ANSI to UNICODE is a tedious work right now, writting an A in 1 line of code is easy. Your answer is really interesting, I would keep that in mind in the future.
  • Adrian McCarthy
    Adrian McCarthy about 9 years
    This is an incomplete answer. CreateDirectoryA assumes that the string is in the user's current code page. Lots of code uses std::strings to hold UTF-8 (or, less commonly, some other encoding), in which case you should convert (not typecast) the std::string into a UTF-16 WCHAR string and pass that to CreateDirectoryW. Rationale and code samples here: utf8everywhere.org
  • Adrian McCarthy
    Adrian McCarthy about 9 years
    This is fine if the source string is ASCII or if it's ANSI and the current code page is Windows-1252 (which is very similar to Latin-1). If the source is UTF-8 or another code page, then this just hides the problem.
  • Adrian McCarthy
    Adrian McCarthy about 9 years
    You're starting with a path in a std::string with an unknown encoding. The code sample in your answer copies the byte files from that string into the wchar_t values in a std::wstring. CreateDirectoryW expects the wstring to be UTF-16. If the source string is ASCII or Windows-1252, your suggestion will work (in nearly every case). But if the source string is in another encoding, like UTF-8 or Windows-1250, then the wstring will contain nonsense. To make it work in all cases, you need to know the source encoding to convert (not copy) from the source to the wstring.
  • Adrian McCarthy
    Adrian McCarthy about 9 years
    No, that's not what I mean. That's not what happens. Suppose the source string contains a Greek capital letter Beta, encoded as UTF-8. So the source string is 0xCE 0x92. The way you're constructing the wide string, it will contain 0x00CE 0x0092, which is a Latin capital letter I with circumflex followed by a private use character. That's because you did a copy instead of a conversion. My answer explains ways to do the conversion (which requires knowing the source encoding) and has a link to a page with actual code examples.
  • jave.web
    jave.web about 9 years
    Thank you very much for this explanation :) Anyway sorry I've somehow missed your answer x) , could you please clean up the comments so only the important remains ? :) thanks