Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Преобразование char* -> wchar_t -> char*

2.1K
02 апреля 2011 года
foxby
44 / / 16.07.2003
Может кто подскажет, как правильно преобразовывать wchar_t в char* и наоборот char* в wchar_t ?

IDE: C++ Builder :: Embarcadero RAD Studio XE (build 3953, +update1)

Пример кода, при выполнении которого вместо номера версии файла (типа 1.2.34.567) выдается не читаемый текст. Функции, которая определяет версию файла, должно передаваться имя файла в char*, и результат возвращает она тоже в char*. Но в форму нужно уже подставлять значение в wchar_t.

 
Код:
char* __fastcall GetFileVer(char* sFileName) {
   ...
   return(result);
}

char* szFileVersion = GetFileVer( (char*)Application->ExeName.c_str() );

AboutVersionLbl->Caption = AboutVersionLbl->Caption + (wchar_t)szFileVersion;


Использование макросов типа _TEXT('...') не решает проблему.
(в программе используется только английский язык)

Спасибо.
278
02 апреля 2011 года
Alexander92
1.1K / / 04.08.2008
Цитата: foxby
Может кто подскажет, как правильно преобразовывать wchar_t в char* и наоборот char* в wchar_t ?



MultiByteToWideChar
WideCharToMultiByte

2.1K
02 апреля 2011 года
foxby
44 / / 16.07.2003
Спасибо. Но эти функции как-то нерационально использовать - там табун параметров в каждой.
Хочется найти более лаконичное решение, и именно используя код C++ Builder, а не Microsoft C++.
278
02 апреля 2011 года
Alexander92
1.1K / / 04.08.2008
Ну раз уж на то пошло, то самый прозрачный вариант - это через sprintf / swprintf.

char* -> wchar_t*:
 
Код:
swprintf(wstr, L"%S", str);


wchar_t* -> char*:
 
Код:
sprintf(str, "%S", wstr);
2.1K
02 апреля 2011 года
foxby
44 / / 16.07.2003
Спасибо. Половину проблемы решил.

Код:
char* __fastcall GetFileVer(char* sFileName) {
   ...
   return(result);
}

char* szFileVersion;
wchar_t* szFileVersionW;
sprintf(szFileVersion, "%S", Application->ExeName.c_str());
szFileVersion = GetFileVer( szFileVersion ) ;
ShowMessage( szFileVersion );
swprintf(szFileVersionW, L"%S", szFileVersion);
AboutVersionLbl->Caption = AboutVersionLbl->Caption + szFileVersionW;


ShowMessage( szFileVersion ); - теперь выводит читабельную строку с версией файла.
Но как правильно обратно преобразовать в wchar_t? При всевозможных манипуляциях со строкой,
 
Код:
AboutVersionLbl->Caption = AboutVersionLbl->Caption + (wchar_t)szFileVersion;

включая использование перед ней преобразование с функцией swprintf(...), происходит исключение типа "access violation..."

Может это потому, что вроде swprintf и sprintf не добавляет закрывающий "0" в буфер переменной-строки?
278
02 апреля 2011 года
Alexander92
1.1K / / 04.08.2008
 
Код:
wchar_t szBuffer[10] = {'\0'};
swprintf(szBuffer, L"%S", szFileVersion);
AboutVersionLv1->Caption = wcscat(AboutVersionLv1->Caption, szBuffer);


Почитайте про строки и указатели в Си. Я начну хотя бы с того, что wchar_t - это не указатель на строку, как вы пишете, указателем будет wchar_t *.
2.1K
02 апреля 2011 года
foxby
44 / / 16.07.2003
Alexander92,
к сожалению предложенный вами вариант тоже не подходит, т.к. в этом случает выдается ошибка:
 
Код:
E2034 Cannot convert 'UnicodeString' to 'wchar_t *

Ошибка указывает на строку
 
Код:
AboutVersionLbl->Caption = wcscat(AboutVersionLbl->Caption, szBuffer);
278
02 апреля 2011 года
Alexander92
1.1K / / 04.08.2008
Виноват, не работаю с билдером, поэтому написал немного не то.

 
Код:
wchar_t szBuffer[10] = {'\0'};
swprintf(szBuffer, L"%S", szFileVersion);
AboutVersionLbl->Caption += UnicodeString(szBuffer);


Вот что вам нужно.
2.1K
02 апреля 2011 года
foxby
44 / / 16.07.2003
Alexander92,
если вот такой код запустить на выполнение, то заголовок попросту будет заменен на "12345", т.е. он не "склеивается", а попросту заменяется.
 
Код:
char* szFileVersion;
wchar_t szBuffer[10] = {'\0'};
swprintf(szBuffer, L"%S", "12345");
AboutVersionLbl->Caption += UnicodeString(szBuffer);

