C语言实现ls之myls改进

C语言实现ls之myls改进

20191331 lyx

在之前的系统调用实践中已经实现myls-l命令

但该命令实现的并不完美,只能查看单一文件,且工程代码没有实现模块化

具体情况如下:

源代码链接:https://gitee.com/DKY2019/xxaqxt/blob/master/myls_l.c

现为实现完整的 ls-l 命令,做如下改进:

  • 代码模块化
  • 执行 ls -l ./ 打印目录下所有文件

代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <utime.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>


int print_type(mode_t st_mode){
    char perms[11]={0}; 
    switch (st_mode & S_IFMT){
        case S_IFLNK:
            perms[0]='l';
            break;
        case S_IFDIR:
            perms[0]='d';
            break;
        case S_IFREG:
            perms[0]='-';
            break;
        case S_IFBLK:
            perms[0]='b';
            break;
        case S_IFCHR:
            perms[0]='c';
            break;
        case S_IFSOCK:
            perms[0]='s';
            break;
        case S_IFIFO:
            perms[0]='p';
            break;
        default:
            perms[0]='?';
            break;
    }
    
    perms[1]=(st_mode & S_IRUSR) ? 'r':'-';
    perms[2]=(st_mode & S_IWUSR) ? 'w':'-';
    perms[3]=(st_mode & S_IXUSR) ? 'x':'-';
    perms[4]=(st_mode & S_IRGRP) ? 'r':'-';
    perms[5]=(st_mode & S_IWGRP) ? 'w':'-';
    perms[6]=(st_mode & S_IXGRP) ? 'x':'-';
    perms[7]=(st_mode & S_IROTH) ? 'r':'-';
    perms[8]=(st_mode & S_IWOTH) ? 'w':'-';
    perms[9]=(st_mode & S_IXOTH) ? 'x':'-';
  printf("%s ", perms);
  return 0;
}

int print_info(struct stat currentstat){
  struct passwd *p_passwd;
  struct group *p_group;
  char *p_time;
  int i;
  p_time = ctime(&currentstat.st_mtime);
  p_passwd = getpwuid(currentstat.st_uid);
  p_group = getgrgid(currentstat.st_gid);       
  printf("%d ",(int)currentstat.st_nlink);
  if(p_passwd != NULL)
	printf("%s ",p_passwd->pw_name);
  else
	printf("%d ",(int)currentstat.st_uid);
  if(p_group != NULL)
	printf("%s ",p_group->gr_name);
  else
	printf("%d ",currentstat.st_gid);
  printf("%7d ",(int)currentstat.st_size);
  for(i=0; p_time[i] !=0 && p_time[i]!='\n'; i++){
	  putchar(p_time[i]);
  }

  return 0;
}

int main(int argc, char* argv[]){
  char buf[500];
  DIR *currentdir = NULL;
  struct dirent *currentdp = NULL;
  struct stat currentstat;



  if(argc != 2)
  {
     printf("%s need filename\n",argv[0]);
     exit(1);
  }
  memset(buf,0,500); 
  sprintf(buf,"%s",argv[1]);
  currentdir = opendir(buf);
  if(currentdir == NULL){
     printf("open directory fail\n");
     return 0;
  }


  while((currentdp = readdir(currentdir)) != NULL)
 {
  if(currentdp->d_name[0] != '.')
 {
    sprintf(buf,"%s/%s",buf,currentdp->d_name);
  if(lstat(buf,&currentstat) == -1){
    printf("the dir:%s :",buf);
    printf("get stat error\n");
    continue;
  }

  lstat(buf,&currentstat);


  
  print_type(currentstat.st_mode);        
  print_info(currentstat);
  printf("  ");
  printf("%s\n", currentdp->d_name);
 
  memset(buf,0,500);
  sprintf(buf,"%s",argv[1]);
  
 }//if end
 }//while end
  closedir(currentdir);
  return 0;
}

