станд :: радок LPCTSTR

Новая версія тыповы пытанне аб тым, як канвертаваць з станд :: радкі на LPCTSTR .

Чытанне з розных SO пастоў я даведаўся, што я павінен зрабіць гэта:

CreateDirectory(path.c_str(),NULL);

І ўсё ж кампілятар выдасць памылку, таму што не можа пераўтварыць з сопзЬ паўкокс * да LPCTSTR .

Я спрабаваў:

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

Няма памылак!

Тым не менш, створаныя (у правільным месцы) называюцца:

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

што не зусім тое, што я хацеў, як вы можаце здагадацца ...

Так што мне не хапае? Ці з'яўляецца гэта нешта звязанае з UNICODE/ANSI? Як я магу вырашыць гэтую праблему?

11
@DavidHeffernan Я буду слухаць усёведнага майстар-кампілятар!
дададзена аўтар Ander Biguri, крыніца
@DavidHeffernan Я буду слухаць усёведнага майстар-кампілятар!
дададзена аўтар Ander Biguri, крыніца
Урок атрымаць з гэтага не кінуць. Кастынг ўсляпую толькі вы кажаце кампілятар заткнуцца. Паспрабуйце слухаць кампілятар.
дададзена аўтар David Heffernan, крыніца

13 адказы

Ваша задача тут заключаецца ў тым, што LPCTSTR дазволены да wchar_t * або паўкокс * на падставе таго, ці падтрымлівае будаваць сцяг юнікода (Unicode усталяваны ці не ).

Для відавочнага выкліку сімвал * версія, выклік CreateDirectoryA() .

6
дададзена
Гэта няпоўны адказ. CreateDirectoryA мяркуе, што радок знаходзіцца ў бягучай кодавай старонцы карыстальніка. Шмат кода выкарыстоўвае STD :: радка для захоўвання UTF-8 (ці, радзей, некаторыя іншыя кадоўкі), у гэтым выпадку вы павінны пераўтварыць (не надрукаваны) БППП :: радок у UTF-16 WChar радкі і перадаць, што CreateDirectoryW. Абгрунтаванне і прыклады кода тут: utf8everywhere.org
дададзена аўтар Adrian McCarthy, крыніца

Ваша задача тут заключаецца ў тым, што LPCTSTR дазволены да wchar_t * або паўкокс * на падставе таго, ці падтрымлівае будаваць сцяг юнікода (Unicode усталяваны ці не ).

Для відавочнага выкліку сімвал * версія, выклік CreateDirectoryA() .

6
дададзена
Гэта няпоўны адказ. CreateDirectoryA мяркуе, што радок знаходзіцца ў бягучай кодавай старонцы карыстальніка. Шмат кода выкарыстоўвае STD :: радка для захоўвання UTF-8 (ці, радзей, некаторыя іншыя кадоўкі), у гэтым выпадку вы павінны пераўтварыць (не надрукаваны) БППП :: радок у UTF-16 WChar радкі і перадаць, што CreateDirectoryW. Абгрунтаванне і прыклады кода тут: utf8everywhere.org
дададзена аўтар Adrian McCarthy, крыніца

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 *

Робячы гэта: (LPCTSTR) path.c_str() вы прымаеце два сімвала з крынічнай радкі і стварыць з іх адзін Юнікода wchar_t ліст. Тое, як вы атрымліваеце «кітайскія» сімвалы.

5
дададзена

Вы компилируете для Unicode, што азначае, што CreateDirectory гэта псеўданім для CreateDirectoryW , шырокі версія характар. Тым не менш, тэкст у праграме кадуецца з выкарыстаннем ANSI. Гэта азначае, што праграма не можа працаваць належным чынам інтэрнацыяналізацыю.

Кампілятар кажа вам, што існуе неадпаведнасць паміж кадоўкай, што CreateDirectoryW чакае, і кадыроўкі тэксту, які вы падачы. Гэта праўда, што вы маглі б назваць CreateDirectoryA , каб вырашыць, што няправільна матч, але гэта толькі збіраецца ўвекавечыць корань праблемы, той факт, што вы выкарыстоўваеце ANSI тэкст у вашай праграме.

Такім чынам, лепшае рашэнне будзе пачаць кадавальныя увесь ваш тэкст у Unicode. Спыніць выкарыстанне радок і пачаць выкарыстоўваць wstring . Пасля таго, як вы зменіце шлях у wstring то

CreateDirectory(path.c_str(),NULL);

