资源描述
Linux下实现Is命令(仅适用于 Is -a pathname ; Is T pathname; Is pathname )
Is命令就是list的缩写,缺省下Is用来打印出当前目录的清单,如果I S指定其他目录,那么就会显示指定目录里的文件及文件夹清单。通过Is命令 不仅可以查看linux文件夹包含的文件.而且可以查看文件权限(包括目录、文 件夹、文件权限),查看目录信息等等,Is命令在日常的linux操作中用的很多
-a选项:表示显示该目录下的所有文件,包括隐藏文件。
-I选项:表示显示文件的详细信息,包括方问权限,文件大小…… 例如:Is -a /Is - I /
1)主要构造的函数void error (const char *err string, int line);
〃错误处理函数,打印错误所在行数和错误信息void Demonstrate attribute (struct stat buf, char *name);
〃获得文件属性并打印void Demonstrate si ng Ie (char *name);
〃输出文件名,命令没有-1选项。输出文件名要保持上下对齐void Demonstrate(int flag, char *pathname);
〃根据命令行参数和文件路径名来显示目标文件void Demonstrate dir (int 千lag parameter, char *path);
〃为显示某个目录下的文件做准备2)函数流程
(1)获取该目录下文件的总数和最长文件名(2)假设获该目录下所有文件的文件名,存放于变量f i lenames中
(3)使用冒泡法对文件名按字母顺序存储于fi lenanes中(4)调用Demonstrate。函数来显示每个文件信息
3)程序中主要的结构体:
参数struct stat *buf是一个保存文件状态信息的结构体A):struct stat {
dev st dev;〃文件设备号ino t st ino;〃文件的 i-node
mode t st mode;〃文件类型和存储权限nl ink t st nI ink;〃连到该文件的硬链接数目。
uid t st uid:〃文件所有者的用户idgid t st Mid;〃文件所有者的组id
dev t st rdev:〃假设此文件为设备文件,那么为其设备编号off t st size;〃文件大小
blksize t st blksize;〃文件系统的I/O缓冲区大小blkcnt t st blocks;〃占用文件区块的个数
time t st atime;〃文件最近一次被访问的时间 文件最后一次被修改的时间
time_t st_ctime;〃文件最近一次被更改的时间 }其中,对于st nxxJe包含的文件类型信息,P0SIX标准定义了一系列的宏:
S ISLNK (st mode) 〃判断是否为符号链接S_ISREG (st_mode) 〃判断是否为一般文件
/***用Istat而不是stat以方便解析链接文件
*/if ( I stat (pathname, &buf) = -1 ) 〃I stat返回的是符号链接文件文件本身 的4犬态信息
(error ("stat", _LINE_J ;
1 ——switch (flag)
(case PARAMETER NONE: 〃没有一I选项
if (name[0] !='.')(
Demonstrate_s ingle (name);} "
break;case PARAMETER A: // -a:显示包括隐藏文件在内的所有文件
Demonstrate single(name);break;
case PARAMETER L: 〃-1:每个文件单独占一行,显示文件的详细属性信息if (name[0] !=')
(Demonstrate attr ibute(buf, name);
printfC' %-s\n", name);1
break;case PARAMETER A + PARAMETER L: 〃同时有-a 和选项的情况
Demonstrate attr ibute(buf, name);printfC' 5{ns\n", name);
break;default:
break;}
1/*为显示目录下的文件做准备*/
void Demonstrate_dir(int flag_parameter, char *path)(
DIR*dir;struct d i rent *ptr;
int count = 0;char fi Ienames[256] [PATH MAX + 1 ], tenp[PATH_MAX + 1];
〃获取该目录下文件总数和最长的文件名dir = opendir (path);
if (dir = NULL) error ("opendir", _LINE__);1
whi Ie ((ptr 二 readdir (dir)) != NULL) if (g maxlen < str Ien(ptr->d name))r maxlen = str Ien (ptr->d_name);
count++;1
c I osed i r (d i r);if (count > 256)
error ("too many f i les under this dir",_LINE_);int i, i, len = str I en (path);
〃获取该目录下所有的文件名dir = opendir (path);
for (i = 0; i < count; i++) (ptr = readd i r (d i r);
if( ptr = NULL) (error ("readdir",_LINE_);
)strncpv (f i lenames [i], path, I en); //f i I enames 存放目录下的所有文件名
f i Ienames[i] [Ien] = *\0';str cat (f i I enames [ i ]. ptr->d name);
f i Ienames[i] [len + str Ien (ptr->d_name)]二’\0’;)
〃使用冒泡法对文件名进行排序,排序后文件名按字母顺序存储于千i lenan^s for (i = 0; i < count-1; i++)for (j = 0; j < count - 1 - i; j++)
(if ( strcnp(fi lenames[j], fi Ienames[j + 1]) > 0 )
(strcpv(tenp.fi Ienames[j + 1]);
temp [str I en (f i I enames [ i + 1])]='\0';strcpv(f i Ienames[i + 1], f i Ienames[j]);
fi Ienames[j + 1] [strlen(fi Ienames[j])] = '\0';strcpv(f i Ienames[ j], tew):
f i Ienames[j] [str Ien(terrp)] = '\0";1
)for (i = 0: i < count; i++)
Demonstrate (flagj^arameter, fiIenames[i]);「I I r (,
〃如果命令行$没有-|选项,打印一个换行符if( (flag parameter & PARAMETER_L) = 0)
printf ("Xn'1);)
附录资料:不需要的可以自行删除Abstract: Based on the comprehensive analysis on the plastic part's structure service requirement, mounding quality and mould menu factoring cost. A corresponding injection mould of internal side core pulling was designed. By adopting the multi-direction and multi-combination core-pulling. A corresponding injection mould of internal side core pulling was designed, the working process of the mould was introduced
C语言详解-枚举类型注:以下全部代码的执行环境为VC++ 6.0
在程序中,可能需要为某地整数定义一个别名,我们可以利用预处理指令#define来完成这 项工作,您的代码可能是:
# dcfinc MON 1define TUE 2
# define WED 3define THU 4
# define FRI 5define SAT 6
# define SUN 7在此,我们定义一种新的数据类型,希望它能完成同样的工作。这种新的数据类型叫枚举型。
1 .定义一种新的数据类型一枚举型
以下代码定义了这种新的数据类型一枚举型enum DAY
{
MON=LTUE, WED, THU, FRI, SAT, SUN};
(I)枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号, 隔开。
⑵DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。
(3)第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。
(4)可以人为设定枚举成员的值,从而自定义某个范围内的整数。
(5)枚举型是预处理指令#define的替代“(6)类型定义以分号;结束。
2 .使用枚举类型对变量进行声明新的数据类型定义完成后,它就可以使用了。我们已经见过最基本的数据类型,如:整型int, 单精度浮点型float,双精度浮点型double,字符型char,短整型short等等。用这些基本数据 类型声明变量通常是这样:
char a; 〃变量a的类型均为字符型char charletter;inix,
y,
z; 〃变量x,y和z的类型均为整型int int number;double m, n;
double result; 〃变量result的类型为双精度浮点型double 既然枚举也是一种数据类型,那么它和基本数据类型一样也可以对变量进行声明。
方法■:枚举类型的定义和变量的声明分开enum DAY (
MON= 1, TUE, WED. THU, FRI, SAT, SUN }; enum DAY yesterday;enum DAY today;
enum DAY tomorrow; 〃变量(omorrow 的类型为枚举型 enum DAYenum DAY good_day, bad_day; 〃变量 good_day 和 bad_day 的类型均为枚举型 enum DAY 方法二:类型定义与变量声明同时进行:
enum〃跟第一个定义不同的是,此处的标号DAY省略,这是允许的。 {Saturday, sunday = 0, monday, luesday, Wednesday, thursday, friday
} workday; 〃变量workday的类型为枚举型enum DAYenum week { Mon=l, Tue, Wed. Thu. Fri Sal, Sun} days; 〃变量 days 的类型为枚举型 enum week
enum BOOLEAN { false, true } end_flag, malch_flag; 〃定义枚举类型并声明了两个枚举型变 量方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明: typcdef enuni workday {
Saturday, sunday = 0, monday, tuesday, Wednesday, thursday, friday} workday; 〃此处的workday为枚举型enum workday的别名
workday today, tomorrow; 〃变量 today 和 tomorrow 的类型为枚举型 workday,也即 enum workdayenurn workday 中的 workday 可以省略:
typcdcf cnum {Saturday, sunday = 0, monday, tuesday, Wednesday, thursday, Friday
} workday; //此处的workday为枚举型cnum workday的别名workday today, tomorrow; 〃变量 today 和 tomorrow 的类型为枚举型 workday,也即 enum workday 也可以用这种方式:
typedef enum workday |Saturday, sunday = 0, inonday, tuesday, Wednesday, thursday, friday
1;workday today, tomorrow; 〃变量 today 和 tomorrow 的类型为枚举型 workday,也即 enum workday
注意:同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常 量。错误例如如下所示:
错误声明一:存在同名的枚举类型typedef enum {
Wednesday,
thursday, friday } workday;typedef enum WEEK (
Saturday,
sunday = 0, nionday, } workday;错误声明二:存在同名的枚举成员
typedef enum {
Wednesday,
thursday, friday } workday」;typedef enum WEEK {
Wednesday, sunday = 0, monday, } workday_2;.使用枚举类型的变量
2.1 对枚举型的变量赋值。
实例将枚举类型的赋值与基本数据类型的赋值进行了比照: 方法一:先声明变量,再对变量赋值#include<stdio.h>
/*定义枚举类型*/enum DAY { MON=1,TUE, WED, THU, FRI, SAT, SUN };
void main()(
/*使用基本数据类型声明变显,然后对变显赋值*/
int x, y, z;
x= 10;
y = 20;
z = 30;
/*使用枚举类型声明变量,再对枚举型变量赋值*/
enum DAY yesterday, today, tomorrow;
yesterday = MON;
today = TUE;
tomorrow = WED;
printf("%d %d %d \n", yesterday, today, tomorrow);}
方法二:声明变量的同时赋初值#include <stdio.h>
/*定义枚举类型*/enum DAY { MON=1,TUE, WED, THU, FRI, SAT, SUN };
void main(){
/*使用基本数据类型声明变量同时对变量赋初值*/
int x=10, y=20, z=30;
/*使用枚举类型声明变量同时对枚举型变量赋初值*/
enum DAY yesterday = MON,
today = TUE, tomorrow = WED;
printf("%d %d %d \n'\ yesterday, today, tomorrow);方法三:定义类型的同时声明变量,然后对变量赋值。
#include <stdio.h>/*定义枚举类型,同时声明该类型的三个变量,它们都为全局变量*/
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN } yesterday, today, tomorrow;/*定义三个具有基本数据类型的变量,它们都为全局变量*/
int x, y, z;void main()
{
/*对基本数据类型的变量赋值*/
x = 10; y = 20: z = 30;
/*对枚举型的变量赋值*/
yesterday = MON;
today = TUE;
tomorrow = WED;
printf("%d %d %d \n", x, y, z); 〃输出:10 20 30
printf("%d %d %d \n'\ yesterday, today, tomorrow); 〃输出:I 2 3)
方法四:类型定义,变量声明,赋初值同时进行。
#includc <stdio.h>/*定义枚举类型,同时声明该类型的三个变量,并赋初值。它们都为全局变量*/
enum DAY{
MON=I,
TUE,
WED,
THU, FR1, SAT, SUN)
yesterday = MON, today = TUE, tomorrow = WED;/*定义三个具有基本数据类型的变量,并赋初值。它们都为全局变量*/
int x = 10, y = 20, z = 30;void main()
printf("%d %d %d \n", x, y, z); 〃输出:10 20 30
printf("%d %d %d \n", yesterday, today, tomorrow); 〃输出:12 3)
2.2 对枚举型的变量赋整数值时,需要进行类型转换。
#include <stdio.h>enum DAY { MON=1,TUE, WED, THU. FRI, SAT. SUN );
void main(){
enum DAY yesterday, today, tomorrow;
yesterday = TUE;
today = (enum DAY) (yesterday + 1); 〃类型转换
tomorrow = (enum DAY) 30; 〃类型转换
//tomorrow = 3; 〃错误
printf("%d %d %d \n'\ yesterday, today, tomorrow); 〃输出:2 3 30 I使用枚举型变量
#include<stdio.h>enum
{
BELL= W,
BACKSPACE = '\b',
HTAB='\t',
RETURN= '\r;
NEWLINE = '\n',
VTAB=W,
SPACE=" enum BOOLEAN { FALSE = 0, TRUE } match_flag;void main()
{
int index = 0;
int count_ofllcttcr = 0;
int count_oOpace = 0;
char str[] = "I'm Ely efod";
match_flag = FALSE;
for(; str[index] != ''0'; index++)if( SPACE != str[index]) count_oflletter++;
else(
match_flag = (enuni BOOLEAN) 1;count_oflspace++;
)printf("%s %d times %c", match_flag ? "match": "not match", count_oflspace, NEWLINE); printf("count of letters: %d %c%c", count_oLletter, NEWLINE, RETURN);
1输出:
match 2 timescount of letters: 10
Press any key to continue4.枚举类型与sizeof运算符
#include <stdio.h>enum escapes
{
BELL=
BACKSPACE = \b',
HTAB= *\t',
RETURN ='\r;
NEWLINE = '\n',
VTAB= '\v\
SPACE="};
enum BOOLEAN { FALSE = 0, TRUE } match_flag;void main()
{
printf("%d bytes \n", sizeof(enum escapes)); //4 bytes
printf("%d bytes \n", sizcof(cscapcs)); //4 bytes
printf("%d bytes \n", sizeof(enum BOOLEAN)); //4 bytes
printf("%d bytes \n", sizeof(BOOLEAN)); //4 bytes
printf("%d bytes \n", sizeof(match_flag)); //4 bytesS ISDIR (st mode) 〃判断是否为目录文件
S I SOP (st mode) 〃判断是否为字符设备文件S IBLK (st mode) 〃判断是否为块设备文件
S ISFIFO (st mode) 〃判断是否为先进先出FIFOS ISFOCK (st mode) //判断是否为 socket
B): struct passwd *psd; 〃从该结构体中获取文件所有者的用户名C): struct group *grp; 〃从该结构体中获取文件所有者所属组的组名
4)心得体会本次课程设计我写的是Linux下的Is命令,通过这次课程设计,不仅使我对Is 命令有了更深一层的认识,还认识到了系统提供的命令实现的途径和方法。之前 总是使用系统命令,如今自己编程实现了一些命令,每次使用系统提供的命令和 调用自己编写的命令感觉大不相同。
5)具体解析与详细代码:
#include <stdio. h>#include <stdlib. h>
#include <str ing. h>#include <time. h>
#include <sys/stat. h>#include <unistd. h>
#include <sys/types. h>include <1 inux/l imits. h>
# include <dirent. h>include <grp. h>
# include <pwd. h>include <errno. h>
# define PARAMETER NONE 0 〃无参数define PARAMETER A 1 // -a:显示所有文件
# define PARAMETER L 2// T : 一行显示一个文件的详细信息define MAXROWLEN 80 〃一行显示的最多字符数
int r leave len二MAXROWLEN; 〃一行剩余长度,用于输出对齐int g max I en; 〃存放某目录下最长文件名的长度
void error (const char *err_string, int line); 〃专酊吴处理函数,打印4 酊吴 所在行数人错误信息void Demonstrate attr ibute(struct stat buf, char * name); 〃获取文件属 性并打印
void Demonstrate single (char * name);〃输出文件名,命令没有T 选项,那么 输出文件名时要保持上下文对齐void Demonstrate(int flag, char * pathname); /"艮^^令行豺攵牙口文彳牛*'各 径名显示目标文件
void Demonstrate_dir (int f lag_parameter, char * path); 〃为显示某个目 录下的文件做准备一int main(int argc, char ** argv) int i, j, k, nun;
printf("%d bytes \n", sizeof(SPACE)); //4 bytes
printf("%d bytes \n", sizeof(NEWLINE)); //4 bytes
printf("%d bytes \n", sizeof(FALSE)); //4 bytes
printf("%d bytes \n", sizeof(0)); //4 bytes)
5.综合举例#include<stdio.h>
enum Season{
spring, sunimer= 100, fall=96, winter1;
typedef enum{
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, SundayI
Weekday;void main()
{
/* Season */
printf("%d \n", spring);//0
printf("%d, %c \n", summer, summer); // 100, d
printf("%d \n\ fall+winter);// 193
Season mySeason=winter;
if(winter==mySeason)printf("myScason is winter \n"); // myScason is winter
int x= 10();
if(x==summer)printf("x is equal to summer\n"); 〃 x is equal to summer
printf("%d bytes\n", sizeof(spring)); // 4 bytes
/* Weekday */
printf("sizcof Weekday is: %d \n", sizcof(Wcckday)); //sizcof Weekday is: 4
Weekday today = Saturday;
Weekday tomorrow;
if(today == Monday)tomorrow = Tuesday;
elsetomorrow = (Weekday) (today + 1); //remember to convert from int to Weekday
本文来自CSDN--xiaobai32966博客
char path [PATH MAX+1]; 〃文件路径名
char parameter [32];〃保存命令行参数,目标文件名和目录名不在此列
int flag paraneter二PARAMETER_NONE; 〃用来标志参数种类,即是否有T和- a选项
struct stat buf;
/*首先对命令行参数进行解析,即提取命令行参数中后的选项。用户的输入有 多样性,如Is-1 -a; Is-la。我们用两层循环类来解析参数.外层循环对a rgv □数组中的元素依次进行内层循环的解析,二层循环对以=为首的字符 串进行选项提取.并把每个选项存于parameter □数组当中,用nun记下'-' 的数目,以备后用。而命令行参数中的总选项数目那么用j计数。
*/
i = 0,
num = 0;
for (i = 1 ; i < argc; i++)
(
if (argv[i] [0]='-1)
(
for (k = 1; k < str len(argv[i]); k++)
(
parameter [j] = argv[i] [k]; 〃获取一后面的参数保存到数组parameter中 J44-;
1
nuE; //保存的个数
1
)
/*检查刚刚提取的选项是否合法。并且用或运算记录参数,以备后用。最后为选项数 组的末尾元素赋,\0'。
*/
//check the argunent because of only supporting -a ang -I
for(i = 0; i < j; i++)
(
if (parameter[i] = 'a1)
(
f lag_parameter = PARAMETERA;
continue;
) , else if (parameter[i] = 'I') (
flag parameter = PARAMETER_L; continue;
1
elseprintf ("my_ls: invaI id option Tk)\n”, parameter[i]); exit (1);
) 1 parameter [j] = '\0';/*
由上面所知num记录的是参数中‘-’的数量,因此如果num+1=argc,那说明 用户所输入的命令行参数不包含目录或文件名。只是显示当前目录下的文件。因 为这是我们必须自动将path赋值为当前目录。为了使其称为一个字符串,必须 在末尾加'\0'。然后进入Demonstrate_dir函数.
*///print the information of current directory if the cannand without th e name of target f i Ie and current directory if ((num + 1) = argc)
{strcpy(path, /");// /"当前目录
path [2] = '\0':
Demonstrate_d i r (f I ag_parameter, path); return 0;1
/*
如果命令行参数包含目录或者文件名,那么我们要检查其合法性(参数中 的目录或者文件是否存在)。这里我们利用stat族函数来获取文件的属性,实现 上述功能。stat族函数通常有两个参'数:文件路径/文件描述符.struct stat *buf类型的结构体。如果操作成功,那么buf将保存文件的属性。假设合法,利 用宏S ISDIR(buf. st mode),判断此文件是否为目录文件。假设为目录文件那么进入 Demonstrate dir 函数,否那么进入Demonstrate 函数。通常情况,Demonstrate dir函数是获取path目录下所有文件的完整路径玄,在使每个文件执行Demons trate函数。因此如果参数中是指定的文件名.那么可绕过 Demonstrate_d i r 函数,直接进入 Demonstrate 函数。
*/ i=1; do { /* 梆如果不是目标文件名或目录,解析下一个命令行参数 */if (argv[i][0]='」) (
i『continue;1
else strcpy (path, argv[i]);/*
林如果目标文件或目录不存在,报错并退出程序*/
if ( stat (path, &buf) = -1 )(
error ("stat", _LINE_J ;1
if ( S ISDIR(buf. st mode) ) // argv[i]是一个目录〃如果目录的最后一个字符不是就加上'/'
(if (path] strlen(argv[i])-1 ] != '/')
(path[ strlen(argv[i]) ] = '/':
path[ str len(argv[i])+1 ]='\0';1
else(
path[ str len(argv[i]) ] = >\0';)
Demonstrate_d i r (f I ag_parameter, path);if
1else //argv[i]是一个文件
(Demonstrate (f I ag_parameter, path);
i++;)
)} whi Ie (i < argc);
return 0;1
/*料错误处理函数,打印出错误所在行的行数和错误信息
*/void error (const char *err_str ing, int I ine)
(fprintf(stderr, “line:%d ", line);
perror (err_str ing);exit(1);
1/*
**获取文件属性并打印*/
void Demonstrate_attr ibute(struct stat buf, char * name) char buf time[32]: 〃存放时间struct passwd *psd; 〃从该结构体中获取文件所有者的用户名 struct group *grp; 〃从该结构体中获取文件所有者所属组的组名
/***获取并打印文件类型
*///st mode:文件内容禾^存取权限
if (S_ISLNK(buf. stjnode)) 〃判断是否为符号链接(
printfC'l");)
else if (S_lSREG(buf. st_mode)) 〃判断是否为文件(
printf ;}
else if (S_ISDIR(buf. st_mode)) 〃判断是否为目录{
pr intf ("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)) 〃判断是否为先进先出的FIFO (printfCT');
)else if (S_ISSOCK(buf. st_mode)) 〃判断是否为 socket
(printf ("s");
)/*
林获取并打印文件所有者的权限*/
if (buf. st_mode & S_IRUSR)(
printfC'r");)
else(
printf ;)
if (buf. st_mode & S_IWUSR) (pr intf ("w");
) else ( printf ;1
if (buf. st_mode & S_IXUSR) (printf ("x");
1else ( printf ;
林获取并打印与文件所有者同组的用户对该文件的操作权限*/
if (buf. st_mode & S_IRGRP)(
pr intf ("r");1
else(
printf ;1
if (buf. st_mode & S_IWGRP)(
printfC'w");1
else(
printf ;1
if (buf. st_nDde & S_IXGRP)(
printfC'x");)
else(
printf ;)
/***获取并打印其它用户的对该文件的操作权限
*/if (buf. st_mode & S_IROTH) (
printfC'r");1
else ( printf C-");)
if (buf. st_mode & S_IWOTH) (pr intf ("w");
)else
(printf ;
)if (buf. st_mode & S_IXOTH) (
printfC'x");1
elsef
printf ;1
printfC'");/*
展开阅读全文