转换(const char*)var出错
Conversion (const char*) var goes wrong
我需要在仅支持旧式 C++ 的嵌入式 Visual C++ 中将 CString 转换为 double。我正在使用以下代码
CString str = "4.5";
double var = atof( (const char*) (LPCTSTR) str )
结果是 var=4.0
,所以我丢失了小数位。
我又做了一个测试
LPCTSTR str = "4.5";
const char* var = (const char*) str
再次得到结果var=4.0
谁能帮我得到正确的结果?
CString
不是 const char*
要将 TCHAR CString 转换为 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);
找到使用 scanf 的解决方案
CString str="4.5"
double var=0.0;
_stscanf( str, _T("%lf"), &var );
这给出了正确的结果var=4.5
感谢大家的评论和帮助。
这里的问题是,你在欺骗编译器,而编译器信任你。使用嵌入式 Visual C++ 我将假设您的目标是 Windows CE。 Windows CE 仅公开 Unicode API 表面,因此您的项目很可能设置为使用 Unicode(UTF-16 LE 编码)。
在这种情况下,CString
扩展为 CStringW
,它将代码单元存储为 wchar_t
。当执行 (const char*) (LPCTSTR) str
时,您将从 wchar_t const*
转换为 char const*
。给定输入,第一个字节的值为 52(字符 4
的 ASCII 编码)。第二个字节的值为 0。这被解释为 C 风格字符串的终止符。换句话说,您将字符串 "4"
传递给对 atof
的调用。当然,您会得到值 4.0
作为结果。
要修复代码,请使用如下内容:
CStringW str = L"4.5";
double var = _wtof( str.GetString() );
_wtof 是 Microsoft 对其 CRT 的特定扩展。
特别注意两件事:
- 该代码使用具有 显式 字符编码 (
CStringW
) 的 CString
变体。始终明确说明您的字符串类型。这有助于阅读您的代码并在错误发生之前发现错误(尽管原始代码中的所有那些 C 风格转换完全失败了)。
- 代码调用 CString::GetString 成员来检索指向不可变缓冲区的指针。这也使代码更易于阅读,因为它不使用看起来像 C 风格的类型转换(而是一个运算符)。
同时考虑定义 _CSTRING_DISABLE_NARROW_WIDE_CONVERSION 宏以防止发生无意的字符集转换(例如 CString str = "4.5";
)。这也可以帮助您及早发现错误(除非您也使用 C 风格的强制转换来克服错误)。
我需要在仅支持旧式 C++ 的嵌入式 Visual C++ 中将 CString 转换为 double。我正在使用以下代码
CString str = "4.5";
double var = atof( (const char*) (LPCTSTR) str )
结果是 var=4.0
,所以我丢失了小数位。
我又做了一个测试
LPCTSTR str = "4.5";
const char* var = (const char*) str
再次得到结果var=4.0
谁能帮我得到正确的结果?
CString
不是 const char*
要将 TCHAR CString 转换为 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);
找到使用 scanf 的解决方案
CString str="4.5"
double var=0.0;
_stscanf( str, _T("%lf"), &var );
这给出了正确的结果var=4.5
感谢大家的评论和帮助。
这里的问题是,你在欺骗编译器,而编译器信任你。使用嵌入式 Visual C++ 我将假设您的目标是 Windows CE。 Windows CE 仅公开 Unicode API 表面,因此您的项目很可能设置为使用 Unicode(UTF-16 LE 编码)。
在这种情况下,CString
扩展为 CStringW
,它将代码单元存储为 wchar_t
。当执行 (const char*) (LPCTSTR) str
时,您将从 wchar_t const*
转换为 char const*
。给定输入,第一个字节的值为 52(字符 4
的 ASCII 编码)。第二个字节的值为 0。这被解释为 C 风格字符串的终止符。换句话说,您将字符串 "4"
传递给对 atof
的调用。当然,您会得到值 4.0
作为结果。
要修复代码,请使用如下内容:
CStringW str = L"4.5";
double var = _wtof( str.GetString() );
_wtof 是 Microsoft 对其 CRT 的特定扩展。
特别注意两件事:
- 该代码使用具有 显式 字符编码 (
CStringW
) 的CString
变体。始终明确说明您的字符串类型。这有助于阅读您的代码并在错误发生之前发现错误(尽管原始代码中的所有那些 C 风格转换完全失败了)。 - 代码调用 CString::GetString 成员来检索指向不可变缓冲区的指针。这也使代码更易于阅读,因为它不使用看起来像 C 风格的类型转换(而是一个运算符)。
同时考虑定义 _CSTRING_DISABLE_NARROW_WIDE_CONVERSION 宏以防止发生无意的字符集转换(例如 CString str = "4.5";
)。这也可以帮助您及早发现错误(除非您也使用 C 风格的强制转换来克服错误)。