我想将__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变量,但是结果是相同的。这可能是什么原因?
答案 0 :(得分:10)
这里:
totalSpace.Format(_T("%I64d", i64TotalGB));
您要将i64TotalGB
作为参数传递给_T()
macro,而不是将其作为第二个参数传递给Format()
。
尝试一下:
totalSpace.Format(_T("%I64d"), i64TotalGB);
话虽如此,由于MS围绕字符编码的混乱(ha),在这里使用_T
是不正确的,因为CString
由TCHAR
而不是{{ 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
。_T
,TEXT
和_TEXT
,并用L
前缀替换。固定代码如下:
__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);