文章目录

  • ​​1.仿写cp命令的部分功能(编写mycp程序)​​
  • ​​2.命令行参数​​
  • ​​3.打开文件(POSIX API)​​
  • ​​3.读取文件(POSIX API)​​
  • ​​4.写文件(POSIX API)​​
  • ​​5.关闭文件(POSIX API)​​
  • ​​6.文件定位(POSIX API)​​
  • ​​7.错误处理​​
  • ​​8.仿写cp命令的部分功能的进阶要求​​

1.仿写cp命令的部分功能(编写mycp程序)

  • 要求:
(1)将源文件复制到另外一个文件(将test1.text复制成test2.txt)
[test@linux test]$ ./mycp /home/test1.txt /usr/test2.txt

(2)将源文件复制到另外一个目录(将test1.txt复制到/tmp目录)
[test@linux test]$ ./mycp /home/test1.txt /tmp

源文件路径和目标文件路径通过命令行参数来指定
  • 程序流程

2.命令行参数

  • 命令行参数:在命令(也是可执行文件名) 后,传递进入程序的
参数(字符串形式)
cp命令:根据接收的命令行参数进行复制
✓ cp /usr/local/src/main.c /root/main.c(文件到文件复制)
✓ cp /usr/local/src/main.c /root (文件到目录复制)
✓ cp –r /usr/local/src /root(-r 递归复制,用于目录到目录的复制)

权限不够的情况,采用sudo cp XX XX的方式。
sudo,在linux中输入sodu就是调用这个程序提升权限
  • 程序命令行参数的启动流程:
操作系统启动C程序->调用C启动例程->例程获取命令行参数->main函数接收

int main(int argc, char* argv[])
argc:整型,输入参数个数
argv:字符串数组,存储命令行参数
  • eg1:
root@ubuntu:/root# ./pg I am NEW
argv[1]:I
argv[2]:am
argv[3]:NEW
  • eg2:
#include <stdio.h>
int main(int argc ,char* argv[])
{
int i;
for (i=0;i<argc;i++)
{
printf("Argv %d is %s.\n", i, argv[i]);
}
return 0;
}

将左边代码编译为hello.o
命令行中执行两种命令:
./hello.o
./hello.o aaa bbb ccc ddd eee

(实验2)文件IO实验_命令行参数

argv[0]->可执行文件名; 
argv[1]-argv[5] ->命令行参数
以字符串的形式传递(空格作为命令行参数之间的分隔)

3.打开文件(POSIX API)

头文件: fcntl.h
函数: int open( const char *pathname, int oflag, …);
作用: 打开或者创建一个文件,返回值是打开文件的文件描述符

pathname:文件的路径
oflag:打开文件的方式
…:变参创建新文件时使用

Oflag值 含义
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读、写打开

Oflag值 含义
O_APPEND 每次写都加到文件尾
O_CREAT 若此文件不存在则创建它,此时需要第三个参数mode,
该参数约定了所创建文件的权限,计算方法mode&~umask
O_EXCL 如同时指定了O_CREAT,此指令会检查文件是否存在,
若不存在则建立此文件;若文件存在,此时将出错
O_TRUNC 如果此文件存在,并以读写或只写打开,则文件长度0

3.读取文件(POSIX API)

头文件: unistd.h
函数: ssize_t read( int filedes, void *buf, size_t nbytes);
作用:从打开的文件中读数据

返回值:
✓ 成功: 返回实际读取的字节数(例外情况:读普通文件,未到要求的字节数前
就到达文件末尾,此时返回字节数不等于要求字节数)
✓ 出错: 返回-1, 原因: 磁盘满、权限问题、超文件长度限制

注: 读操作完成后,文件的当前位置变为之前位置+实际读取字节数

4.写文件(POSIX API)

头文件: unistd.h
函数: ssize_t write( int filedes, const void *buf, size_t nbytes);
作用: 向打开的文件中写数据

返回值:
✓ 成功: 写入成功返回实际写入字节数
✓ 出错: 返回-1, 原因: 磁盘满、权限问题、超文件长度限制

注: 写操作完成后,文件的当前位置变为之前位置+实际写入字节数

5.关闭文件(POSIX API)

头文件: unistd.h
函数: int close(int filedes)
作用: 关闭打开的文件

返回值:
✓ 成功: 返回0
✓ 出错: 返回-1

注: 关闭后,不能通过该文件描述符操作该文件

6.文件定位(POSIX API)

头文件: unistd.h
函数: off_t lseek( int filedes, off_t offset, int whence);
作用:设置或查询文件当前位置

✓每个打开文件都有一个“文件当前位置”
✓打开文件时默认当前位置为文件头(0)
✓打开时如指定O_APPEND选项,则当前位置变为文件尾(文件长度)
✓回忆:读写操作完成后文件的当前位置变为之前位置+实际读写字节数

文件定位lseek函数的参数whence及offset(offset可正可负)
✓ whence=SEEK_SET, 文件当前位置=文件头+offset(字节)
✓ whence=SEEK_CUR, 文件当前位置=文件当前位置+offset(字节)
✓ whence=SEEK_END, 文件当前位置=文件尾+offset(字节)

(实验2)文件IO实验_API_02

7.错误处理

调用POSIX API会发生错误,需要定位产生问题的更具体原因
系统错误码: POSIX规范定义的记录系统错误的标准码,
使用方式: 通过全局变量errorno获取该错误码,记录最后一次错误
✓ extern errorno
✓ 头文件: errorno.h

(1)将错误码转换为易读的错误信息:
函数1: char *strerror(int errnum);
头文件: string.h
作用: 将errnum转换为对应错误信息(字符串)

(2)函数2: void perror(const char * msg);
头文件: stdio.h
作用: 先输出msg字符串,然后输出当前errorno对应错误信息

(实验2)文件IO实验_#include_03

  • eg:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>//引入头文件
extern errno;//引入变量

int main(int argc,char *argv[])
{
int i=open("/usr/src/s.t", 0);
perror([argv[0]]);
printf(strerror(error));
printf("\n");
return 0;
}

编译为error.o
使用./error.o运行
得到如下结果:

(实验2)文件IO实验_命令行参数_04

8.仿写cp命令的部分功能的进阶要求

  • 实现基本功能基础上,针对特殊情况及边界条件,进行流程完善与优化:
    ✓目标文件存在时,提示“是否覆盖” or“是否合并”等提示信息,并实现覆盖或者目标文件与源文件合并的功能(目标文件尾部追加写入)
    ✓源文件不存在时给出错误提示信息
    ✓源文件是目录时给出错误提示信息
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>//引入头文件
extern errorno;//引入变量

int main(int argc, char *argv[])
{
int fd_src,fd_dst;
char *buf;
int fd_src_length;
int n,m;
if (-1==(fd_src=open(argv[1],O_RONLY)))
perror(argv[1]);

if (-1==(fd_dst=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC, 0666)))
perror(argv[2]);

if (-1==(fd_src_length=lseek(fd_src,0, SEEK_END)))
exit(-1);
buf=(buf *)malloc(long (fd_src_length+1));
if (buf==NULL)
printf("malloc error");

memset(buf,'0',fd_src_length+1);

if ((n=read(fd_src, buf, fd_src_length))>0)
{
printf("buf:%d", strlen(buf));
if (n!=(m=write(fd_dst, buf, n)))
printf("write error");
exit(-1);
}

close(fd_src);
close(fd_dst);
free(buf);



return 0;
}