我无法理解为什么它没有按照DirObj的时间/大小对矢量进行排序....我正在努力解决的代码的相关部分就在下面,但我也把这个项目的完整代码(3个文件)放在那个下面。
编辑:我应该澄清一下,它似乎确实会移动,但最终结果不是有序或反向排序的,而且似乎与我试图排序的属性无关。
相关部分:
sortBy() {
std::sort(v.begin(), v.end(), byTime);
std::cout << "Sorted by time:" << std::endl;
for (it = v.begin(); it != v.end(); ++it) {
std::cout << **it;
}
std::sort(v.begin(), v.end(), bySize);
std::cout << "Sorted by size:" << std::endl;
for (it = v.begin(); it != v.end(); ++it) {
std::cout << **it;
delete *it;
}
}
bool byTime(DirObj * x, DirObj * y) {
return ( ((x->getStat()).st_size) < ((y->getStat()).st_size) );
}
bool bySize(DirObj * x, DirObj * y) {
return ( ((x->getStat()).st_atime) < ((y->getStat()).st_atime) );
}
Traversal.cpp
/* A file traversal program for the Unix filesystem. */
/* Allows the user to select one of the following options:
depth-first-order (stack)
breadth-first-order (queue)
Sort by size */
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include "DirObj.h"
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
void printUsage();
void breadthFirst(const std::string);
void depthFirstR(const std::string);
void depthFirstNR(const std::string);
void sortBy(const std::string);
bool byTime(DirObj *, DirObj *);
bool bySize(DirObj *, DirObj *);
int main(int argc, char **argv) {
std::string buffer;
int cnt;
/* input validation, check for too few arguments */
if (argc < 3) {
printUsage();
return 1;
}
/* get directory pathname */
buffer = argv[2];
buffer.append("/");
/* check for options */
if (strcmp(argv[1], "-a") == 0) {
breadthFirst(buffer);
std::cout << std::endl << "Recursive depth-first traversal of " << buffer << ":" << std::endl;
depthFirstR(buffer);
depthFirstNR(buffer);
sortBy(buffer);
}
else if (strcmp(argv[1], "-b") == 0) {
breadthFirst(buffer);
}
else if (strcmp(argv[1], "-d") == 0) {
std::cout << std::endl << "Recursive depth-first traversal of " << buffer << ":" << std::endl;
depthFirstR(buffer);
depthFirstNR(buffer);
}
else if (strcmp(argv[1], "-s") == 0) {
sortBy(buffer);
}
else {
printUsage();
return 1;
}
std::cout << std::endl << "DONE. All requested traversals were successful." << std::endl;
return 0;
}
void printUsage() {
printf("Usage: ./dirTraverse <mode> <directory pathname>\n");
printf(" Modes:\n");
printf(" -a All traversals\n");
printf(" -b Breadth-first\n");
printf(" -d Depth-first\n");
printf(" -s Sort by size\n");
printf(" -t Sort by time\n");
return;
}
/* uses a queue */
void breadthFirst(const std::string b) {
std::cout << std::endl << "Breadth-first traversal of " << b << ":" << std::endl;
struct dirent *d;
DIR *dir;
struct stat stat_b;
std::string buffer;
buffer = b;
std::queue<DirObj *> q;
DirObj * o;
/* open the initial directory */
dir = opendir(buffer.c_str());
if (!dir) {
std::cout << "Could not open " << buffer << "." << std::endl;
}
else {
/* push all directory entries onto queue */
while ((d = readdir(dir))) {
q.push(new DirObj(d, buffer));
}
// closedir(dir);
}
/* dequeue each directory entry and print */
while (!q.empty()) {
o = q.front();
q.pop();
std::cout << *o;
d = o->getEntry();
stat_b = o->getStat();
/* if the entry is a directory (but not . or ..) */
if (S_ISDIR(stat_b.st_mode) && (strcmp(d->d_name, "..") != 0) && (strcmp(d->d_name, ".") != 0)) {
buffer = o->getPath();
buffer.append(d->d_name);
/* open directory */
dir = opendir(buffer.c_str());
if (!dir) {
std::cout << "Could not open " << buffer << "." << std::endl;
}
else {
/* push all directory entries onto queue */
buffer.append("/");
while ((d = readdir(dir))) {
q.push(new DirObj(d, buffer));
}
// closedir(dir);
}
}
delete o;
}
}
/* recursive, works, very basic */
void depthFirstR(const std::string b) {
struct dirent *d;
DIR *dir;
struct stat stat_b;
std::string buffer = b;
int l = buffer.length();
/* open initial directory */
dir = opendir(buffer.c_str());
if (!dir) {
std::cout << "Could not open " << buffer << "." << std::endl;
}
else {
/* while there are directory entries, read the next one and print it */
while ((d = readdir(dir))) {
buffer.append(d->d_name);
stat(buffer.c_str(), &stat_b);
std::cout << buffer << " : {inode=" << d->d_ino << ", size=" << stat_b.st_size << ", time=" << stat_b.st_atime << "}" << std::endl;
/* if the directory entry is a directory, recursively traverse it */
if (S_ISDIR(stat_b.st_mode) && (strcmp(d->d_name, "..") != 0) && (strcmp(d->d_name, ".") != 0)) {
buffer.append("/");
depthFirstR(buffer);
}
buffer = buffer.substr(0, l);
}
// closedir(dir);
}
}
/* non-recursive, uses an explicit stack of DirObj to keep track of paths associated with dirents */
void depthFirstNR(const std::string b) {
std::cout << std::endl << "Non-recursive depth-first traversal of " << b << ":" << std::endl;
struct dirent *d;
DIR *dir;
struct stat stat_b;
std::string buffer = b;
DirObj *o;
std::stack<DirObj *> s;
/* open the initial directory */
dir = opendir(buffer.c_str());
if (!dir) {
std::cout << "Could not open " << buffer << "." << std::endl;
}
else {
/* push all directory entries onto stack */
while ((d = readdir(dir))) {
s.push(new DirObj(d, buffer));
}
// closedir(dir);
}
/* pop each directory entry off stack and print */
while (!s.empty()) {
o = s.top();
s.pop();
std::cout << *o;
d = o->getEntry();
stat_b = o->getStat();
/* if the entry is a directory (but not . or ..) */
if (S_ISDIR(stat_b.st_mode) && (strcmp(d->d_name, "..") != 0) && (strcmp(d->d_name, ".") != 0)) {
/* open directory */
buffer = o->getPath();
buffer.append(d->d_name);
dir = opendir(buffer.c_str());
if (!dir) {
std::cout << "Could not open " << buffer << "." << std::endl;
}
else {
/* push all directory entries onto stack */
buffer.append("/");
while ((d = readdir(dir))) {
s.push(new DirObj(d, buffer));
}
// closedir(dir);
}
}
delete o;
}
}
void sortBy(const std::string b) {
std::cout << std::endl << "Sorted by size/time traversal of " << b << ":" << std::endl;
struct dirent *d;
DIR *dir;
struct stat stat_b;
std::string buffer = b;
DirObj * o;
std::stack<DirObj *> s;
std::vector<DirObj *> v;
/* open the initial directory */
dir = opendir(buffer.c_str());
if (!dir) {
std::cout << "Could not open " << buffer << "." << std::endl;
}
else {
/* push all directory entries onto stack */
while ((d = readdir(dir))) {
s.push(new DirObj(d, buffer));
}
// closedir(dir);
}
/* pop each directory entry off stack and print */
while (!s.empty()) {
o = s.top();
s.pop();
v.push_back(o);
d = o->getEntry();
stat_b = o->getStat();
/* if the entry is a directory (but not . or ..) */
if (S_ISDIR(stat_b.st_mode) && (strcmp(d->d_name, "..") != 0) && (strcmp(d->d_name, ".") != 0)) {
/* open directory */
buffer = o->getPath();
buffer.append(d->d_name);
dir = opendir(buffer.c_str());
if (!dir) {
std::cout << "Could not open " << buffer << "." << std::endl;
}
else {
/* push all directory entries onto stack */
buffer.append("/");
while ((d = readdir(dir))) {
s.push(new DirObj(d, buffer));
}
// closedir(dir);
}
}
}
std::vector<DirObj *>::iterator it;
std::sort(v.begin(), v.end(), byTime);
std::cout << "Sorted by time:" << std::endl;
for (it = v.begin(); it != v.end(); ++it) {
std::cout << **it;
}
std::sort(v.begin(), v.end(), bySize);
std::cout << "Sorted by size:" << std::endl;
for (it = v.begin(); it != v.end(); ++it) {
std::cout << **it;
delete *it;
}
}
bool byTime(DirObj * x, DirObj * y) {
return ( ((x->getStat()).st_size) < ((y->getStat()).st_size) );
}
bool bySize(DirObj * x, DirObj * y) {
return ( ((x->getStat()).st_atime) < ((y->getStat()).st_atime) );
}
DirObj.h
#include <string>
#include <iostream>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
class DirObj {
friend std::ostream& operator<< (std::ostream &out, DirObj &obj);
private:
dirent * entry;
std::string path;
struct stat stat_b;
public:
DirObj(dirent * e, const std::string p);
DirObj();
~DirObj();
DirObj(const DirObj &rhs);
DirObj& operator=(const DirObj &rhs);
std::string getPath() const;
dirent * getEntry() const;
struct stat getStat() const;
};
DirObj.cpp
#include "DirObj.h"
DirObj::DirObj(dirent * e = 0, const std::string p = "\0") {
entry = e;
path = p;
std::string buffer = path;
buffer.append(entry->d_name);
stat(buffer.c_str(), &stat_b);
}
DirObj::DirObj() {
entry = 0;
path = "\0";
}
DirObj::~DirObj() {
}
DirObj::DirObj(const DirObj &rhs) {
this->entry = rhs.entry;
this->path = rhs.path;
this->stat_b = rhs.stat_b;
}
DirObj& DirObj::operator=(const DirObj &rhs) {
this->entry = rhs.entry;
this->path = rhs.path;
this->stat_b = rhs.stat_b;
return *this;
}
std::string DirObj::getPath() const {
return path;
}
dirent * DirObj::getEntry() const {
return entry;
}
struct stat DirObj::getStat() const {
return stat_b;
}
std::ostream& operator<< (std::ostream &out, DirObj &obj) {
out << obj.path << (obj.entry)->d_name << ": {inode=" << (obj.entry)->d_ino << ", size=" << (obj.stat_b).st_size << ", time=" << (obj.stat_b).st_atime << "}" << std::endl;
return out;
}
答案 0 :(得分:1)
您应该按时间和bySize交换两个函数的名称(混合属性以进行排序)。修正版:
bool byTime(DirObj * x, DirObj * y) {
return ( ((x->getStat()).st_atime) < ((y->getStat()).st_atime) );
}
bool bySize(DirObj * x, DirObj * y) {
return ( ((x->getStat()).st_size) < ((y->getStat()).st_size) );
}