#include <windows.h>
#include <iostream.h>
#include <string.h>
void getAllFiles(char *dir){
char cFullPath[100];
WIN32_FIND_DATA data;
HANDLE hFind;
strcat(strcpy(cFullPath,dir),"*.*");
hFind=FindFirstFile(cFullPath,&data);
do
{
char cNewDir[100];
if((!strcmp(".",data.cFileName)) || (!strcmp("..",data.cFileName)))
{
continue;
}
if(data.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)
{
strcpy(cNewDir,dir);
strcat(cNewDir,data.cFileName);
strcat(cNewDir,"\\\\");
getAllFiles(cNewDir);//递归
}else{
strcpy(cNewDir,dir);
strcat(cNewDir,data.cFileName);
}
cout << cNewDir << endl;
}while(FindNextFile(hFind,&data));
FindClose(hFind);
}
int main(int argc, char* argv[])
{
int DSLength = GetLogicalDriveStrings(0,NULL);
char* DStr = new char[DSLength];
GetLogicalDriveStrings(DSLength,(LPTSTR)DStr);
int DType;
int si=0;
BOOL fResult;
for(int i=0;i<DSLength/4;++i)
{
DType = GetDriveType(DStr+i*4);
if(DType != DRIVE_FIXED)
{
continue;
}
char dir[100]={DStr[si],'''':'''',''''\0''''};
fResult = GetDiskFreeSpaceEx(dir,NULL,NULL,NULL);
if(!fResult)
{
continue;
}
strcat(dir,"\\\\");
getAllFiles(dir);
si+=4;
}
return 0;
}
C++技术网会员解答:
您好,感谢您对C++技术网的支持与信任。
首先说声抱歉,有一点耽误了。现在开始为您解答问题。
程序运行的效果如下:
代码存在几个问题。
1.文件名长度问题
Windows 通常限定文件名最多包含 260 个字符。但实际的文件名必须少于这一数值,因为完整路径(如 C:\Program Files\filename.txt)都包含在此字符数值中。
而你代码中的数组长度也就100字节。当遍历的深度比较深的时候,或者一些临时文件的文件名都很长,然后拼起来,都会超过100个字节。这样就会出现大量的字节写入一个指定的内存,然后超出的部分写入到其他内存中,而这些内存不是你程序的空间,所以就被系统阻止了。这样就是产生的内存越界错误。
问题的根本原因就是给的数组大小不够。在两个变量中都存在长度不够的问题。对于单个文件名是不超过260字符,然后你之类是进行完整路径的拼接,那长度就会更长,所以尽可能大一点。
2.递归的变量使用问题
在遍历文件夹时,采用了递归。而在递归函数调用的时候,都会传入一个数组。而数组是临时的变量,当递归进入到另外一层的时候,代码会对上一层的数组进行内存操作,这个有违背递归的思想。递归的每一层最好只依赖本层的参数,而不要依赖上一层的参数。所以,当数组存在最上一层,然后进行内存操作,很容易出现内存使用不当的问题。解决的办法是使用string对象。每一层只依赖和存储本层的内容。当然这个是建议。
在大量递归的时候,最好少使用局部的数据。这些局部的变量都会压栈存放,放多了,就容易出现栈溢出,然后爆炸了。而我们通过参数传递变量,会比较好。或者需要积累的数据,可以采用全局变量。
3.代码优化问题
在字符串操作的时候,可以采用string类,可以实现字符串的=赋值和+=字符串拼接,都非常方便。而且,代码中写的字符串操作函数,在VS2017是不推荐的。C++的头文件一般是iostream,而不是写iostream.h。当然,这个跟VS版本有关,推荐使用最新的VS2017。
下面是参考代码:
再次对耽误一些时间说声抱歉。感谢支持。
#include "StdAfx.h"
#include <windows.h>
#include <iostream>
#include <string.h>
using namespace std;
void getAllFiles(const char *dir) {
//char cFullPath[100];
string cFullPath;
WIN32_FIND_DATA data;
HANDLE hFind;
cFullPath = dir;
cFullPath += "*.*";
//strcat(strcpy(cFullPath, dir), "*.*");
hFind = FindFirstFile(cFullPath.c_str(), &data);
do
{
char cNewDir[1024] = {0};
//string cNewDir;
if ((!strcmp(".", data.cFileName)) || (!strcmp("..", data.cFileName)))
{
continue;
}
if (data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
{
//cNewDir = dir;
//cNewDir += data.cFileName;
//cNewDir += "\\\\";
//getAllFiles(cNewDir.c_str());//递归
strcpy(cNewDir, dir);
strcat(cNewDir, data.cFileName);
strcat(cNewDir, "\\\\");
getAllFiles(cNewDir);//递归
}
else {
//cNewDir = dir;
//cNewDir += data.cFileName;
strcpy(cNewDir, dir);
strcat(cNewDir, data.cFileName);
}
cout << cNewDir << endl;
} while (FindNextFile(hFind, &data));
FindClose(hFind);
}
int main(int argc, char* argv[])
{
int DSLength = GetLogicalDriveStrings(0, NULL);
char* DStr = new char[DSLength];
GetLogicalDriveStrings(DSLength, (LPTSTR)DStr);
int DType;
int si = 0;
BOOL fResult;
for (int i = 0; i<DSLength / 4; ++i)
{
DType = GetDriveType(DStr + i * 4);
if (DType != DRIVE_FIXED)
{
continue;
}
char dir[100] = { DStr[si],'''':'''',''''\0'''' };
fResult = GetDiskFreeSpaceEx(dir, NULL, NULL, NULL);
if (!fResult)
{
continue;
}
strcat(dir, "\\\\");
getAllFiles(dir);
si += 4;
}
return 0;
}