您的位置:首页 > 运维架构 > Linux

解读unix/linux编程实践教程------cp1.c延伸1

2014-04-14 22:23 381 查看
题目:添加cp1.c的功能,使得当两个参数是目录时,把第一个目录中的所有文件复制到第二个目录中。

C程序代码:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/stat.h>

#include <string.h>

#include <dirent.h>

#define BUFFERSIZE 4096

#define COPYMODE 0644//COPYMODE 用来定义创建文件的权限。

void oops(char *, char *);//输出出错信息到 stderr,即标准错误输出的文件流。

void *emalloc(size_t);//分配内存空间

int main(int ac, char *av[])

{

if ( ac != 3 ){

fprintf( stderr, "usage: %s source destination\n", *av);

exit(1);

}

if ( isadir(av[1]) ){

if ( isadir(av[2]) )

copydir(av[1], av[2]);

else {

fprintf(stderr,"cp1: %s is not a directory\n", av[2]);

exit(1);

}

}

else

do_copy( av[1], av[2] );

return 0;

}

copydir(char *srcdir, char *destdir)

{

char *srcpath, *destpath;

DIR *dir_ptr;//详解一

struct dirent *direntp;

srcpath = (char *) emalloc(strlen(srcdir)+1+MAXNAMLEN+1);//MAXNAMLEN文件名字所占字符数

destpath = (char *) emalloc(strlen(destdir)+1+MAXNAMLEN+1);

if ( (dir_ptr = opendir(srcdir)) == NULL )

oops("Cannot open directory", srcdir);

while( ( direntp = readdir(dir_ptr)) != NULL )

{

sprintf(srcpath,"%s/%s", srcdir, direntp->d_name);//sprintf用法详解二

if ( isadir(srcpath) ){

if ( strcmp(direntp->d_name,".") != 0 &&

strcmp(direntp->d_name,"..") != 0 )//strcmp(direntp->d_name,".")== 0说明该名是目录名称,

它的d_name也就是文件名或者说目录名 是"."或“..” (文件名不是"."并且文件名不是"..")

printf("skipping directory %s\n", srcpath);

continue;

}

sprintf(destpath, "%s/%s", destdir, direntp->d_name);

do_copy( srcpath, destpath );

}

closedir(dir_ptr);

free(srcpath);

free(destpath);

}

do_copy(char *src, char *dest)

{

int in_fd, out_fd, n_chars;

char buf[BUFFERSIZE];

char *destfilename;

char *make_destfilename(char*,char*);

destfilename = make_destfilename(src, dest);

if ( (in_fd=open(src, O_RDONLY)) == -1 )

oops("Cannot open ", src);

if ( (out_fd=creat( destfilename, COPYMODE)) == -1 )

oops( "Cannot creat", destfilename);

while ( (n_chars = read(in_fd , buf, BUFFERSIZE)) > 0 )

if ( write( out_fd, buf, n_chars ) != n_chars )

oops("Write error to ", destfilename);

if ( n_chars == -1 )

oops("Read error from ", src);

if ( close(in_fd) == -1 || close(out_fd) == -1 )

oops("Error closing files","");

}

void oops(char *s1, char *s2)

{

fprintf(stderr,"Error: %s ", s1);

perror(s2);

exit(1);

}

char *make_destfilename(char *src, char *dest)//将源目录中的文件复制到目的目录中,起名为原来文件的名字。

{

struct stat info;

char *srcfilename;

char *rv;

if ( stat(dest, &info) == -1 )/* let someone else handle this */

return dest;//这个错误处理的意思是抛出去~就是它本身出错了,但是自己不处理,谁调用它,它就把错误抛给谁去处理

if ( ! S_ISDIR(info.st_mode) )/* ok to copy to other types*/

return dest;//不是目录,是文件。

if ( (srcfilename = strrchr(src, '/')) != NULL )//strrchr()详解三srcfilename++;

else

srcfilename = src;

rv = emalloc(strlen(srcfilename) + strlen(dest) + 2);

sprintf(rv, "%s/%s", dest, srcfilename);

return rv;

}

void *emalloc(size_t n)//为n分配空间

{

void *rv = malloc(n);

if ( rv == NULL )

oops("Out of memory","");

return rv;

}

isadir(char *str)

{

struct stat info;

return ( stat(str,&info) != -1 && S_ISDIR(info.st_mode) );//详解四

}

