搜索
有爱,有技术,有你^_^)y
╱人◕‿‿◕人╲订下契约(注册新用户)

合作站点账号登陆

QQ登录

只需一步,快速开始

快捷导航
查看: 317|回复: 14
收起左侧

求助,关于遍历指定目录中的所有文件和子目录

[复制链接]

该用户从未签到

6

主题

8

好友

2018

积分

Continue

积分
2018
发表于 2015-8-27 20:29:45 | 显示全部楼层 |阅读模式

╱人◕‿‿◕人╲定下契约

您需要 登录 才可以下载或查看,没有账号?╱人◕‿‿◕人╲订下契约(注册新用户)

x
废话不多说先上程序:
#include <stdio.h>
#include <tchar.h>
#include<io.h>
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
int ayu = 0;
int change_path(string path, stringnew_path){
        int i = path.length();
        new_path = "\\" + new_path + "*.*";
        path.replace(i - 2, i, new_path);
        return 0;
}
int find_file( string a )
{
        string s1,s2;
        long Handle;
        s1.replace(NULL, NULL, a);
        struct _finddata_t FileInfo;
        cout << ayu << "\t" << endl;
        if ((Handle = _findfirst(a.c_str(), &FileInfo)) == -1L){
                  if (_A_SUBDIR & FileInfo.attrib){
                           if ((strcmp(FileInfo.name, ".") != 0) &&(strcmp(FileInfo.name, "..") != 0)){
                                              printf("%s\n", FileInfo.name);
                                              s2.replace(NULL, NULL, FileInfo.name);
                                            change_path(s1, s2);
                                              ayu = ayu + 1;
                                              find_file(s1);
                                    }
                  }
        }
        else{
                  printf("%s\n", FileInfo.name);
                  while (_findnext(Handle, &FileInfo) == 0){
                           if (_A_SUBDIR & FileInfo.attrib){
                                    if ((strcmp(FileInfo.name, ".") != 0) &&(strcmp(FileInfo.name, "..") != 0)){
                                              printf("%s\n", FileInfo.name);
                                              s2.replace(NULL, NULL, FileInfo.name);
                                              change_path(s1, s2);
                                              ayu = ayu + 1;
                                              find_file(s1);
                                    }
                           }
                           printf("%s\n", FileInfo.name);
                  }
                  _findclose(Handle);
        }
        ayu -= 1;
        system("pause");
        return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
        string s;
        cout << "please inupt path:";
        cin >> s;
        find_file(s);
        return 0;

}
主要思路就是通过对find_file()的递归调用来达到遍历目录的目的(ayu变量是在检错的时候加上去的)
但是实际运行的时候出来这样的错误

运行结果

运行结果

变量ayu显示程序在这两个文件上重复了上千次。
然而想了好久实在不知道是哪里错了orz

签名被小宅喵吞掉了~~~~(>_<)~~~~
回复

使用道具 举报

该用户从未签到

6

主题

8

好友

2018

积分

Continue

积分
2018
 楼主| 发表于 2015-8-27 20:31:12 | 显示全部楼层
那个,文件的标题是当初打错了后面也就懒得改了,不要在意
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

2

主题

11

好友

1431

积分

Continue

积分
1431
发表于 2015-8-28 14:30:47 | 显示全部楼层
为何不用 Win API
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

58

好友

2万

积分

第一章

积分
20519
发表于 2015-8-28 20:08:27 | 显示全部楼层
你这个代码里有很多问题,比如 change_path 来改变下一个遍历的路径,但没有用引用传参,也就是说,你调用了 change_path 之后, s1 里面的值根本没变化(楼主可以自己写段小代码测试下),建议改为如下:
[mw_shl_code=cpp,true]int change_path(string & path, string new_path)[/mw_shl_code]
另外,在 change_path 里面,你想用 s2 的目录名加在 s1 后面,只加上了前面的斜杠,却没有“*.*”与 s2 之间的分隔,建议改为如下:
[mw_shl_code=cpp,true]new_path = "\\" + new_path + "\\*.*";[/mw_shl_code]
如果你要加上这个子目录名字,没必要调用 replace 还要计算 s1 的长度,直接用“+”连接两个string对象就行了:
[mw_shl_code=cpp,true]path += new_path;[/mw_shl_code]

另外,在你的 find_file 函数里,也有很明显的问题,你的 if 居然是在 _findfirst 返回 -1L 的时候(也就是找不到任何匹配项)去执行 if 里面的语句、进入子目录。
如果你给 _findfirst 传入的第一个参数是一个目录名,例如“C:\\XX\\YY”,只要这目录存在就能被 _findfirst 正常打开,而且它在FileInfo的name里写入的字符串会是“YY”,而不是“YY”下面的目录或文件名,更不会返回 -1L, 你的代码却还要在返回 -1L 的情况下进去挖掘子目录,这个问题是很明显的。

