使用Linux C 简易实现LS(实现过程)

ls实现过程

参考书籍:Unix-Linux编程实践教程

可以说这个是我写的第一个项目,也是我成长的最多的一个项目,因为这个项目我整整写了四个版本,也大概是4个程序实现的过程,一个从39行到380行的进步

第一版 ls实现列出每个文件名的功能

青涩的代码

/*************************************************************************
	> File Name: ls1.cpp
	> Author: ldc
	> Mail: litesla
	> Created Time: 2018年09月21日 星期五 19时17分38秒
 ************************************************************************/

#include
#include 
#include 
//#include 

void do_ls(char []);

int main(int ac,char * av[]){
     
    if (ac == 1) {
     
        do_ls(".");
    } else {
     
        while (--ac) {
     
            //printf("%s:\n", *(++av));
            ++av;
            do_ls(*av);
        }
    }
    return 0;
}
/ls1 /
void do_ls(char dirname[]){
     
    DIR *dir_ptr;
    struct dirent  *direntp;
    if ((dir_ptr = opendir(dirname)) == NULL) {
     
        fprintf(stderr, "ls1 cannot open %s\n",dirname);
    } else {
     
        while ((direntp = readdir(dir_ptr)) != NULL)
            printf("%s   ", direntp->d_name);
        printf("\n");
        closedir(dir_ptr);
    }
}

样例截图

在这里插入图片描述

总结

这次的实现只是属于尝试版本,因为涉及到的结构体,有点陌生所以拿来练练手,但是当我看到屏幕输出的时候还是非常兴奋的

问题与改进

这个只是ls的基础功能,但是没有实现 -l 的功能,为此我做了第二版改进

第二版 ls -l实现

测试代码

/*************************************************************************
	> File Name: ls2.cpp
	> Author: ldc
	> Mail: litesla
	> Created Time: 2018年09月21日 星期五 19时44分01秒
 ************************************************************************/

#include
#include 
#include 
#include 
using namespace std;

void do_ls(char []);
void dotat(chat *);
void show_stat_info(char *fname, struct stat *buf);
void mode_to_letters(int mode, char str[]);
char *uid_to_name(uid_t);
char *gid_to_name(gid_t);
int main(int ac, char *av[]){
     
    struct stat info;

    if (ac > 1) {
     
        if (stat(av[1],&info) != -1) {
     
            show_stat_info(av[1], &info);
            return 0;
        }
        else{
     
            perror(av[1]);
            return 1;
        }
    }
    return 0;
}
void show_stat_info(char *fname, struct stat *buf){
     
    printf("   mode:%o\n",buf->st_mode);
    printf("  links:%d\n",buf->st_nlink);
    printf("   user:%d\n",buf->st_uid);
    printf("  group:%d\n",buf->st_gid);
    printf("   size:%d\n",buf->st_size);
    printf("modtime:%d\n",buf->st_mtime);
    printf("   name:%s\n",fname);

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

}

不是那么青涩的代码

/*************************************************************************
	> File Name: ls2.cpp
	> Author: ldc
	> Mail: litesla
	> Created Time: 2018年09月21日 星期五 19时44分01秒
 ************************************************************************/

#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

void do_ls(char []);
void dostat(char *,char *);
void show_stat_info(char *fname, struct stat *buf);
void mode_to_letters(int mode, char str[]);
char *uid_to_name(uid_t);
char *gid_to_name(gid_t);



int main(int ac, char *av[]){
     
    if (ac == 1) {
     
        do_ls(".");
    } else {
     
        while(--ac){
     
            //printf("%s:\n", *(++av));
            av++;
            do_ls( *av );
        }
    }
    return 0;
}
void do_ls(char dirname[]){
     
    DIR *dir_ptr;
    struct dirent * direntp;
    if ((dir_ptr = opendir(dirname)) == NULL){
     
        fprintf(stderr, "ls22:connot open %s\n", dirname);
    } else {
     
        while (( direntp = readdir(dir_ptr)) != NULL){
     
            dostat(direntp->d_name,dirname);
        }
        closedir(dir_ptr);
    }
}

