ls的实现及改进ls的实现
参考伪代码实现ls的功能,提交代码的编译,运行结果截图,码云代码链接。
打开目录文件
针对目录文件
读取目录条目
显示文件名
关闭文件目录文件
ls实现代码:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <linux/limits.h> #include <pwd.h> #include <grp.h> #include <time.h> #define PARAM_NONE 0 //无参数 #define PARAM_A 1 //-a #define PARAM_L 2 //-l #define MAXROWLEN 80 //一行最多显示的字符数 int g_leave_len = MAXROWLEN; //一行是剩余长度,用于输出对齐 int g_maxlen; //存放某目录下最长文件名的长度 void my_error(const char* errstring, int line) { fprintf(stderr,"line:%d",line); perror(errstring); exit(1); } //打印单个文件,且没有-l参数 void display_single(char *name) { int i,len; //如果本行不足以打印一个文件名则换行 if(g_leave_len < g_maxlen) { printf("\n"); g_leave_len = MAXROWLEN; } len = strlen(name); len = g_maxlen - len; printf("%-s",name); for(i=0;i<len;i++) { printf(" "); } printf(" "); g_leave_len = g_leave_len - g_maxlen - 2; } /*获取文件属性并打印*/ void display_attribute(struct stat buf, char *name) { char buf_time[32]; struct passwd *psd; struct group *grp; //获取文件类型 if(S_ISLNK(buf.st_mode)) printf("1"); else if(S_ISREG(buf.st_mode)) printf("-"); else if(S_ISDIR(buf.st_mode)) printf("d"); else if(S_ISCHR(buf.st_mode)) printf("c"); else if(S_ISBLK(buf.st_mode)) printf("b"); else if(S_ISFIFO(buf.st_mode)) printf("f"); else if(S_ISSOCK(buf.st_mode)) printf("s"); //获取文件权限 if(buf.st_mode & S_IRUSR) printf("r"); else printf("-"); if(buf.st_mode & S_IWUSR) printf("w"); else printf("-"); if(buf.st_mode & S_IXUSR) printf("x"); else printf("-"); if(buf.st_mode & S_IRGRP) printf("r"); else printf("-"); if(buf.st_mode & S_IWGRP) printf("w"); else printf("-"); if(buf.st_mode & S_IXGRP) printf("x"); else printf("-"); if(buf.st_mode & S_IROTH) printf("r"); else printf("-"); if(buf.st_mode & S_IWOTH) printf("w"); else printf("-"); if(buf.st_mode & S_IXOTH) printf("x"); else printf("-"); printf(" "); //根据uid和gid获取文件所有者的用户名于组名 psd = getpwuid(buf.st_uid); grp = getgrgid(buf.st_gid); printf("%4d",buf.st_nlink); printf("%-8s",psd->pw_name); printf("%-9s",grp->gr_name); printf("%6d",buf.st_size); strcpy(buf_time, ctime(&buf.st_mtime));//将格林位置时间转化成正常时间格式 buf_time[strlen(buf_time) - 1] = 0; printf(" %s",buf_time); } //根据flag参数显示文件内容,调用display_single或者display_attribute void display(int flag,char *pathname) { int i,j; struct stat buf; char name[NAME_MAX + 1]; for(i=0,j=0;i<strlen(pathname);i++) { if(pathname[i] == '/') { j = 0; } else name[j++] = pathname[i]; } name[j] = 0; if(lstat(pathname,&buf) == -1) { my_error("stat",__LINE__); } if(flag == PARAM_NONE) { if(name[0] != '.')//不显示隐藏文件 { display_single(name); } } else if(flag == PARAM_A) { display_single(name); } else if(flag == PARAM_L) { if(name[0] != '.') { display_attribute(buf,name); printf(" %-s\n",name); } } else if(flag == (PARAM_A | PARAM_L)) { display_attribute(buf,name); printf(" %-s\n",name); } } void display_dir(int flag_param,const char *path) { DIR* dir; struct dirent* dirent; char filenames[256][PATH_MAX+1],temp[PATH_MAX+1]; int count = 0;//总共有多少个文件 if((dir = opendir(path)) == NULL) { my_error("opendir",__LINE__); } //获取文件总数和最长文件名 while((dirent = readdir(dir)) != NULL) { if(g_maxlen < strlen(dirent->d_name)) g_maxlen = strlen(dirent->d_name); count++; } closedir(dir); if(count>256) my_error("文件太多超过了256个",__LINE__); int i,j,len = strlen(path); //获取目录下所有的文件名 dir = opendir(path); for(i=0;i<count;i++) { dirent = readdir(dir); if(dirent == NULL) { my_error("readdir",__LINE__); } strncpy(filenames[i],path,len); filenames[i][len] = 0; strcat(filenames[i],dirent->d_name); filenames[i][len+strlen(dirent->d_name)] = 0; } //对文件名进行排序 for(i=0;i<count-1;i++) for(j=i+1;j<count-1;j++) { if(strcmp(filenames[i],filenames[j]) > 0) { strcpy(temp,filenames[j]); strcpy(filenames[j] , filenames[i]); strcpy(filenames[i] , temp); } } for(i=0;i<count;i++) display(flag_param,filenames[i]); closedir(dir); //没有-l的话打印一个换行符 if((flag_param & PARAM_L) == 0) printf("\n"); } int main(int argc, char **argv) { int i,j,k; int num;//记录-的个数 char path[PATH_MAX + 1]; char param[32]; // 保存命令行参数 int flag_param = PARAM_NONE; struct stat buf; j = 0; num = 0; for(i=1;i<argc;i++) { if(argv[i][0] == '-') { for(k=1;k<strlen(argv[i]);k++) { param[j] = argv[i][k]; j++; } num++; } } //现在只支持-a和-l参数 for(i=0;i<j;i++) { if(param[i] == 'a') { flag_param |= PARAM_A; } else if(param[i] == 'l') { flag_param |= PARAM_L; } else { printf("错误的参数:%c\n",param[i]); exit(1); } } param[j] = 0; //如果没有输入文件名或者目录,就显示当前目录 if((num + 1) == argc) { strcpy(path,"./"); path[2] = 0; display_dir(flag_param,path); return 0; } i = 1; for(i=1;i<argc;i++) { if(argv[i][0] != '-') { strcpy(path,argv[i]); if(stat(path,&buf) == -1) my_error("stat",__LINE__); if(S_ISDIR(buf.st_mode)) { //判断目录是否以/结尾 if(path[strlen(argv[i]) - 1] != '/') { path[strlen(argv[i])] = '/'; path[strlen(argv[i] + 1)] = 0; } else path[strlen(argv[i])] = 0; display_dir(flag_param,path); } else { display(flag_param,path); } } } return 0; }
文件可执行建立
测试-l -a
参见附图,改进你的ls的实现。提交代码运行截图和码云链接。
实现代码:
#include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <sys/stat.h> #include <pwd.h> #include <grp.h> #include <unistd.h> #include <string.h> #define LS_NONE 0 #define LS_L 101 #define LS_R 102 #define LS_D 103 #define LS_I 104 #define LS_A 200 #define LS_AL (LS_A+LS_L) #define LS_AI (LS_A+LS_I) // 展示单个文件的详细信息 void show_file_info(char* filename, struct stat* info_p) { char* uid_to_name(), *ctime(), *gid_to_name(), *filemode(); void mode_to_letters(); char modestr[11]; mode_to_letters(info_p->st_mode, modestr); printf("%s", modestr); printf(" %4d", (int) info_p->st_nlink); printf(" %-8s", uid_to_name(info_p->st_uid)); printf(" %-8s", gid_to_name(info_p->st_gid)); printf(" %8ld", (long) info_p->st_size); printf(" %.12s", 4 + ctime(&info_p->st_mtime)); printf(" %s\n", filename); } void mode_to_letters(int mode, char str[]) { strcpy(str, "----------"); if (S_ISDIR(mode)) { str[0] = 'd'; } if (S_ISCHR(mode)) { str[0] = 'c'; } if (S_ISBLK(mode)) { str[0] = 'b'; } if ((mode & S_IRUSR)) { str[1] = 'r'; } if ((mode & S_IWUSR)) { str[2] = 'w'; } if ((mode & S_IXUSR)) { str[3] = 'x'; } if ((mode & S_IRGRP)) { str[4] = 'r'; } if ((mode & S_IWGRP)) { str[5] = 'w'; } if ((mode & S_IXGRP)) { str[6] = 'x'; } if ((mode & S_IROTH)) { str[7] = 'r'; } if ((mode & S_IWOTH)) { str[8] = 'w'; } if ((mode & S_IXOTH)) { str[9] = 'x'; } } char* uid_to_name(uid_t uid) { struct passwd* getpwuid(),* pw_ptr; static char numstr[10]; if((pw_ptr = getpwuid(uid)) == NULL) { sprintf(numstr,"%d",uid); return numstr; } else { return pw_ptr->pw_name; } } char* gid_to_name(gid_t gid) { struct group* getgrgid(),* grp_ptr; static char numstr[10]; if(( grp_ptr = getgrgid(gid)) == NULL) { sprintf(numstr,"%d",gid); return numstr; } else { return grp_ptr->gr_name; } } void do_ls(char dirname[],int mode) { DIR* dir_ptr; struct dirent* direntp; if ((dir_ptr = opendir(dirname)) == NULL) { fprintf(stderr, "ls2: cannot open %s \n", dirname); } else { if(mode==LS_D) { printf("%s\n", dirname); } else { char dirs[20][100]; int dir_count = 0; while ((direntp = readdir(dir_ptr)) != NULL) { if(mode < 200 && direntp->d_name[0]=='.') { continue; } char complete_d_name[200]; // 文件的完整路径 strcpy (complete_d_name,dirname); strcat (complete_d_name,"/"); strcat (complete_d_name,direntp->d_name); struct stat info; if (stat(complete_d_name, &info) == -1) { perror(complete_d_name); } else { if(mode == LS_L||mode == LS_AL) { show_file_info(direntp->d_name, &info); } else if(mode == LS_A||mode == LS_NONE||mode == LS_I||mode == LS_AI) { if(mode == LS_I||mode == LS_AI) { printf("%llu ", direntp->d_ino); } printf("%s\n", direntp->d_name); } else if(mode == LS_R) { if(S_ISDIR(info.st_mode)) { printf("%s\n", direntp->d_name); strcpy (dirs[dir_count],complete_d_name); dir_count++; } else { printf("%s\n", direntp->d_name); } } } } if(mode == LS_R) { int i=0; printf("\n"); for(;i<dir_count;i++){ printf("%s:\n", dirs[i]); do_ls(dirs[i],LS_R); printf("\n"); } } } closedir(dir_ptr); } } // 解析一个单词参数,如-l,-i int analyzeParam(char* input){ if(strlen(input)==2) { if(input[1]=='l') return LS_L; if(input[1]=='a') return LS_A; if(input[1]=='d') return LS_D; if(input[1]=='R') return LS_R; if(input[1]=='i') return LS_I; } else if(strlen(input)==3) { if(input[1]=='a'&& input[2]=='l') return LS_AL; if(input[1]=='a'&& input[2]=='i') return LS_AI; } return -1; } int main(int ac,char* av[]) { if(ac == 1) { do_ls(".",LS_NONE); } else { int mode = LS_NONE; // 默认为无参数ls int have_file_param = 0; // 是否有输入文件参数 while(ac>1) { ac--; av++; int calMode = analyzeParam(*av); if(calMode!=-1) { mode+=calMode; } else { have_file_param = 1; do { printf("%s:\n", *av); do_ls(*av,mode); printf("\n"); ac--; av++; }while(ac>=1); } } if (!have_file_param) { do_ls(".",mode); } } }
makels改进测试:
码云链接提交图:
来源:https://www.cnblogs.com/ldc175206/p/12114475.html