转换 (const char*) var 出错
Posted
技术标签:
【中文标题】转换 (const char*) var 出错【英文标题】:Conversion (const char*) var goes wrong 【发布时间】:2019-04-09 08:18:26 【问题描述】:我需要在 Embedded Visual C++ 中从 CString 转换为 double,它只支持旧式 C++。我正在使用以下代码
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
谁能帮我得到正确的结果?
【问题讨论】:
您确定源 (str
) 确实指向您认为的字符串吗?如果您在调试器中单步执行代码,它会告诉您什么?
可能是本地化问题。看看setlocale()
。在某些语言(例如德语)中,.
和 ,
的含义是互换的。如果德语语言环境处于活动状态,"4.0"
的解析将在 .
处停止。 (在这种情况下,"4,5"
将返回正确的结果4.5
。)
【参考方案1】:
这里的问题是,你在对编译器撒谎,而编译器信任你。我假设使用 Embedded 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 风格的强制转换来解决它)。
【讨论】:
不幸的是,在 Embedded Visual C++ 4.0 中没有 wchar_t 类型,并且在该版本的 MFC 中没有用于 CString 的方法 GetString。除此之外,您只批评而不回答问题。所以你的评论不相关。 如果编译器不支持wchar_t
,请使用WCHAR
。如果您的 MFC 版本不提供 GetString
成员,请使用 operator LPCWSTR()
。【参考方案2】:
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);
【讨论】:
宏是 ATL 的一部分,而不是 C++ 标准。阅读此内容以获取使用说明docs.microsoft.com/en-us/previous-versions/87zae4a3(v=vs.140)。很可能您不包括标题。 #include #include 不,_wtof 不存在,只有 atof 我没有尝试包含 atldef.h,因为我通过使用 scanf 找到了解决方案(请参阅下面的答案)。但是非常感谢您的帮助。 最后一段是错误的。这里的问题是关于字符编码,而不是正在使用的特定字符。字符串"4.5"
被编码为34 2E 35 00
(ASCII) 和34 00 2E 00 35 00 00 00
(UTF-16 LE)。当您将 Unicode 字符串转换为 ASCII(或 ANSI)字符串时,您会截断它,从而生成字符串 34 00
。后一段代码仅在您的项目设置为使用 MBCS 编码时才有效,这是您不想要的。【参考方案3】:
使用 scanf 找到了解决方案
CString str="4.5"
double var=0.0;
_stscanf( str, _T("%lf"), &var );
这给出了正确的结果var=4.5
感谢大家的cmets和帮助。
【讨论】:
以上是关于转换 (const char*) var 出错的主要内容,如果未能解决你的问题,请参考以下文章
从 const uint8_t* 转换为 uint8_t* 时出错
将 char 数组发送到 DLL 调用“不知道如何转换参数”时出错
164VS2022下VC++调用CreateFile文件名不能接受char*,包括强制转换成LPCWSTR的char*也会出错
164VS2022下VC++调用CreateFile文件名不能接受char*,包括强制转换成LPCWSTR的char*也会出错
VS2008 C++中 inet_addr()函数用法。 inet_addr: 不能将参数 1 从“CString”转换为“const char *”