з'яўляецца правільным.

5
дададзена
Так, але я буду выкарыстоўваць яго толькі адзін раз у праграме адтуліны, так як змяненне ад ANSI ў Юнікод з'яўляецца стомнай працы прама зараз, кампазітарства ў А ў 1 радку кода лёгка. Ваш адказ сапраўды цікава, я буду трымаць гэта на ўвазе ў будучыні.
дададзена аўтар Ander Biguri, крыніца

Вы компилируете для Unicode, што азначае, што CreateDirectory гэта псеўданім для CreateDirectoryW , шырокі версія характар. Тым не менш, тэкст у праграме кадуецца з выкарыстаннем ANSI. Гэта азначае, што праграма не можа працаваць належным чынам інтэрнацыяналізацыю.

Кампілятар кажа вам, што існуе неадпаведнасць паміж кадоўкай, што CreateDirectoryW чакае, і кадыроўкі тэксту, які вы падачы. Гэта праўда, што вы маглі б назваць CreateDirectoryA , каб вырашыць, што няправільна матч, але гэта толькі збіраецца ўвекавечыць корань праблемы, той факт, што вы выкарыстоўваеце ANSI тэкст у вашай праграме.

Такім чынам, лепшае рашэнне будзе пачаць кадавальныя увесь ваш тэкст у Unicode. Спыніць выкарыстанне радок і пачаць выкарыстоўваць wstring . Пасля таго, як вы зменіце шлях у wstring то

CreateDirectory(path.c_str(),NULL);

з'яўляецца правільным.

5
дададзена
Так, але я буду выкарыстоўваць яго толькі адзін раз у праграме адтуліны, так як змяненне ад ANSI ў Юнікод з'яўляецца стомнай працы прама зараз, кампазітарства ў А ў 1 радку кода лёгка. Ваш адказ сапраўды цікава, я буду трымаць гэта на ўвазе ў будучыні.
дададзена аўтар Ander Biguri, крыніца

Паколькі гэтае пытанне ўсплывае, калі вы спрабуеце знайсці «(станд: :) радок 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:

<�Р> Гэта добра, калі зыходная радок ASCII або, калі гэта ANSI і   бягучая кодавая старонка Windows-1252 (які вельмі падобны на Latin-1).   Калі крыніца UTF-8 ці іншы код старонкі, то гэта проста хавае   праблема.
5
дададзена
Гэта добра, калі зыходная радок ASCII або, калі гэта ANSI <�я> і бягучая кодавая старонка Windows-1252 (які вельмі падобны на Latin-1). Калі крыніца UTF-8 ці іншы код старонкі, то гэта проста хавае праблему.
дададзена аўтар Adrian McCarthy, крыніца
Вы пачынаеце з шляхам у станд :: радок з невядомай кадоўкай . Прыклад кода ў адказе капіюе байты-файлы з гэтага радка ў значэння wchar_t ў станд :: wstring. CreateDirectoryW чакае, што wstring быць UTF-16. Калі зыходная радок ASCII або Windows-1252, ваша прапанова будзе працаваць (амаль у кожным выпадку). Але калі зыходная радок знаходзіцца ў іншай кадоўцы, як UTF-8 або Windows-1250, то wstring будзе ўтрымліваць нонсэнс. Для таго, каб прымусіць яго працаваць ва ўсіх выпадках, вы павінны ведаць кадыроўку крыніцы для пераўтварэння (не капіяваць) з крыніцы ў wstring.
дададзена аўтар Adrian McCarthy, крыніца
Не, гэта не тое, што я маю на ўвазе. Гэта не тое, што адбываецца. Выкажам здагадку, што зыходная радок утрымлівае загалоўную літару грэцкага Beta, закадаваны ў UTF-8. Такім чынам, зыходная радок 0xCE 0x92 . Тое, як вы будзеце будаваць шырокую радок, яна будзе ўтрымліваць 0x00CE 0x0092 , які з'яўляецца лацінская літара I з наступным циркумфлексом прыватнага выкарыстання сімвала. Гэта таму, што вы зрабілі копію замест пераўтварэнні. Мой адказ тлумачыць спосабы зрабіць пераўтварэнне (што неабходна ведаць кадыроўку зыходнай) і мае спасылку на старонку з рэальнымі прыкладамі кода.
дададзена аўтар Adrian McCarthy, крыніца
Вялікі дзякуй за гэта тлумачэнне :) У любым выпадку шкада, што я так ці інакш прапусціў свой адказ х), не маглі б вы, калі ласка, ачысціць каментары так толькі важныя рэшткі? :) дзякуй
дададзена аўтар jave.web, крыніца