评分

参与人数 1宅币 +50 贡献 +10 收起 理由
原味板烧鸡腿堡 + 50 + 10 全蛋哥好

查看全部评分

签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

6

主题

8

好友

2018

积分

Continue

积分
2018
 楼主| 发表于 2015-8-28 21:43:17 | 显示全部楼层

初学还没接触过win api
如果用win api 的话该怎么写?
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

58

好友

2万

积分

第一章

积分
20519
发表于 2015-8-28 22:29:46 | 显示全部楼层
樱花流逝 发表于 2015-8-28 21:43
初学还没接触过win api
如果用win api 的话该怎么写?

没有必要,因为一部分标准库函数在底层实现就是调用了系统的API。
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

58

好友

2万

积分

第一章

积分
20519
发表于 2015-8-28 22:32:54 | 显示全部楼层
樱花流逝 发表于 2015-8-28 21:43
初学还没接触过win api
如果用win api 的话该怎么写?

今晚我要是有空再来帮你改改代码吧。
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

6

主题

8

好友

2018

积分

Continue

积分
2018
 楼主| 发表于 2015-8-29 11:11:52 | 显示全部楼层
张全蛋 发表于 2015-8-28 20:08
你这个代码里有很多问题,比如 change_path 来改变下一个遍历的路径,但没有用引用传参,也就是说,你调用 ...

嗯多谢了。
我把change_path()改成了这样
int change_path(string & path, string new_path){
        int i = path.length();
        new_path = new_path + "\\*.*";
        path.replace(i - 3, i, new_path);
        return 0;
}
假设path="d:\xx\*.*";    new_path="yy";
如果写成new_path = "\\" + new_path + "\\*.*";的话就要把path.replace(i - 3, i, new_path);中的3改成,(虽然之前把3写成2了。。。)


如果直接这么写的话path += new_path;的到的结果不是会变成d:\xx\*.*yy么?




弱弱的问一句。。。那个代码的字体是怎么弄出来的?
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

6

主题

8

好友

2018

积分

Continue

积分
2018
 楼主| 发表于 2015-8-29 12:05:38 | 显示全部楼层
本帖最后由 樱花流逝 于 2015-8-29 12:57 编辑

看了4楼的建议后自己又改了一下,发现按照之前那样子在那个位置改s1的话,s1的值会一直继承下去导致所有的文件名都连一起。
所以就改成了这个样子:
#include <stdio.h>
#include <tchar.h>
#include<io.h>
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
int ayu = 0;
int change_path(string & path, string new_path){
        int i = path.length();
        new_path = new_path + "\\*.*";
        path.replace(i - 3, i, new_path);
        return 0;
}

int find_file( string a ,string b )
{
        string s1,s2;
        long Handle;
        if (b.compare("sdf.txt") != 0){ change_path(a, b); }
        s1.replace(NULL, NULL, a);
        ayu += 1;
        cout << ayu << "\t" << s1 << "\t" << endl;
        struct _finddata_t FileInfo;
        if ((Handle = _findfirst(a.c_str(), &FileInfo)) == -1L){
                return 0;
        }else{
                printf("123%s\n", FileInfo.name);
                while (_findnext(Handle, &FileInfo) == 0){
                        if (_A_SUBDIR & FileInfo.attrib){
                                if ((strcmp(FileInfo.name, ".") != 0) && (strcmp(FileInfo.name, "..") != 0)){
                                        printf("%s\n", FileInfo.name);
                                        s2.replace(NULL, NULL, FileInfo.name);
                                        find_file(s1, s2);
                                        ayu += -1;
                                }
                        }else{
                                printf("456%s\n", FileInfo.name);}
                }
                _findclose(Handle);
        }

        return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
        string s;
        cout << "please inupt path:";
        cin >> s;
        find_file(s,"sdf.txt");
        system("pause");
        return 0;
}
然而还是错了而且总感觉越来越奇怪了
屏幕截图(22).png
不知为何字符串粘到一起去了==而且粘的方式还无比奇葩
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

58

好友

2万

积分

第一章

积分
20519
发表于 2015-8-29 19:35:30 | 显示全部楼层
樱花流逝 发表于 2015-8-29 12:05
看了4楼的建议后自己又改了一下,发现按照之前那样子在那个位置改s1的话,s1的值会一直继承下去导致所有的 ...

我这边写了个测试代码,也是递归遍历的,要不要先发给你看下?
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

6

主题

8

好友

2018

积分

Continue

积分
2018
 楼主| 发表于 2015-8-29 20:53:48 | 显示全部楼层
本帖最后由 樱花流逝 于 2015-8-29 21:05 编辑
张全蛋 发表于 2015-8-29 19:35
我这边写了个测试代码,也是递归遍历的,要不要先发给你看下?

