使用抛出exeption的代码:**terminate在抛出'std::filesystem::__cxx11::filesystem_error'的示例后调用what():文件系统错误:无法递增递归目录迭代器:无效参数
#include <iostream>
#include <filesystem>
#include <string>
using namespace std;
using namespace std::filesystem;
void explore(const directory_entry& directory,size_t& counter) {
for(const auto& entry : recursive_directory_iterator{ directory.path() }) {
cout<<"\nREC: "<<entry;
counter++;
}
}
int main(int argc,char* argv[]){
if(argc) cout<<"";
if(argc!=3){
cerr<<"Wrong arguments. Usage app \"PATH\" \"three symbols extension\"\n";
return -1;
}
recursive_directory_iterator di{argv[1]},end;
size_t counter{};
explore(directory_entry{argv[1]},counter);
(counter)? cout<<"\nTotal files in "<<argv[1]<<"with extension *"<<argv[2]<<" is "<<counter<<"\n": cout<<"\nFiles with extension "<<argv[2]<<" not found\n";
}
不抛出exeption的代码:
#include <filesystem>
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
using namespace std::filesystem;
struct Attributes {
size_t size_bytes;
size_t n_directories;
size_t n_files;
};
void print_line(const Attributes& attributes, string_view path) {
cout << setw(12) << attributes.size_bytes << setw(6) << attributes.n_files << setw(6) << attributes.n_directories
<< " " << path << "\n";
}
Attributes explore(const directory_entry& directory) {
Attributes attributes{};
for(const auto& entry : recursive_directory_iterator{ directory.path() }) {
cout<<"\nREC: "<<entry;
}
return attributes;
}
int main(int argc, const char** argv) {
if(argc < 2) {
cerr << "Usage: treedir PATH";
return -1;
}
path sys_path{};
std::string args{};
if(argv[1][0]=='-'){
args=argv[1];
sys_path=argv[2];
}
else{
sys_path=argv[1];
}
bool recursive{};
for(auto& val:args){
if(val=='R') recursive=1;
}
cout << "Size Files Dirs Name\n";
cout << "------------ ----- ----- ------------\n";
Attributes root_attributes{};
for(const auto& entry : directory_iterator{ sys_path }) {
try {
if(entry.is_directory()) {
if(recursive){
const auto attributes = explore(entry);
print_line(attributes, entry.path().string());
}
root_attributes.n_directories++;
} else {
root_attributes.n_files++;
error_code ec;
root_attributes.size_bytes += entry.file_size(ec);
if(ec)
cerr << "Error reading file size: " << entry.path().string() << endl;
}
} catch(const exception&) {
}
}
print_line(root_attributes, sys_path.string());
}
在第一种情况下,当我从“C:”开始遍历时,我得到了exeption,但是当我使用D:\遍历时,我得到了exeption。在第二种情况下,遍历对于C:\和D:都是可以的。
通过skip_permission_denied应用std::filesystem::directory_options没有帮助。
有什么想法吗
2条答案
按热度按时间g52tjvyc1#
在第二个代码片段中,您通过
try {} catch
屏蔽了常规类型上的异常,而不采取任何操作。尝试(对不起)此版本的函数:
你会看到发生什么事的。在我的情况下
程序遇到一个非空的回收站,并拒绝尝试戳它。:P
对于第二种情况,我使用了一个函数,它将在进一步传播异常之前打印诊断消息。注意,使用异常作为控制流可能不是一个好主意。在可能的情况下,最好使用函数返回值。
并且可以自由添加垃圾邮件控制标志:
调用explore():
6tr1vspr2#
将你的两个版本简化为基本内容,你正在比较这个:
与
在第一种情况下,当
might_throw
抛出异常时,异常会在调用堆栈中向上移动,因为在任何地方捕捉到异常,程序都会终止。当在第一个迭代中抛出异常时,其他迭代将不会执行。在第二个例子中,当
might_throw
抛出一个异常时,这个异常会被try-catch
捕获。不对异常执行任何操作,然后执行下一个迭代。当在第一次迭代中抛出异常时,其他迭代仍然会执行。你可以用eg
std::cout << e.what() << "\n";
替换//do nothing
,以在出现异常时产生一些输出。很可能您会在代码的两个变体中看到相同的异常被抛出(除了第一个变体在第一个变体之后终止)。