programme unscramble:

1.this programme is a revised version of cp1.c that can copy an entire directory file by file to a second directory. It also supports some of the features required by earlier exercises.

A version of cp1.c that works if src or dest name directories(but not if src is a directory and dest is not)

* usage: cp1 src dest

* If dest names a directory, then copy src to dest/src

* If src names a directory, then copy all files in src to dest

* If src is a directory and dest is NOT a directory, quit

* Note: if src has a leading path, then only use last component

2. copydir()

loops through all files in srcdir, copying each to destdir uses do_copy but builds the paths here

Note: this function skips subdirectories of srcdir

3.do_copy( )

copies a file from src to dest. If dest is a directory, then do_copy() copies to a file in dest with the name taken from the filename for src

knowledge unscramble:

一.DIR

linux中dir命令参数支持的命令格式为:

DIR [filename] [/O[sortorder]] [/S] [/W](/ON 按名称排序

/OE 按扩展名排序/OS 按大小排序/OD......./W 采用宽列表格式)

linux中dir命令参数不区分大小写,支持多参数。

DIR返回的就是指向DIR结构体的指针.即获取路径。

Linux dir 命令和 ls 命令功能类似,用以查看目录、文件权限等详细信息。

DIR结构体的定义:

1. struct __dirstream

2. {

3. void *__fd;

4. char *__data;

5. int __entry_data;

6. char *__ptr;

7. int __entry_ptr;

8. size_t __allocation;

9. size_t __size;

10. __libc_lock_define (, __lock)

11. };

12.

13. typedef struct __dirstream DIR;

DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息。函数 DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针,而该指针由以下几个函数使用:

struct dirent *readdir(DIR *dp);...... void seekdir(DIR *dp,long loc);

二.sprintf()

函数功能:把格式化的数据写入某个字符串

函数原型:int sprintf( char *buffer, const char *format [, argument] … );

返回值:字符串长度(strlen)

例子:char* who = "I";char* whom = "CSDN";sprintf(s, "%s love %s.", who, whom); //产生:"I love CSDN. " 这字符串写到s中

sprintf(s, "%10.3f", 3.1415626); //产生:" 3.142"

三.strrchr() 函数的分析

函数原型:extern char * strrchr (const char *s, int c)

参数说明:s为一个字符串的指针,c为一个待查找字符。

所在库名:#include <string.h>

函数功能:查找在s字符串中最后一次出现字符c的位置。

返回说明:如果str中存在字符ch,返回出现ch的位置的指针;否则返回NULL。

说明:

str 必要参数。指定需要进行搜索的字符串(字符串指针)

c 必要参数。指定需要查找的字符对象。如果是一个数字,那么他将搜索与这个数字对应的ASCII值相匹配的字符

strrchr()函数源码:

char * strrchr (const char *s, int c)

{

register const char *found, *p;

c = (unsigned char) c;

//如果查找的字符是结束符,直接用strchr 函数返回结束符号的位置。

if (c == '/0')

return strchr (s, '/0');

//返回值(查找的字符地址)赋初值,很重要。

found = NULL;

//从当前字符串超找字符c,并将返回指针赋给p,如果p不等于NULL,则执行循环。

//如果p等于NULL,说明已查找整个字符串,退出循环。

while ( (p = strchr (s, c)) != NULL )

{

//暂存查找到的字符地址。

found = p;

//截取已经查找过的字符串(将返回地址p的下一个字符地址作为字符串开头)。

s = p + 1;

}

//如果没有找到字符,则不会执行循环,found返回初值NULL。

//如果找到字符,返回p赋给found的指针地址。

return (char *) found;

}

函数举例:

#include <string.h>

#include <stdio.h>

void main()

{

char * pCh = "www.inkcool.com";

char * pFind = strrchr(pCh, '.');

if ( pFind != NULL)

{

printf("%s/n", pFind); //可以直接printf(pFind);printf("/n");左边的表达式是合二为一的表达方法;

}

}

返回结果是:.com //注意,有'.'而不是只返回com

四.stat(str,&info):stat获取文件信息,str是文件名,info是文件地址

S_ISDIR是判断某文件是否为目录文件

S_ISDIR 只是一个 macro(宏)而已。

类型 和特定的 权限 进行 & 运算,判断结果是否为特定的值。

这么说,若为所判断的值,则结果为1(真),若不为所判断的值,则结果为0(假)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: