我是c ++的新手。我试图在dir中列出文件。我使用的是unicode。问题不是列出文件,而是用wchar *处理字符串和路径,我疯了。这是我的测试代码:
#define UNICODE 1
#include <stdio.h>
#include <windows.h>
#include <wchar.h>
int wmain(int argc,wchar_t **argv){
if (argc > 1){
wchar_t* path=argv[1];
wchar_t* pwc;
int last_occurence;
pwc=wcsrchr(path,L'\\');
last_occurence = pwc-path+1;
int len = wcslen(path);
if (last_occurence == len){
//slash
}else{
//no slash
wcscat(path,L"\\");
}
wcscat(path,L"*");
WIN32_FIND_DATA FindData;
HANDLE hSearch;
hSearch = FindFirstFile(path , &FindData);
if(hSearch == INVALID_HANDLE_VALUE){
return -1;
}else{
// *** PROBLEM STARTS HERE
wchar_t* filePath=NULL;
do{
wcscpy(filePath,path);
wcscat(filePath,FindData.cFileName);
wprintf(L"Path %s\n",filePath);
memset(filePath, '\0', wcslen(filePath));
// *** PROBLEM ENDS HERE
}while( FindNextFile(hSearch, &FindData) > 0 );
int ret = FindClose(hSearch);
return 0;
}
}
}
当我运行已编译的应用程序时,它会停止响应。我想要做的是打印我传递给我的应用程序的路径(c:\ dir1 \ dir2)并将文件附加到其中(file1,file2),如下所示:
C:\ DIR1 \ DIR2 \文件1
C:\ DIR1 \ DIR2 \ file2的
如何解决这个问题?有最好的方法可以做这样的事情吗?如果可能的话,我会继续使用wchar而不是std字符串
答案 0 :(得分:1)
您的代码存在一些问题。
您将"\\*"
连接到argv[1]
指向的内存,这是不好的。您需要将path
从wchar_t*
指针更改为wchar_t[]
数组,然后将wcscpy
argv[1]
数据更改为{。
您没有为filePath
分配任何内存,因此wcscpy()
和wcscat()
正在写入无效内存。您还需要将filePath
更改为wchar_t[]
数组,然后将wcscpy
/ wcscat
路径数据更改为该数组。
将*
和path
值组合在一起时,您也不会忽略连结的cFileNames
。
您根本不需要memset()
(特别是因为您无论如何都要给它错误的字节数)。
尝试更像这样的东西:
#define UNICODE 1
#include <stdio.h>
#include <windows.h>
#include <wchar.h>
int wmain(int argc, wchar_t **argv)
{
if (argc < 2)
{
wprintf(L"Usage: \"%s\" path\n", argv[0]);
return -1;
}
int len = wcslen(argv[1]);
if (len >= MAX_PATH)
{
wprintf(L"Path is too long\n");
return -1;
}
wchar_t path[MAX_PATH+1] = {};
wcscpy(path, argv[1]);
if ((len > 0) && (path[len-1] != L'\\'))
wcscat(path, L"\\");
wchar_t searchMask[MAX_PATH+2] = {};
wcscpy(searchMask, path);
wcscat(searchMask, L"*");
WIN32_FIND_DATA FindData;
HANDLE hSearch = FindFirstFileW(searchMask, &FindData);
if (hSearch == INVALID_HANDLE_VALUE)
{
if (GetLastError() != ERROR_FILE_NOT_FOUND)
{
wprintf(L"Error looking for first file\n");
return -1;
}
wprintf(L"No files found\n");
}
else
{
wchar_t filePath[MAX_PATH*2];
do
{
wcscpy(filePath, path);
wcscat(filePath, FindData.cFileName);
wprintf(L"Path %s\n", filePath);
}
while (FindNextFileW(hSearch, &FindData));
if (GetLastError() != ERROR_NO_MORE_FILES)
{
FindClose(hSearch);
wprintf(L"Error looking for next file\n");
return -1;
}
FindClose(hSearch);
}
return 0;
}
尽管如此,您确实应该使用std::unique_ptr
和std::wstring
类,让他们为您管理内存/资源。使用C库函数无助于您学习C ++:
#define UNICODE 1
#include <windows.h>
#include <wchar.h>
#include <iostream>
#include <string>
#include <memory>
struct FindDeleter
{
typedef HANDLE pointer;
void operator()(HANDLE h)
{
if(h != INVALID_HANDLE_VALUE)
FindClose(h);
}
};
int wmain(int argc, wchar_t **argv)
{
if (argc < 2)
{
std::wcerr << L"Usage: \"" << argv[0] << L"\" path" << std::endl;
return -1;
}
std::wstring path = argv[1];
if ((!path.empty()) && (path[path.length()-1] != L'\\'))
path += L'\\';
WIN32_FIND_DATA FindData;
std::unique_ptr<HANDLE, FindDeleter> hSearch(FindFirstFileW((path + L"*").c_str(), &FindData));
if (hSearch.get() == INVALID_HANDLE_VALUE)
{
if (GetLastError() != ERROR_FILE_NOT_FOUND)
{
std::wcerr << L"Error looking for first file" << std::endl;
return -1;
}
std::wcout << L"No files found" << std::endl;
}
else
{
do
{
std::wstring filePath = path + FindData.cFileName;
std::wcout << L"Path " << filePath << std::endl;
}
while (FindNextFileW(hSearch.get(), &FindData));
if (GetLastError() != ERROR_NO_MORE_FILES)
{
std::wcerr << L"Error looking for next file" << std::endl;
return -1;
}
}
return 0;
}
或者,如果您不使用C ++ 11编译器:
#define UNICODE 1
#include <windows.h>
#include <wchar.h>
#include <iostream>
#include <string>
class FindHandle
{
private:
HANDLE m_hFind;
public:
FindHandle(HANDLE hFind) : m_hFind(hFind) {}
~FindHandle()
{
if (m_hFind != INVALID_HANDLE_VALUE)
FindClose(m_hFind);
}
HANDLE get() { return m_hFind; }
};
int wmain(int argc, wchar_t **argv)
{
if (argc < 2)
{
std::wcerr << L"Usage: \"" << argv[0] << L"\" path" << std::endl;
return -1;
}
std::wstring path = argv[1];
if ((!path.empty()) && (path[path.length()-1] != L'\\'))
path += L'\\';
WIN32_FIND_DATA FindData;
FindHandle hSearch(FindFirstFileW((path + L"*").c_str(), &FindData));
if (hSearch.get() == INVALID_HANDLE_VALUE)
{
if (GetLastError() != ERROR_FILE_NOT_FOUND)
{
std::wcerr << L"Error looking for first file" << std::endl;
return -1;
}
std::wcout << L"No files found" << std::endl;
}
else
{
do
{
std::wstring filePath = path + FindData.cFileName;
std::wcout << L"Path " << filePath << std::endl;
}
while (FindNextFileW(hSearch.get(), &FindData));
if (GetLastError() != ERROR_NO_MORE_FILES)
{
std::wcerr << L"Error looking for next file" << std::endl;
return -1;
}
}
return 0;
}