В своем первом фрагменте кода вы четко компилируете свой проект с определением UNICODE
(что очевидно из вашей способности передать WIN32_FIND_DATA
в FindNextFileW()
без ошибок).Когда определено UNICODE
, WIN32_FIND_DATA
отображается на WIN32_FIND_DATAW
.Но FindFirstFileA()
хочет вместо WIN32_FIND_DATAA
.Таким образом, самое простое решение этой ошибки - просто изменить WIN32_FIND_DATA
на WIN32_FIND_DATAA
, чтобы удовлетворить вызов к FindFirstFileA()
.Но тогда у вас будет новая ошибка, потому что вы будете передавать WIN32_FIND_DATAA
в FindNextFileW()
, который вместо этого хочет WIN32_FIND_DATAW
.Поэтому вам нужно будет вызвать FindNextFileA()
вместо этого, чтобы исправить эту ошибку:
#include <iostream>
#include <string>
#include <Windows.h>
int wmain() {
WIN32_FIND_DATAA data;
std::string dir = "c:\\* ";
HANDLE hFind = FindFirstFileA(dir.c_str(), &data); // DIRECTORY
if (hFind != INVALID_HANDLE_VALUE) {
do {
std::cout << data.cFileName << std::endl;
} while (FindNextFileA(hFind, &data));
FindClose(hFind);
}
return 0;
}
Во втором фрагменте кода std::cout
не содержит перегруженных operator<<
для wchar_t
данных, но этоимеют перегрузку на void*
.Поле WIN32_FIND_DATAW::cFileName
представляет собой массив wchar_t[]
, который распадается в wchar_t*
указатель на 1-й символ, и все указатели неявно преобразуются в void*
.Вот почему вы видите печатные адреса памяти.Вместо этого вам нужно использовать std::wcout
:
#include <iostream>
#include <string>
#include <windows.h>
int wmain()
{
WIN32_FIND_DATAW data;
std::wstring dir = L"c:\\*";
HANDLE hFind = FindFirstFileW(dir.c_str(), &data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
std::wcout << data.cFileName << std::endl;
} while (FindNextFileW(hFind, &data));
FindClose(hFind);
}
}
Большинство Win32 API, которые работают со строковыми данными, имеют разновидности A
(ANSI) и W
(Wide, Unicode) и предоставляют общие TCHAR
макросы на основе для сопоставления с одним или другим условием UNICODE
.В этом случае FindFirstFile()
сопоставляется с FindFirstFileA()
или FindFirstFileW()
, FindNextFile()
сопоставляется либо с FindNextFileA()
или FindNextFileW()
, WIN32_FIND_DATA
сопоставляется с WIN32_FIND_DATAA
или WIN32_FIND_DATAW
и т. Д.
Таким образом, общее правило заключается в том, что суффикс, который вы явно указываете (или опускаете) при вызове функции API, должен также повторяться в любых связанных объявлениях переменных по мере необходимости.Если вы вызываете API-функцию A
явно, явно используйте соответствующие типы переменных A
.Если вы вызываете API-функцию W
явно, явно используйте соответствующие типы переменных W
.Если вы опустите A
/ W
в вызове функции API, опустите его в объявлениях переменных (или замените на T
для TCHAR
, если необходимо).