void dostat( char *filename ,char dirname[]){
     
    struct stat info;
    char pwdname[1000];
    //memset(pwdname,0,sizeof(pwdname));
    strcpy(pwdname,dirname);
    if(strcmp(dirname,".") == 0){
     
        strcpy(pwdname,filename);
    } else if (strcmp(dirname,"/") == 0){
     
        strcat(pwdname,filename);
    } else {
     
        strcat(strcat(pwdname,"/"), filename);

    }
    //printf("dirname:%s\n filename:%s\n",dirname,filename);
    if(stat(pwdname, &info) == -1){
     
        perror(filename);
    } else {
     
        show_stat_info(filename, &info);
    }
}

void show_stat_info(char *filename, struct stat *info_p){
     
    //char *uid_to_name(), *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("%-4d", info_p->st_blocks/2);
    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;
    struct passwd *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;
    struct group *grp_ptr;
    static char numstr[10];
    
    if((grp_ptr = getgrgid(gid)) == NULL){
     
        sprintf(numstr,"%d", gid);
        return numstr;
    }else{
     
        return grp_ptr->gr_name;
    }
}

样例截图

使用Linux C 简易实现LS(实现过程)_第1张图片

总结

可以看到这一版和上一版,你不会想到是一个人在隔了一天写出的代码,可以看出来进步是多么明显

问题与改进

这个与上个实现的功能的不同,只能实现-l的功能,不能传递参数,而且没有颜色的功能,一般的ls都是有功能的,所以我做出了第三版本

第三版本 ls -al 和颜色的实现

摆脱青涩的代码

/*************************************************************************
	> File Name: ls2.cpp
	> Author: ldc
	> Mail: litesla
	> Created Time: 2018年09月21日 星期五 19时44分01秒
 ************************************************************************/

#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define BROWN                "\e[0;33m"
#define NONE                 "\e[0m"
#define BLUE                 "\e[0;34m"

void do_ls(char [], int);
void print(char *ch);
void dostat(char *,char *,int);
void show_stat_info(char *fname, struct stat *buf,int gon);
void mode_to_letters(int mode, char str[]);
char *uid_to_name(uid_t);
char *gid_to_name(gid_t);

int main(int ac,char *av[]){
     
    int temp = 0,i = 2; //00 低位是a,高位是l
    *(++av);
    for(i = 2; i <= ac && (*av)[0] == '-'; *(++av),i++){
     
         strlen(*av) == 2 && (*av)[1] =='a'&& (temp |=1,1)||(*av)[1] == 'l' && (temp |= 2,1);
         strlen(*av) == 3 && ((*av)[1] == 'a' && (*av)[2] == 'l' ||
                              (*av)[1] == 'l' && (*av)[2] == 'a') && (temp |= 3,1);
    }
    if (i > ac) {
     
        do_ls(".",temp);
    }else if (i == ac) {
     
        do_ls(*av,temp);
    }
    else{
     
        while(i <= ac){
     
            printf("%s:\n",*av);
            do_ls(*av,temp);
            *(++av);
            i++;
        }
    }
    return 0;
}


int comp(const void *a, const void *b){
     
    return strcmp((char *)a, (char *)b);
}


void do_ls(char *dirname, int gon){
     
    DIR *dir_ptr;
    struct dirent *direntp;
    struct stat dir;
    char name[1000][255];
    int tn = 0;
    
    if ((dir_ptr = opendir(dirname)) == NULL) {
     
        fprintf(stderr, "ls3:connot open %s\n", dirname);
    } else {
     
       
        while((direntp = readdir(dir_ptr)) != NULL){
     
            if(gon & 1){
     //1
                strcpy(name[tn],direntp->d_name);
                tn++;
            }else{
     
                if(direntp->d_name[0] == '.') continue;
                strcpy(name[tn],direntp->d_name);
                tn++;
            }
        }
        
    }
    qsort(name,tn,sizeof(name[0]),comp);
    for(int i = 0; i < tn; i++){
     
        dostat(name[i],dirname,gon);
    }
    printf("\n");
}
void dostat( char *filename ,char dirname[],int gon){
     
    struct stat info;
    char pwdname[1000];
    
    strcpy(pwdname,dirname);
    if(strcmp(dirname,".") == 0){
     
        strcpy(pwdname,filename);
    } else if (strcmp(dirname,"/") == 0){
     
        strcat(pwdname,filename);
    } else {
     
        strcat(strcat(pwdname,"/"), filename);
    }
    

    if(stat(pwdname, &info) == -1){
     
        perror(filename);
    } else {
     
        show_stat_info(filename, &info,gon);
    }
}

