实现cp 复制指令
cp指令: 复制一个文件,并对复制后的文件进行重命名;
用法:
***@Embed_Learn:~$ cp demo5.c demo6.c //复制一个demo5.c 为demo6,c
除了名字不一样之外,demo6.c和demo5.c的内容一样。
我们利用write/read 函数来写一个小应用来实现和cp 指令一样的效果。
C语言参数输入
在正式编程之前,我们应该要熟悉C语言的参数输入,也就是当运行程序的时候,如何输入文件名,即上面提到cp 指令之后跟着的 demo5.c 和 demo6.c 。我们所写出来的程序运行的时候,也应该是类似cp 一样的操作,
比如:./a.out demo5.c demo6.c 。
而demo5.c 和 demo6.c 该怎么输入呢?其实很简单,给main函数传递参数就行了,我们可以写一个测试程序来看看:
#include <stbio.h>
int main(int argv,char **argc)//传递参数,argv为参数个数 **argc为二级指针,即指针数组
{
if(rgv!=3){ //判断输入是否是三个
printf("params error!");//如果不是则提示错误
exit(-1); //结束程序
}
printf("params argv:%d\n",argv);//打印参数个数
printf("params argc1:%s\n",argc[0]);//第一个参数
printf("params argc2:%s\n",argc[1]);//第二个参数
printf("params argc3:%s\n",argc[2]);//第三个参数
return 0;
}
运行结果如下:
可以看到,运行 ./a.out Src Der 后正确输出了这三个参数,至此我们就可以开始编程了。
编程思路
详细代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int fd_Src,fd_Des;//定义文件描述符
char *Scr_Buf=NULL;//定义文件内容缓存区
if(argc!=3){
printf("params error!\n");
exit(-1);
}
fd_Src=open(argv[1],O_RDWR);//打开已经存在的文件
int Src_Size=lseek(fd_Src,0,SEEK_END);//读取该文件的大小
lseek(fd_Src,0,SEEK_SET); //把光标设置到文件头部,方便下次读取
Scr_Buf=(char *)malloc(sizeof(char)*Src_Size+8);//为指针分配合适的内存空间
int n_read=read(fd_Src,Scr_Buf,Src_Size); //读取argv[1]的内容
// ssize_t write(int fd, const void *buf, size_t count);
fd_Des=open(argv[2],O_RDWR|O_CREAT,0600); //打开并创建一个新的文件
int n_write=write(fd_Des,Scr_Buf,n_read); //把读取的内容写入刚刚创建的文件中
if(n_write!=-1){ //判断是否写入失败
printf("write %d byte to file\n",n_write);//打印写入数据的大小
}
close(fd_Src|fd_Des); //关闭两个文件
return 0;
}
运行结果:
可以看到,我们在运行./mycp demo4.c new1.c后,看到打印:wrie 909 byte to file,证明我们成功的写入了,程序运行正确。
实现修改配置文件参数
功能说明: 有一个 .config 的配置文件,里面有如下配置信息:
NAME=6
SPEED=10
LENG=36
TIME=75
编写一个能够实现修改某个参数的值的小应用,比如运行 ./rev Test.config NAME 36 就是把Test.config中的NAME 的值改为36。
编程思路
在编程过程中需要注意需要修改的参数的地址不能改变,否则会破坏配置文件:
首先创建一个名为Test.config 的文件,在文件写一些参数;就拿上面所说的参数为例。
Test.config中的原始内容如下:
详细代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int fd_Src,i;
char *Scr_Buf=NULL;
char *p=NULL;
if(argc!=4){
printf("params error!\n");
exit(-1);
}
fd_Src=open(argv[1],O_RDWR,0600);//打开一个配置文件
int Src_Size=lseek(fd_Src,0,SEEK_END);//计算文件的大小
lseek(fd_Src,0,SEEK_SET); //光标定位到文件头
Scr_Buf=(char *)malloc(sizeof(char)*Src_Size+8);//分配适合的空间
int n_read=read(fd_Src,Scr_Buf,Src_Size);//读取文件内容
printf("read:%s",Scr_Buf);//打印读取信息
p=strstr(Scr_Buf,argv[2]);//查找需要修改的参数
if(p==NULL){
printf("no found!\n");//如果找不到,则打印错误信息
exit(-1); //然后结束程序
}
p=p+strlen(argv[2])+1;//指针根据参数来移位,+1是 为了移到“=”的后面
*p='\0';//“=”的后面的值全部清掉
int j=(int)strlen(argv[3]);//获取修改值得字符串长度
for(i=0;i<j;i++){
*p=*argv[3]; //开始赋值
argv[3]++; //赋值后,往后位移一位
p++; //p 也应该往后移
}
lseek(fd_Src,0,SEEK_SET);//光标重新移到文件头,这样可以覆盖原来的信息
int n_write=write(fd_Src,Scr_Buf,strlen(Scr_Buf));//开始写入
printf("write:%s\n",Scr_Buf);//打印写入的信息
close(fd_Src);//关闭文件
return 0;
}
需要注意的是,在赋值的时候,我们用的是取内容运算符 ,而不是直接 p=argv[3] ,这是因为指针p的地址是和Src_Buf 的其中一个参数的地址是一样的,如果我们 p=argv[3] 的话,会改变p的地址,造成Test.config的配置信息没有改变,就达不到我们的目的 。而使用 *p的话,就不会改变地址,改的其中的内容而已,这样就连带Scr_Buf的同地址的内容一起修改了。
运行结果:
