Reputation: 655
I'm having trouble understanding why this doesn't sort the vector by the time/size of the DirObj....the relevant part of the code I'm struggling with is just below, but I've also put the full code for this project (3 files) below that.
edit: I should probably clarify, it does appear to move things around, but the end result is not ordered or reverse ordered, and seems unrelated to the property I'm trying to sort by.
Relevant part:
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;
}
Upvotes: 2
Views: 589
Reputation: 12920
You should swap the names of the both functions byTime and bySize (you mixed the properties to sort by). Fixed version:
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) );
}
Upvotes: 1