Вот при таком коде уже работает как надо
 
Код:
wchar_t szBuffer[10] = {'\0'};
swprintf(szBuffer, L"%S", " 12345");
AboutVersionLbl->Caption = AboutVersionLbl->Caption + UnicodeString(szBuffer);


Спасибо за советы и потраченное на меня время.
В целом я разочарован в Embarcadero XE. Не ожидал, что вроде бы простые манипуляции со строками будут так напрягать, да и усложнять сам исходный код. Хотя может все же есть нормальные методы, но видимо они спрятаны где-то глубоко в документации :)
278
02 апреля 2011 года
Alexander92
1.1K / / 04.08.2008
Цитата: foxby
Alexander92,
если вот такой код запустить на выполнение, то заголовок попросту будет заменен на "12345", т.е. он не "склеивается", а попросту заменяется.
 
Код:
char* szFileVersion;
wchar_t szBuffer[10] = {'\0'};
swprintf(szBuffer, L"%S", "12345");
AboutVersionLbl->Caption += UnicodeString(szBuffer);


Возможно, но в любом случае, это уже особенности реализации operator+=() в конкретном классе UnicodeString.

535
02 апреля 2011 года
Нездешний
537 / / 17.01.2008
[QUOTE=foxby]Не ожидал, что вроде бы простые манипуляции со строками будут так напрягать[/QUOTE]В справку со словами AnsiString, WideString

 
Код:
char* szFileVersion = GetFileVer(const_cast<char*>(Application->ExeName.c_str()) );
AboutVersionLbl->Caption = AboutVersionLbl->Caption + WideString(szFileVersion);


Операторы += для VCL классов не работают, поскольку VCL реализован на дельфи, а там такого нет. В связи с этим во многих местах нумерация массивов начинается с 1, а не с 0. В случае со строками это именно так. Читайте справку и будьте внимательны.
2.1K
02 апреля 2011 года
foxby
44 / / 16.07.2003
Нездешний,
это было бы здорово, но вот заморочка все же остается:
 
Код:
E2031 Cannot cast from 'wchar_t *' to 'char *'

Может еще как-нить можно или нужно преобразовать тип для Application->ExeName.c_str() ?
535
02 апреля 2011 года
Нездешний
537 / / 17.01.2008
Загляните уже в справку
Есть конструктор AnsiString(wchar_t*)
Далее есть метод c_str()
2.1K
02 апреля 2011 года
foxby
44 / / 16.07.2003
Спасибо всем за помощь и наводки.
В результате упорных скитаний по справкам нашел решение проблемы, используя функцию [COLOR="blue"]wcstombs[/COLOR]
Код:
char* __fastcall GetFileVer(char* sFileName) {
   ...
   // здесь код извлечения номера версии из исполняемого файла
   return(result);
}

char* szFileVersion; // для номера версии файла
char* pbuf = (char*) malloc( Application->ExeName.Length() ); // выделяем память для буфера
wcstombs( pbuf, Application->ExeName.c_str(), Application->ExeName.Length() ); // преобразуем wchar_t* в char* строку
szFileVersion = GetFileVer( pbuf ); // получаем номер версии в строку типа char*
AboutVersionLbl->Caption = AboutVersionLbl->Caption + WideString( szFileVersion ); // склеиваем заголовок метки с номером версии файла


Однако новая проблема появилась:
- если запускать программу из под IDE нажатием F9 (Run), то номер версии отображается нормально;
- если же запускать скомпилированный файл (или через Shift+Ctrl+F9), то номер версии нечитабельный, причем при каждом запуске программы отображается разный набор символов;

С чем это может быть связано?
535
02 апреля 2011 года
Нездешний
537 / / 17.01.2008
 
Код:
char *szFileVersion = GetFileVer(AnsiString(Application->ExeName).c_str());
AboutVersionLbl->Caption = AboutVersionLbl->Caption + WideString(szFileVersion);
2.1K
03 апреля 2011 года
foxby
44 / / 16.07.2003
Нездешний, спасибо! Работает ваш код как надо!
Коротко и наглядно. Я просто как-то не задумывался об AnsiString-преобразовании, т.к. сами Embarcadero-вцы писали, что надо в C++ избавляться от AnsiString.

Я заодно нашел причину вот этой проблемы
Цитата:
- если запускать программу из под IDE нажатием F9 (Run), то номер версии отображается нормально;
- если же запускать скомпилированный файл (или через Shift+Ctrl+F9), то номер версии нечитабельный, причем при каждом запуске программы отображается разный набор символов;


Оказался виновным Code Guard, и когда я его в свойствах проекта отключил, то теперь и под IDE, и при запуске скомпилированного файла отображаются нормальные читабельные символы.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог