__int64到CString返回错误的值-C ++ MFC

时间:2018-09-25 09:28:27

标签: c++ mfc printf c-strings int64

我想将__int64变量转换为CString。代码就是这个

effect

第一个printf打印

dt[, rank:=order(effect,  decreasing = T), by=c('src')]

这是正确的,但是第二个printf随机打印高数字,例如

    > dt variable src effect rank 1: var1 A 0.0047950319 5 2: var1 B 0.0052094522 5 3: var2 A 0.0414826536 2 4: var2 B 0.0534395645 2 5: var3 A 0.0032120294 4 6: var3 B 0.0042620197 4 7: var4 A 0.0207942300 1 8: var4 B 0.0268992334 1 9: var5 A 0.3048336544 3 10: var5 B 0.2913103031 3

我也尝试使用INT64变量而不是__int64变量,但是结果是相同的。这可能是什么原因?

3 个答案:

答案 0 :(得分:10)

这里:

totalSpace.Format(_T("%I64d", i64TotalGB));

您要将i64TotalGB作为参数传递给_T() macro,而不是将其作为第二个参数传递给Format()

尝试一下:

totalSpace.Format(_T("%I64d"), i64TotalGB);

话虽如此,由于MS围绕字符编码的混乱(ha),在这里使用_T是不正确的,因为CStringTCHAR而不是{{ 1}}。因此,考虑到这一点,最好使用_TCHAR而不是TEXT(),因为它取决于T()而不是UNICODE

_UNICODE

此外,此行是错误的,因为它试图将ATL totalSpace.Format(TEXT("%I64d"), i64TotalGB); 作为CString(也就是 C样式字符串)传递:

char*

编译器为此发出警告:

printf("totalSpace contains: %s", totalSpace);

尽管warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'ATL::CString' 的结构实际上可以像您传递它那样兼容,但这仍然是形式上未定义的行为。使用CString进行防御:

CString::GetString()

请注意,printf("totalSpace contains: %ls", totalSpace.GetString()); 如我的配置%ls返回了totalSpace.GetString()。但是,作为"printf does not currently support output into a UNICODE stream."的这一行的正确版本将支持您当前code page之外的字符,它是通过以下方式调用const wchar_t*的:

wprintf()

话虽如此,这是一个一般性建议,无论问题背后的直接问题是什么。如今,更好的做法已经完全不同了,我引用@IInspectable的恰当回答,说“通用文本映射在20年前是相关的”。

有什么选择?在没有足够充分理由的情况下,请尝试明确地坚持使用wprintf("totalSpace contains: %s", totalSpace.GetString()); A Unicode character type string with CRT support )。根据您的程序中已定义常量CStringW还是_UNICODE,优先使用L character literal而不是古老的data/text mappings。相反,更好的做法是使用所有API和语言库调用的宽字符版本,例如wprintf()而不是_MBCS

答案 1 :(得分:6)

该错误是由于代码中的许多问题导致的,特别是这些2:

  • totalSpace.Format(_T("%I64d", i64TotalGB));

    这以不应该使用的方式使用_T macro。它应该包装单个字符串文字。在代码中,它包装了第二个参数。

  • printf("totalSpace contains: %s", totalSpace);

    这假定使用ANSI编码的字符串,但传递一个CString对象,该对象可以存储ANSI和Unicode编码的字符串。

建议采取的措施是完全放弃generic-text mappings,以便在整个 1 中使用Unicode(Windows上为UTF-16LE)。通用文本映射在20年前就很有意义,以简化Win9x代码向基于Windows NT的产品的移植。

为此

  • CStringW上选择CString
  • 丢弃所有出现的_TTEXT_TEXT,并用L前缀替换。
  • 使用Windows API,CRT和C ++标准库的宽字符版本。

固定代码如下:

__int64 i64TotalGB;
CStringW totalSpace;  // Use wide-character string
i64TotalGB = 150;
printf("disk space: %I64d GB\n", i64TotalGB);
totalSpace.Format(L"%I64d", i64TotalGB);  // Use wide-character string literal
wprintf(L"totalSpace contains: %s", totalSpace.GetString());  // Use wide-character library

无关紧要的是,尽管在变量变元列表中传递CString对象代替字符指针在技术上是安全的,但这是实现的详细信息,并未正式记录为有效。如果您关心正确的代码,请致电CString::GetString()


1 除非有正当理由使用使用char作为其基础类型的字符编码(例如UTF-8或ANSI)。在那种情况下,您仍然应该使用CStringA来明确表示它。

答案 2 :(得分:2)

尝试

totalSpace.Format(_T("%I64d"), i64TotalGB);