void show_stat_info(char *filename, struct stat *info_p,int gon){
     
    char modestr[11];

    mode_to_letters(info_p->st_mode, modestr);
    if(gon & 2){
     
        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));

        if (modestr[0] == 'd') printf(BROWN "%s\n" NONE, filename);
        else if(modestr[0] == '-') printf(BLUE "%s\n" NONE, filename);


    }else{
     
        if (modestr[0] == 'd') printf(BROWN "%s " NONE, filename);
        else if(modestr[0] == '-') printf(BLUE "%s " NONE, 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 *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 *grp_ptr;
    static char numstr[10];
    
    if((grp_ptr = getgrgid(gid)) == NULL){
     
        sprintf(numstr,"%d", gid);
        return numstr;
    }else{
     
        return grp_ptr->gr_name;
    }
}


样例截图

使用Linux C 简易实现LS(实现过程)_第2张图片

总结

这次可以说是比较完美的了,而且他还可以解析多个文件加,文件名也对齐了

问题与总结

完美总是想着跟完美,所以我就进行了我当时能做的最后一步

第四版 ls 模块化+解析

开始成熟的代码

/*************************************************************************
	> File Name: ls4_1.cpp
	> Author: ldc
	> Mail: litesla
	> Created Time: 2018年09月22日 星期六 19时07分39秒
 ************************************************************************/
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;




//Macro definition

#define NONE                 "\e[0m"
#define BLACK                "\e[0;30m"
#define L_BLACK              "\e[1;30m"
#define RED                  "\e[0;31m"
#define L_RED                "\e[1;31m"
#define GREEN                "\e[0;32m"
#define L_GREEN              "\e[1;32m"
#define BROWN                "\e[0;33m"
#define YELLOW               "\e[1;33m"
#define BLUE                 "\e[0;34m"
#define L_BLUE               "\e[1;34m"
#define PURPLE               "\e[0;35m"
#define L_PURPLE             "\e[1;35m"
#define CYAN                 "\e[0;36m"
#define L_CYAN               "\e[1;36m"
#define GRAY                 "\e[0;37m"
#define WHITE                "\e[1;37m"

#define BOLD                 "\e[1m"
#define UNDERLINE            "\e[4m"
#define BLINK                "\e[5m"
#define REVERSE              "\e[7m"
#define HIDE                 "\e[8m"
#define CLEAR                "\e[2J"
#define CLRLINE              "\r\e[K" //or "\e[1K\r"


#define maxn 1000
#define chlen 255
#define qu  11
//end///




//Structure declaration
typedef struct Node{
     
    char name[chlen];
    //char pwdname[maxn];
    char jur[qu];
    int nlink;
    long  size;
    char ctim[chlen];
    struct stat filestat;
    char uidname[chlen];
    char gidname[chlen];

}Node;

typedef struct forlen0{
     
    int uid;
    int gid;
    int links;
}forlen0;

//end///


//Function declaration

//Function0
//main
//参数处理

//Function1
//init
//全局变量初始化
void init();

//Function2
//do_ls
//得到每个文件的名字 和当前目录文件总数 完成后续操作
void do_ls(char *);

//Function3
//dostat
//得到每个文件的具体信息
void dostat(char *, int);

//Function4
//show_stat_info
//将信息输入进去 和字符转化 统计对齐格式 
void show_stat_info(int,struct stat*);

//Function5
//mod_to_letters
//将权限转化为字符串
void mod_to_letters(int, char *);

//Function6
//uid_to_name
//将uid转化成对应的名字 获取对齐长度
void uid_to_name(int,uid_t);

//Function7
//gid_to_name
//将gid转化成对应的名字 获取对齐长度
void gid_to_name(int,gid_t);

//Function8
//print1
//普通输出
void print1(int);

//Function9
//print2
//长格式输出
void print2(int);

//end///




//Global variable declaration
Node files[maxn];
forlen0 forlen;
int op = 0;//00 la
int total;
//end///



//
//正文

int main(int ac,char *av[]){
     
    init();
    int opp = 0, i = 2; //00 la

    *(++av);
    for(i = 2; i <= ac && (*av)[0] == '-'; *(++av),i++){
     
         strlen(*av) == 2 && (*av)[1] =='a'&& (opp |=1,1)||(*av)[1] == 'l' && (opp |= 2,1);
         strlen(*av) == 3 && ((*av)[1] == 'a' && (*av)[2] == 'l' ||
                              (*av)[1] == 'l' && (*av)[2] == 'a') && (opp |= 3,1);
    }

    op = opp;

    if (i > ac) {
                             //默认文件夹
        do_ls(".");
    } else if (i == ac) {
                     //指定一个文件夹
        do_ls(*av);
    }
    else {
     
        while(i <= ac){
                      //指定多个文件夹
            printf("%s:\n", *av);
            do_ls(*av);

            *(++av);
            i++;
            printf("\n");
            init();
        }

    }
    return 0;
}


void init(){
     
    memset(files,0,sizeof(Node)*maxn);
    forlen.uid = 0;
    forlen.gid = 0;
    forlen.links = 0;
    total = 0;
}


//Function2
//get_filename
//得到每个文件的名字 和当前目录文件总数 完成后续操作
int comp(const void *a, const void *b){
     
    return strcmp((*(Node*)a).name, (*(Node*)b).name);
}

void  do_ls(char *dirname){
     
    DIR *dir_ptr;
    struct dirent *direntp;
    struct stat dir;
    int tn = 0;
    

    if ((dir_ptr = opendir(dirname)) == NULL) {
     
        fprintf(stderr, "ls5:connot open %s\n", dirname);
    } else {
     
       
        while((direntp = readdir(dir_ptr)) != NULL){
     
            if(op & 1){
     //1
                strcpy(files[tn].name,direntp->d_name);
                tn++;
            }else{
     
                if(direntp->d_name[0] == '.') continue;
                strcpy(files[tn].name,direntp->d_name);
                tn++;
            }
        }
        
    }

    qsort(files,tn,sizeof(files[0]),comp);
    for(int i = 0; i < tn; i++) dostat(dirname, i);
    
    if(op & 2) print2(tn);
    else print1(tn);
    
}


//Function3
//dostat
//得到每个文件的具体信息
void dostat(char *dirname,int i){
     
    struct stat info;
    char pwdname[1000];
    
    strcpy(pwdname,dirname);
    if(strcmp(dirname,".") == 0){
     
        strcpy(pwdname,files[i].name);
    } else if (strcmp(dirname,"/") == 0){
     
        strcat(pwdname,files[i].name);
    } else {
     
        strcat(strcat(pwdname,"/"), files[i].name);
    }
    //strcpy(files[i].pwdname,pwdname);

    if(stat(pwdname, &info) == -1){
     
        perror(files[i].name);
    } else {
     
        show_stat_info(i,&info);
    }    
}


//Function4
//show_stat_info
//将信息输入进去 和字符转化 统计对齐格式 
void show_stat_info(int i,struct stat* info_p){
     
    forlen.links = forlen.links < log10((int)info_p->st_nlink) ? log10((int)info_p->st_nlink) : forlen.links;
    files[i].nlink = (int)info_p->st_nlink;
    files[i].size = (long)info_p->st_size;
    strcpy(files[i].ctim, 4 + ctime(&info_p->st_mtime));
    mod_to_letters(info_p->st_mode, files[i].jur);
    uid_to_name(i,info_p->st_uid);
    gid_to_name(i,info_p->st_gid);
    total += info_p->st_blocks/2;
}


//Function5 
//mod_to_letters:
//将权限转化为字符串
void mod_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';    
}