嗯,发一下吧,谢谢了
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

58

好友

2万

积分

第一章

积分
20519
发表于 2015-8-29 23:17:01 | 显示全部楼层
樱花流逝 发表于 2015-8-29 20:53
嗯,发一下吧,谢谢了

先说一下,我的编译环境是 Dev-cpp + gcc 4.9.2,代码一共分为3个文件。

主体“main.cpp”:
[mw_shl_code=cpp,true]
/* main.cpp */
#include "find_file.h"
#define _TEST_LOCATION "F:\\图片\\*.*"

int main(void)
{
        string  str1 = _TEST_LOCATION;
       
        find_file(str1);
   
        return 0;
}
[/mw_shl_code]

头文件“find_file.h”如下:
[mw_shl_code=cpp,true]
/* find_file.h */
#pragma once
#ifndef FIND_FILE_H_
#define FIND_FILE_H_
#include <string>
//void change_path(string & path, string new_parh);
using std::string;

void find_file(string  path);

#endif
[/mw_shl_code]

头文件的函数实现部分“find_file.cpp”:
[mw_shl_code=cpp,true]
/* find_file.cpp */
#include "find_file.h"
#include <iostream>
#include <string.h>
#include <io.h>

void find_file(string  path)
{
        using std::cout;
        using std::endl;
       
        /* 用复制构造函数,拷贝原始路径字符串 */
        string  originalPath(path);
        string  subPath;
        struct  _finddata_t FileInfo;
        long  FileHandle;

        FileHandle = _findfirst(originalPath.c_str(), &FileInfo);
        if (FileHandle == -1L)
        {
                cout << "Maybe you have input an invalid path!" << endl
                        << "The invalid path is:" << originalPath;
               
                exit(1);
        }
        else
        {
                do
                {
                        /* 如果打开的内容是一个目录 */
                        if (FileInfo.attrib & _A_SUBDIR)
                        {
                                if (strcmp(FileInfo.name, ".") == 0 ||
                                        strcmp(FileInfo.name, "..") == 0)
                                {
                                        continue;
                                }
                                else
                                {
                                        /* 输出当前的文件夹名 */
                                        cout << "The subdir name is: " << FileInfo.name << endl;
                                        /* 准备进入子目录 */
                                        subPath = originalPath.replace(originalPath.find("*"),
                                                                                                         4,
                                                                                                         FileInfo.name) + "\\*.*";
                                        /** 注意,由于调用replace方法之后,会改变originalPath的内容
                                         *  所以这里要恢复到原始的路径内容, 不然递归回来之后,这里的
                                         *  originalPath 会影响到下一个子目录路径的生成而报错
                                         */
                                        originalPath = path;
                                        find_file(subPath);
                                }
                        }
                        else
                        {
                                cout << "The file name is: " << FileInfo.name << endl;
                        }
                /* 遍历当下这个目录下一个文件(夹) */
                } while(_findnext(FileHandle, &FileInfo) == 0);
                _findclose(FileHandle);
        }
}
[/mw_shl_code]
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 1 反对 0

使用道具 举报

该用户从未签到

3

主题

58

好友

2万

积分

第一章

积分
20519
发表于 2015-8-29 23:24:33 | 显示全部楼层
樱花流逝 发表于 2015-8-29 11:11
嗯多谢了。
我把change_path()改成了这样
int change_path(string & path, string new_path){

那个代码字体就在回复的一个按钮上能调出来。

QQ截图20150829232125.jpg
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

58

好友

2万

积分

第一章

积分
20519
发表于 2015-8-29 23:53:23 | 显示全部楼层
樱花流逝 发表于 2015-8-29 20:53
嗯,发一下吧,谢谢了

我看到前面有人说调用系统API的,这里贴一个MSDN的代码示例吧,它就是调用了系统API遍历了一个目录下的全部文件和文件夹,但不包括子目录里面的内容,https://msdn.microsoft.com/en-us/library/windows/desktop/aa365200(v=vs.85).aspx 。
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

6

主题

8

好友

2018

积分

Continue

积分
2018
 楼主| 发表于 2015-8-30 09:14:51 | 显示全部楼层
本帖最后由 樱花流逝 于 2015-8-30 11:51 编辑
张全蛋 发表于 2015-8-29 23:17
先说一下,我的编译环境是 Dev-cpp + gcc 4.9.2,代码一共分为3个文件。

主体“main.cpp”:

看了你的代码后感觉获益匪浅,真的非常感谢。
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

本版积分规则

小黑屋|手机版|技术宅(Z站|基宅) ( 粤ICP备18082987号-1 )

GMT+8, 2025-6-16 20:45 , Processed in 0.141036 second(s), 27 queries , Redis On.

Copyright © 2018 技术宅社区

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表