我很难理解为什么它不能按DirObj的时间/大小对 vector 进行排序....我正在努力的代码的相关部分在下面,但我也将完整的代码放在了上面在该项目下面(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) );
}

遍历
/* 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;
}

最佳答案

您应该交换两个函数的名称byTime和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) );
}

关于c++ - std::sort使用函数作为比较器,不起作用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9796361/

10-09 06:49