转换 (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 *”

varlet和const