当前位置:学习生活->会员解答 ->根据windows api核心编程,自己练习循环文件夹和文件,程序一两秒后程序就奔溃了

原创版权标志根据windows api核心编程,自己练习循环文件夹和文件,程序一两秒后程序就奔溃了

作者:sunset920  发表时间:2017/12/14 14:34:13  阅读:
[摘要] C++技术网已经用心解答了用户提出的问题【根据windows api核心编程,自己练习循环文件夹和文件,程序一两秒后程序就奔溃了】,如还有问题,请继续在文章底部留言交流,直到完全懂了为止。
使用支付宝扫码领红包,余额宝付款才可以使用红包哦!不要忘记哈。每天扫一次,天天赚红包!!可以将二维码保存到手机,每天直接扫码领红包啦!!
#include "StdAfx.h"
#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;
}
     再次对耽误一些时间说声抱歉。感谢支持。

微信扫码关注公众号CPP技术网,微信号cpp_coder,关注我们的公众号,阅读更多精彩内容!每天还可以领取大红包哦!!!每天还可以领取大红包哦!!!每天还可以领取大红包哦!!!
文章来源:C++技术网原创文章版权为网站和作者共同所有,会员文章禁止转载。非会员文章转载做好本文超链接即表示授权转载。通过文章下面的分享按钮可以自由分享所有文章。

返回顶部

在线提问
问题标题:
问题描述:(简陋的描述会导致问题被最后回答、没有针对性回答甚至无法解答。请确保问题描述的足够清楚。)