Я хочу преобразовать переменную __int64 в CString. Код именно такой
__int64 i64TotalGB;
CString totalSpace;
i64TotalGB = 150;
printf("disk space: %I64d GB\n", i64TotalGB);
totalSpace.Format(_T("%I64d", i64TotalGB));
printf("totalSpace contains: %s", totalSpace);
первый printf выводит
"disk space: 150GB"
что правильно, но второй printf печатает случайные высокие числа, например "totalSpace contains: 298070026817519929"
Я также пробовал использовать переменную INT64 вместо переменной __int64, но результат тот же. Что может быть причиной этого?





попробуй это
totalSpace.Format(_T("%I64d"), i64TotalGB);
Здесь:
totalSpace.Format(_T("%I64d", i64TotalGB));
вы передаете i64TotalGB в качестве аргумента _T() макрос вместо того, чтобы передавать его в качестве второго аргумента в Format().
Попробуй это:
totalSpace.Format(_T("%I64d"), i64TotalGB);
Сказав это, благодаря беспорядку (ха) MS с кодировками символов, использование _T здесь не является правильным, поскольку CString состоит из TCHAR, а не из _TCHAR. Поэтому, принимая это во внимание, можно также использовать TEXT() вместо T(), поскольку он зависит от UNICODE, а не от _UNICODE:
totalSpace.Format(TEXT("%I64d"), i64TotalGB);
Кроме того, эта строка неверна, поскольку она пытается передать ATL CString как char* (он же Строка в стиле C):
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() вернул const wchar_t*. Однако, как «printf в настоящее время не поддерживает вывод в поток UNICODE.», правильная версия для этой строки, которая будет поддерживать символы за пределами вашего текущего кодовая страница, - это вызов wprintf() следующим образом:
wprintf("totalSpace contains: %s", totalSpace.GetString());
Сказав ВСЕ это, вот общий совет, независимо от прямой проблемы, стоящей за вопросом. В настоящее время гораздо лучшая практика немного отличается, и я цитирую респектабельный ответ @IInspectable, в котором говорится, что "отображение общего текста было актуально два десятилетия назад".
Какая альтернатива? При отсутствии достаточно веских причин попробуйте явно придерживаться CStringW (Строка символьного типа Unicode с поддержкой CRT). Предпочитайте Lсимвольный литерал архаичному сопоставления данных / текста, чем зависит от того, определена ли в вашей программе константа _UNICODE или _MBCS. И наоборот, лучше было бы использовать версии всех API и языковых библиотек для расширенных символов, такие как wprintf() вместо printf().
@IInspectable Теперь я вижу это в документах:«printf в настоящее время не поддерживает вывод в поток UNICODE». - внес правку, чтобы отразить. довольно деталь, но достаточно важная, чтобы отметить ИМХО
Ошибка является результатом множества проблем с кодом, в частности этих двух:
totalSpace.Format(_T("%I64d", i64TotalGB));
При этом _T макрос используется не так, как предполагается. Он должен заключаться в односимвольный строковый литерал. В коде он заключает в себе второй аргумент.
printf("totalSpace contains: %s", totalSpace);
Это предполагает символьную строку в кодировке ANSI, но передает объект CString, который может хранить как строки в кодировке ANSI, так и строки в кодировке Unicode.
Рекомендуемый курс действий - полностью отказаться от сопоставления универсального текста в пользу использования Unicode (это UTF-16LE в Windows) во всем 1. Сопоставления универсального текста были актуальны два десятилетия назад, чтобы упростить перенос кода 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.
Общий совет: перестаньте притворяться, что вы нацеливались на Win9x. Ты не такой. Используйте
CStringWвместоCString, замените_Tи аналогичные макросы префиксомLи живите счастливой жизнью с тех пор. Другими словами:CStringW totalSpace; totalSpace.Format(L"%I64d", i64TotalGB); wprintf(L"totalSpace contains: %s", totalSpace.GetString());.