#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <limits.h>
#include <list>
#include <math.h>
#include <vector>
#include <iostream>
using namespace std;
enum ElementType { NONE,SIMPLEFILE, DIRECTORY, SYMBOLICLINK };
class Element{
public:
Element():exists(false){
name=std::string("");
full_path_name=std::string("");;
element_type=NONE;
element_size=0;
exists=false;
};
std::string name;
std::string full_path_name;
ElementType element_type;
long element_size;
bool exists;
};
int inspect( std::list<Element>& result_element_array, long *dir_size,std::string full_path ) {
std::list<Element> result_element_array_temp;
result_element_array.clear();
DIR *d;
struct dirent *dir;
struct stat buf;
std::string mynamebuf;
long dir_size_temp=0;
std::string full_path_temp;
std::string full_path_dummy;
d = opendir( full_path.c_str());
if( d == NULL ) {
return 1;
}
while( ( dir = readdir( d ) )) {
if( strcmp( dir->d_name, "." ) == 0 ||
strcmp( dir->d_name, ".." ) == 0 ) {
continue;
}
mynamebuf=full_path;
mynamebuf+=std::string(full_path.at(full_path.size() - 1) == '/' ? "" : "/");
mynamebuf+=std::string(dir->d_name);
if (stat(mynamebuf.c_str(), &buf) != 0) {
perror(mynamebuf.c_str());
continue;
}
if( S_ISDIR(buf.st_mode) ) {//if dir
chdir( dir->d_name );
full_path_temp=full_path;
full_path_temp+=std::string("/");
full_path_temp+=std::string(dir->d_name);
(dir_size_temp)=0;
inspect(result_element_array_temp, &dir_size_temp, full_path_temp );
chdir( ".." );
full_path_dummy=full_path_temp;
Element element;
element.name=dir->d_name;
element.full_path_name=full_path_dummy;
element.element_type=DIRECTORY;
element.element_size=dir_size_temp;
element.exists=true;
result_element_array.push_back(element);
result_element_array.insert( result_element_array.end(), result_element_array_temp.begin(), result_element_array_temp.end() );
(*dir_size)+=(dir_size_temp);
}else if( S_ISREG(buf.st_mode)) {//if file
full_path_dummy=full_path;
full_path_dummy+=std::string("/");
full_path_dummy+=std::string(dir->d_name);
Element element;
element.name=dir->d_name;
element.full_path_name=full_path_dummy;
element.element_type=SIMPLEFILE;
element.element_size=buf.st_size;
element.exists=true;
result_element_array.push_back(element);
(*dir_size)+=buf.st_size;
} else if( S_ISLNK(buf.st_mode) ) {//if link
full_path_dummy=full_path;
full_path_dummy+=std::string("/");
full_path_dummy+=std::string(dir->d_name);
Element element;
element.name=dir->d_name;
element.full_path_name=full_path_dummy;
element.element_type=SYMBOLICLINK;
element.element_size=0;
element.exists=true;
result_element_array.push_back(element);
} else {
continue;
}
}
closedir(d);
return 0;
}
int prime(int n) {
int i=0;
double sqrt_n = sqrt(static_cast<double>(n));
for (i = 2; i <= sqrt_n; i++) {
if (n % i == 0)
return false;
}
return true;
}
int stringIntValue(std::string key){
int code=0;
for(int i=key.size()-1;i>=0;i--){
code+=key.at(i)*i;
}
return code;
}
int findmforhash(int sizeoflist){
int m=sizeoflist;
if(m % 2 !=1){ m++;}
while(m<sizeoflist*2 && !prime(m)){
m+=2;
}
return m;
}
int hash_func(int keyIntValue, int m, int i){
int code=((keyIntValue % m)+(i*(keyIntValue%(m-2)))%m);
return code;
}
void locatetohashtable(std::list<Element> elist,int m,std::vector<Element>& table, std::list<std::string>& keylist ){
std::vector <Element>::iterator It2=table.begin();
int i=0;
int k=0;
std::list <Element>::iterator It;
for(It = elist.begin(); It != elist.end(); ++It){
int code=hash_func(stringIntValue((*It).name),m,i);
while((*(It2 + code)).exists){
i++;
}
table.insert((It2+code), (*It));
keylist.push_back((*It).name);
k++;
}
}
void usage(void)
{
printf("Usage:\n");
printf("./traversedir -d <directory_to_explore>\n");
exit (8);
}
void searchtable(std::string searchparam,std::vector<Element> table, std::list<std::string> keylist, int m ){
std::list <string>::iterator Itkey;
int code=0;
for(Itkey = keylist.begin(); Itkey != keylist.end(); ++Itkey){
if((*Itkey).find(searchparam)!=-1){
int j=0;
do{
code=hash_func(stringIntValue(*Itkey),m,j);
j++;
}while((*(table.begin()+code)).name.compare(*Itkey)!=0);
printf("%s",(*(table.begin()+code)).full_path_name.c_str());
printf("%ld",(*(table.begin()+code)).element_size);
printf("%d",(*(table.begin()+code)).element_type);
}
}
}
int main(int argc, char *argv[]){
if ((argc > 1) && (argv[1][0] == '-'))
{
switch (argv[1][1])
{
case 'd':
printf("\n");
if(argc>=3){
std::vector<Element> table;
std::list<std::string> keylist;
std::list<Element> result_element_array;
int m;
long dir_size=0;
inspect( result_element_array, &dir_size,std::string(argv[2]) );
m=findmforhash(result_element_array.size());
table.reserve(m);
std::vector <Element>::iterator It;
for(It = table.begin(); It != table.end(); ++It){
Element element;
element.exists=false;
table.insert(It, element);
}
locatetohashtable(result_element_array, m, table, keylist );
std::string searchparam;
printf("Please enter a file name:");
std::cin >> searchparam ;
searchtable(searchparam,table, keylist, m );
}
case 'h':
usage();
break;
default:
printf("Wrong Argument: %s\n", argv[1]);
usage();
}
}else {
usage();
}
return 0;
}
抱歉粘贴了整个代码,我在主线上遇到了段错误
for(It = table.begin(); It != table.end(); ++It){
你能有个主意吗?您还可以建议在 linux、ubuntu 上的 gdb 旁边的调试工具吗?特别是看到内存损坏?
提前致谢。
编辑
感谢 Naveen,我编辑了代码并且该部分工作正常更改为不在循环内使用向量,您迭代该向量:
在主函数中;
table.resize(m);
for(int y=0;y<m;y++){
Element element;
element.exists=false;
table.push_back(element);
}
将某物放在向量处的特定索引上