码云链接:https://gitee.com/DKY2019/xxaqxt/blob/master/myls相关练习/myls_l-2.c

执行效果:

完善myls

  • 文件名读入数组,qsort()排序(为复习C语言,qsort手工完成,参考)
  • 加入-a选项
  • 计算列宽和行数

代码:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<dirent.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>

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;
}

int find_mid(char(*data)[512], int l, int r)
{
    int mid = (l + r) / 2;
    if(strcmp(data[l], data[mid]) > 0)
    {
        int t = l;
        l = mid;
        mid = t;
    }
    if(strcmp(data[mid], data[r]) > 0)
    {
        int t = mid;
        mid = r;
        r = t;
    }
    return mid;
}

void swap(char *a, char *b)
{
    char t[512];
    strcpy(t, a);
    strcpy(a, b);
    strcpy(b, t);
}
void sort(char(*data)[512], int l, int r)
{
    while(l < r)
    {
        int x = l, y = r;
        int mid = find_mid(data, l, r);
        do
        {
            while(strcmp(data[y], data[mid]) > 0)
                y--;
            while(strcmp(data[x], data[mid]) < 0)
                x++;
            if(x <= y)
            {
                swap(data[x++], data[y--]);
            }
        }
        while(x <= y);
        sort(data, x, r);
        r = y;
    }
}
int check_filename_color(int mode_bit)
{
    int file_type = (mode_bit & 0170000);
    if(file_type == 0040000) return 2;
    if(mode_bit & 0000111) return 1;
    return 0;
}

void printdir(char* dirname, int is_all)
{
    char pathname[512];
    char names[256][512];
    int cnt_name = 0;
    DIR* dir;
    struct dirent* dp;
    struct stat st;
    if(!(dir = opendir(dirname)))
    {
        perror("opendir");
        exit(1);
    }
    //weather filter "." ".."
    while(dp = readdir(dir))
    {
        if(!is_all && dp -> d_name[0] == '.')
            continue;
        strcpy(names[cnt_name++], dp -> d_name);
    }

    sort(names, 0, cnt_name - 1);
    //printf("[%s]\n", names[0]);

    for(int i = 0; i < cnt_name; i++)
    {
        sprintf(pathname, "%s/%s", dirname, names[i]);
        if(stat(pathname, &st) == -1)
        {
            perror("stat");
            exit(1);
        }
        int filename_color = check_filename_color(st.st_mode);
        if(filename_color == 1)
        {
            printf("\33[1;32m%s\33[0m  ", pathname + 2);
        }
        else if(filename_color == 2)
        {
            printf("\33[1;34m%s\33[0m  ", pathname + 2);
        }
        else printf("%s  ", pathname + 2);

    }
    closedir(dir);
    printf("\n");
}
int main(int argc, char* argv[])
{
    int is_all = 0;
    if(argc == 1)
    {
        printdir(".", is_all);
        return 0;
    }
    if(argc > 1)
    {
        for(int i = 1; i < argc; i++)
        {
            if(argv[i][0] != '-') continue;
            for(int j = 1; argv[i][j]; j++)
            {
                if(argv[i][j] == 'a') is_all = 1;
                else
                {
                    printf("invalid option, please check again!\n");
                    exit(1);
                }
            }
        }
    }
    int flag = 0;
    for(int i = 1; i < argc; i++)
    {
        if(argv[i][0] == '-') continue;
        flag = 1;
        printdir(argv[i], is_all);
    }
    if(!flag) printdir(".", is_all);
    return 0;
}

码云链接:https://gitee.com/DKY2019/xxaqxt/blob/master/myls相关练习/myls-2.c

执行效果:

参考资料

qsort使用方法 https://blog.csdn.net/C_time/article/details/88428100
C语言实现qsort https://blog.csdn.net/qq_43632625/article/details/93140277

posted @ 2021-11-07 18:42  20191331liyu  阅读(169)  评论(0编辑  收藏  举报