Паколькі гэтае пытанне ўсплывае, калі вы спрабуеце знайсці «(станд: :) радок 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:

<�Р> Гэта добра, калі зыходная радок ASCII або, калі гэта ANSI і   бягучая кодавая старонка Windows-1252 (які вельмі падобны на Latin-1).   Калі крыніца UTF-8 ці іншы код старонкі, то гэта проста хавае   праблема.
5
дададзена
Гэта добра, калі зыходная радок ASCII або, калі гэта ANSI <�я> і бягучая кодавая старонка Windows-1252 (які вельмі падобны на Latin-1). Калі крыніца UTF-8 ці іншы код старонкі, то гэта проста хавае праблему.
дададзена аўтар Adrian McCarthy, крыніца
Вы пачынаеце з шляхам у станд :: радок з невядомай кадоўкай . Прыклад кода ў адказе капіюе байты-файлы з гэтага радка ў значэння wchar_t ў станд :: wstring. CreateDirectoryW чакае, што wstring быць UTF-16. Калі зыходная радок ASCII або Windows-1252, ваша прапанова будзе працаваць (амаль у кожным выпадку). Але калі зыходная радок знаходзіцца ў іншай кадоўцы, як UTF-8 або Windows-1250, то wstring будзе ўтрымліваць нонсэнс. Для таго, каб прымусіць яго працаваць ва ўсіх выпадках, вы павінны ведаць кадыроўку крыніцы для пераўтварэння (не капіяваць) з крыніцы ў wstring.
дададзена аўтар Adrian McCarthy, крыніца
Не, гэта не тое, што я маю на ўвазе. Гэта не тое, што адбываецца. Выкажам здагадку, што зыходная радок утрымлівае загалоўную літару грэцкага Beta, закадаваны ў UTF-8. Такім чынам, зыходная радок 0xCE 0x92 . Тое, як вы будзеце будаваць шырокую радок, яна будзе ўтрымліваць 0x00CE 0x0092 , які з'яўляецца лацінская літара I з наступным циркумфлексом прыватнага выкарыстання сімвала. Гэта таму, што вы зрабілі копію замест пераўтварэнні. Мой адказ тлумачыць спосабы зрабіць пераўтварэнне (што неабходна ведаць кадыроўку зыходнай) і мае спасылку на старонку з рэальнымі прыкладамі кода.
дададзена аўтар Adrian McCarthy, крыніца
Вялікі дзякуй за гэта тлумачэнне :) У любым выпадку шкада, што я так ці інакш прапусціў свой адказ х), не маглі б вы, калі ласка, ачысціць каментары так толькі важныя рэшткі? :) дзякуй
дададзена аўтар jave.web, крыніца

Іншыя тлумачэнні верныя:

CreateDirectory, як і многія з API, вокны, на самай справе макрас, які пашыраецца да «ANSI» або «Wide» версія да залежнасці ад UNICODE вызначаецца ці што. Версіі ANSI эфектыўна пераўтворыць радок сімвалаў однобайтные ў радок шырокіх сімвалаў, а затым дэлегатаў шырокай радка знакаў версіі.

Тым не менш, прапанова назваць CreateDirectoryA непасрэдна прыходзяць з некаторымі недахопамі:

Пераўтварэнні, праведзеныя ў API «ANSI» Выкажам здагадку, што зыходная радок кадуецца ў бягучай кодавай старонкі карыстальніка. У простых выпадках, гэта, верагодна, праўда. Але ў вялікай колькасці рэальных кода, гэта не так. Такім чынам, вы можаце ў канчатковым выніку з няправільным тыпам пераўтварэнні, што прыводзіць да памылак, якія вы знойдзеце значна пазней. Прынамсі, дрэнна надрукаваны прыводзіць да памылак, вы знойдзеце адразу.

Лепшым рашэннем з'яўляецца выкарыстанне шырокіх радкоў (станд :: wstring) па ўсім, і выклікаць CreateDirectoryW. Ніякае пераўтварэнне ня памыліцца. Не патрабуецца прывядзенне тыпаў.