//Function6
//uid_to_name
//将uid转化成对应的名字 获取对齐长度
void uid_to_name(int i,uid_t uid){
     
    struct passwd *pw_ptr;
    static char numstr[10]; 

    if((pw_ptr = getpwuid(uid)) == NULL){
     
        sprintf(numstr,"%d", uid);

        strcpy(files[i].uidname, numstr);
        forlen.uid = forlen.uid < strlen(numstr) ? strlen(numstr):forlen.uid;
    }else{
     
        strcpy(files[i].uidname, pw_ptr->pw_name);
        forlen.uid = forlen.uid < strlen(pw_ptr->pw_name) ? strlen(pw_ptr->pw_name):forlen.uid;
    }
    return ;
}


//Function7
//gid_to_name
//将gid转化成对应的名字 获取对齐长度
void gid_to_name(int i, gid_t gid){
     
    struct group *grp_ptr;
    static char numstr[10]; 

    if((grp_ptr = getgrgid(gid)) == NULL){
     
        sprintf(numstr,"%d", gid);

        strcpy(files[i].gidname, numstr);
        forlen.gid = forlen.gid < strlen(numstr) ? strlen(numstr):forlen.gid;
    }else{
     
        strcpy(files[i].gidname, grp_ptr->gr_name);
        forlen.gid = forlen.gid < strlen(grp_ptr->gr_name) ? strlen(grp_ptr->gr_name):forlen.gid;
    }

    return ;
}


//Function8 
//print1
//普通输出
void print1(int tn){
     
    for(int i = 0; i< tn; i++){
     
        if (files[i].jur[0] == 'd')
            printf(YELLOW "%s  " NONE, files[i].name);
        else if (files[i].jur[0] == 'c')
            printf(RED "%s  " NONE, files[i].name);
        else if (files[i].jur[0] == 'b')
            printf(CYAN "%s  " NONE, files[i].name);
        else if (files[i].jur[3] == 'x'||files[i].jur[6] == 'x'|| files[i].jur[9])
            printf(L_BLUE "%s  " NONE,files[i].name);
        else if (files[i].jur[0] == '-')
            printf(BLUE "%s  " NONE, files[i].name);
    }
    printf("\n");
}


//Function9
//print2
//长格式输出
void print2(int tn){
     
    printf("total: %d\n",total);
    for(int i = 0; i< tn; i++){
     
        
        printf("%s ", files[i].jur);
        printf("%-*d ", forlen.links+1,files[i].nlink);
        printf("%-*s ", forlen.uid+1, files[i].uidname);
        printf("%-*s ", forlen.gid+1, files[i].gidname);
        printf("%8ld ", files[i].size);
        printf("%.12s ", files[i].ctim);        

        if (files[i].jur[0] == 'd')
            printf(YELLOW "%s\n" NONE, files[i].name);
        else if (files[i].jur[0] == 'c')
            printf(RED "%s\n" NONE, files[i].name);
        else if (files[i].jur[0] == 'b')
            printf(CYAN "%s\n" NONE, files[i].name);
        else if (files[i].jur[3] == 'x'||files[i].jur[6] == 'x'|| files[i].jur[9])
            printf(L_BLUE "%s\n" NONE,files[i].name);
        else if (files[i].jur[0] == '-')
            printf(BLUE "%s\n" NONE, files[i].name);
    }
}
//end/

测试样例

使用Linux C 简易实现LS(实现过程)_第3张图片

总结

虽然显示与上次没有什么差别,但是思想却差别巨大,已经有了封装的雏形

问题与改进

其实这次的代码还是有不完美的地方,比如函数接口处理部分,比如ls软连接部等

经典操作

位运算读取存储参数

    int opp = 0, i = 2; //00 la

    *(++av);
    for(i = 2; i <= ac && (*av)[0] == '-'; *(++av),i++){
     
         strlen(*av) == 2 && (*av)[1] =='a'&& (opp |=1,1)||(*av)[1] == 'l' && (opp |= 2,1);
         strlen(*av) == 3 && ((*av)[1] == 'a' && (*av)[2] == 'l' ||
                              (*av)[1] == 'l' && (*av)[2] == 'a') && (opp |= 3,1);
    }

    op = opp;

你可能感兴趣的:(项目)