Преобразование (const char *) var идет не так - PullRequest
1 голос
/ 09 апреля 2019

Мне нужно конвертировать из CString в double в Embedded Visual C ++, который поддерживает только старый стиль C ++. Я использую следующий код

CString str = "4.5"; double var = atof( (const char*) (LPCTSTR) str )

и resutlt var=4.0, поэтому я теряю десятичные цифры. Я сделал еще один тест

LPCTSTR str = "4.5"; const char* var = (const char*) str

и результат снова var=4.0 Может ли кто-нибудь помочь мне получить правильный результат?

Ответы [ 3 ]

1 голос
/ 09 апреля 2019

Проблема здесь в том, что вы лжете компилятору, а компилятор доверяет вам. Используя Embedded Visual C ++, я предполагаю, что вы нацелены на Windows CE. Windows CE предоставляет только поверхность API Unicode, поэтому ваш проект, скорее всего, будет использовать Unicode (кодировка UTF-16 LE).

В этом случае CString расширяется до CStringW, в котором кодовые единицы хранятся как wchar_t. Делая (const char*) (LPCTSTR) str, вы затем кастуете с wchar_t const* на char const*. Учитывая ввод, первый байт имеет значение 52 (кодировка ASCII для символа 4). Второй байт имеет значение 0. Это интерпретируется как терминатор строки в стиле C. Другими словами, вы передаете строку "4" на ваш вызов atof. Естественно, в результате вы получите значение 4.0.

Чтобы исправить код, используйте что-то вроде следующего:

CStringW str = L"4.5";
double var = _wtof( str.GetString() );

_wtof является специфическим для Microsoft расширением CRT.

Обратите внимание на две особенности:

  • В коде используется вариант CString с явным кодированием символов (CStringW). Всегда будьте откровенны в отношении ваших строковых типов. Это помогает читать ваш код и отлавливать ошибки до того, как они произойдут (хотя все эти приведения в стиле C в исходном коде полностью опровергают это).
  • Код вызывает элемент CString :: GetString для получения указателя на неизменяемый буфер. Это также облегчает чтение кода, поскольку не использует то, что выглядит как приведение в стиле C (но вместо этого - оператор).

Также рассмотрите возможность определения макроса _CSTRING_DISABLE_NARROW_WIDE_CONVERSION , чтобы предотвратить случайное преобразование набора символов (например, CString str = "4.5";). Это также поможет вам рано обнаруживать ошибки (если только вы не победите их с помощью приведения в стиле C).

1 голос
/ 09 апреля 2019

CString не const char* Чтобы преобразовать строку TCHAR CSt в ASCII, используйте макрос CT2A - это также позволит вам преобразовать строку в UTF8 (или любую другую кодовую страницу Windows):

// Convert using the local code page
CString str(_T("Hello, world!"));
CT2A ascii(str);
TRACE(_T("ASCII: %S\n"), ascii.m_psz);

// Convert to UTF8
CString str(_T("Some Unicode goodness"));
CT2A ascii(str, CP_UTF8);
TRACE(_T("UTF8: %S\n"), ascii.m_psz);
0 голосов
/ 09 апреля 2019

Нашел решение, используя scanf

CString str="4.5" double var=0.0; _stscanf( str, _T("%lf"), &var );

Это дает правильный результат var=4.5 Спасибо всем за комментарии и помощь.

...