Для многіх кодавых баз, перапісаўшы ўсё, каб выкарыстоўваць шырокія радкі не практычна. Аказваецца, што ёсць важкія прычыны, каб зрабіць як раз наадварот і працягваць выкарыстоўваць STD :: радкі, але стандартаваць мець іх трымаць UTF -8 тэкст . Затым, калі вы павінны выклікаць API для Windows, канвертаваць (не тыпаж) у UTF-16 і выклікаць шырокую версію API напрамую. Гэта дае вам поўную пэўнасць у кошту робіць некалькі пераходаў і некаторыя часовыя буферы. Бо гэтыя тыпы выклікаў рэдка ў гарачых кропках, кошт звычайна не мае вялікага значэння.

У Windows для пераўтварэння паміж UTF-8 і UTF-16, вы можаце патэлефанаваць MultiByteToWideChar/WideCharToMultiByte з кодавай старонкай, усталяванай у CP_UTF8.

1
дададзена

Іншыя тлумачэнні верныя:

CreateDirectory, як і многія з API, вокны, на самай справе макрас, які пашыраецца да «ANSI» або «Wide» версія да залежнасці ад UNICODE вызначаецца ці што. Версіі ANSI эфектыўна пераўтворыць радок сімвалаў однобайтные ў радок шырокіх сімвалаў, а затым дэлегатаў шырокай радка знакаў версіі.

Тым не менш, прапанова назваць CreateDirectoryA непасрэдна прыходзяць з некаторымі недахопамі:

Пераўтварэнні, праведзеныя ў API «ANSI» Выкажам здагадку, што зыходная радок кадуецца ў бягучай кодавай старонкі карыстальніка. У простых выпадках, гэта, верагодна, праўда. Але ў вялікай колькасці рэальных кода, гэта не так. Такім чынам, вы можаце ў канчатковым выніку з няправільным тыпам пераўтварэнні, што прыводзіць да памылак, якія вы знойдзеце значна пазней. Прынамсі, дрэнна надрукаваны прыводзіць да памылак, вы знойдзеце адразу.

Лепшым рашэннем з'яўляецца выкарыстанне шырокіх радкоў (станд :: wstring) па ўсім, і выклікаць CreateDirectoryW. Ніякае пераўтварэнне ня памыліцца. Не патрабуецца прывядзенне тыпаў.

Для многіх кодавых баз, перапісаўшы ўсё, каб выкарыстоўваць шырокія радкі не практычна. Аказваецца, што ёсць важкія прычыны, каб зрабіць як раз наадварот і працягваць выкарыстоўваць STD :: радкі, але стандартаваць мець іх трымаць UTF -8 тэкст . Затым, калі вы павінны выклікаць API для Windows, канвертаваць (не тыпаж) у UTF-16 і выклікаць шырокую версію API напрамую. Гэта дае вам поўную пэўнасць у кошту робіць некалькі пераходаў і некаторыя часовыя буферы. Бо гэтыя тыпы выклікаў рэдка ў гарачых кропках, кошт звычайна не мае вялікага значэння.

У Windows для пераўтварэння паміж UTF-8 і UTF-16, вы можаце патэлефанаваць MultiByteToWideChar/WideCharToMultiByte з кодавай старонкай, усталяванай у CP_UTF8.

1
дададзена

Выкарыстоўвайце CreateDirectoryA замест гэтага. <�Код> CreateDirectory гэта макрас, які пашырае альбо CreateDirectoryA або CreateDirectoryW у залежнасці ад канфігурацыі зборкі; Яны прымаюць адпаведна LPCSTR і LPCWSTR . Калі вы ведаеце, у вас ёсць LPCSTR (што c_str() дае вам), выкарыстоўвайце першы.

1
дададзена

Выкарыстоўвайце CreateDirectoryA замест гэтага. <�Код> CreateDirectory гэта макрас, які пашырае альбо CreateDirectoryA або CreateDirectoryW у залежнасці ад канфігурацыі зборкі; Яны прымаюць адпаведна LPCSTR і LPCWSTR . Калі вы ведаеце, у вас ёсць LPCSTR (што c_str() дае вам), выкарыстоўвайце першы.

1
дададзена

Я змагаўся з гэтым доўгі час. Пасля зусім няшмат капання, я знайшоў, што гэта працуе лепш; Вы можаце паспрабаваць наступнае:

std::string t = "xyz";
CA2T wt (t.c_str());     
0
дададзена

Я змагаўся з гэтым доўгі час. Пасля зусім няшмат капання, я знайшоў, што гэта працуе лепш; Вы можаце паспрабаваць наступнае:

std::string t = "xyz";
CA2T wt (t.c_str());     
0
дададзена