代码实践内容总结
cp
用来复制文件,函数大致步骤:
打开源文件
创建目标文件
针对源文件
把源文件读入缓冲区
把缓冲区内容写入目标文件
关闭源文件和目标文件
cp命令使用格式:cp src dst
运行以下命令:实现复制操作
操作之后cp1.c里面的内容被更改:
代码分析:
#include <stdio.h>//标准输入输出
#include <stdlib.h>//C标准函数库
#include <unistd.h>//Unix类系统定义符号常量
#include <fcntl.h>//定义了很多宏和open,fcntl函数原型
#define BUFFERSIZE 4096//定义存储器容量
#define COPYMODE 0644//定义复制的长度
void oops(char *, char *);
int main(int argc, char *argv[])
{
int in_fd, out_fd, n_chars;//三个描述符值
char buf[BUFFERSIZE];//存储器位置
if (argc != 3) {//检查argc的值是否为三,如果不是,返回标准错误
fprintf(stderr, "usage: %s source destination
", *argv);
exit(1);
}
/*检查cp的第一个参数,要复制的文件,用open打开,in_fd为open返回的描述符
如果返回-1,代表打开失败,提示错误*/
if ((in_fd = open(argv[1], O_RDONLY)) == -1)
oops("Cannot open ", argv[1]);
/*检查cp的第二个参数,复制的目的地址,用create在目的地址创建新文件,out_fd为open返回的描述符
如果返回-1,代表创建失败,提示错误*/
if ((out_fd = creat(argv[2], COPYMODE)) == -1)
oops("Cannot creat", argv[2]);
/*cp指令的动作就是读取一个文件的内容到存储器,在新的地址创建空白文件,再从存储器将内容写入新文件。
这里判断复制是否成功:
如果能读取顺利,而读取的位数和写的位数不同,是写错误;
如果读取失败,是读错误。*/
while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
if (write(out_fd, buf, n_chars) != n_chars)
oops("Write error to ", argv[2]);
if (n_chars == -1)
oops("Read error from ", argv[1]);
/*这里执行的是关闭文件的动作,in_fd和out_fd两个文件描述符
所指向的文件只要有一个关闭错误,就提示关闭错误。*/
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);//用来将上一个函数发生错误的原因输出到标准设备(stderr)
exit(1);
}
setecho & echostate
setecho
设置echo值的一个函数,输入yes后,键盘键入命令是可见的,而输入no后,键盘键入命令是不可见的,但是依然是可执行的
输入y(或是以y开头的一串字符),命令可见
否则(即输入不以y开头的字符),命令不可见
echostate
检查键盘键入命令是否可见,是与以上的setecho代码结合起来的
echo is on:命令可见
echo is off:命令不可见
注意这个过程中会有命令不可见的情形,所以很容易运行出错,必须仔细
代码分析setecho:
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#define oops(s,x) { perror(s); exit(x); }
int main(int argc, char *argv[])
{
struct termios info;
if (argc == 1) //后面没有带参数的话就不做任何操作,退出
exit(0);
if (tcgetattr(0,&info)==-1)//tcgetattr函数用于获取与终端相关的参数。参数fd为终端的文件描述符,返回的结果保存在termios 结构体中,这里fd为0,是标准输入。这句用于读取设备属性
oops("tcgettattr", 1);
if ( argv[1][0] == 'y' )//如果运行命令后面的参数第一个字母是“y”,执行“设置打开提示符”的命令
info.c_lflag |= ECHO ;/*打开提示符*/
else//对其它所有的参数都执行“设置隐藏提示符”的命令
info.c_lflag &= ~ECHO ;/*隐藏提示符*/
if ( tcsetattr(0,TCSANOW,&info) == -1 )//将修改后的参数写回设备
oops("tcsetattr",2);
return 0;
}
fileinfo & filesize
fileinfo
可显示文件信息
filesize
可计算文件的字节数
以上两个代码都是先判断是否有错误,有错就打印报错信息,没有就执行功能代码
mode:st_mode 文件的类型和存取的权限
links:st_nlink 连到该文件的硬链接数目,刚建立的文件值为1
user:st_uid 用户ID
group:st_gid 组ID
size:st_size 文件字节数
modtime:st_mtime 最后一次修改时间
name: 输入的文件名
代码分析fileinfo:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
void do_ls(char []);
int main(int argc, char *argv[])
{
/*如果操作数只有1个,表明ls后面没有带参数,默认为当前目录,.表示当前目录。*/
if ( argc == 1 )
do_ls( "." );
/*如果ls后面有参数,就把参数读入argv中。*/
else
while ( --argc ){
printf("%s:
", *++argv );
do_ls( *argv );
}
return 0;
}
/*因为ls和dir功能相近,用dir来实现ls*/
void do_ls( char dirname[] )
{
DIR *dir_ptr;
struct dirent *direntp;
/*如果没有指向的那个地址,报错*/
if ( ( dir_ptr = opendir( dirname ) ) == NULL )
fprintf(stderr,"ls1: cannot open %s
", dirname);
else
{
/*递归的方式来读取*/
while ( ( direntp = readdir( dir_ptr ) ) != NULL )
printf("%s
", direntp->d_name );
closedir(dir_ptr);
}
}
ls
ls老师给了两个代码,第一个实现功能显示当前文件夹内容,第二个在第一个的基础上更加完善,还可显示出文件的详细信息,如读写权限,大小和创建时间等
ls实现的功能:
ls -l:显示文件信息
ls -a:列出文件目录
ls -lu:最后访问时间
ls -s:以块为单位的文件大小
ls -t:按时间排序
ls -F:显示文件类型
文件树
文件和目录被组织成目录树(tree),节点是目录或者文件
目录是一种特殊文件,文件内容就是目录和文件的名字,与utmp类似
与文件不同,目录不会为空
伪代码:
打开目录文件
针对目录文件
读取目录条目
显示文件名
关闭文件目录文件
如下是运行过程:
spwd
列出当前目录
testioctl
获得终端设备的窗口大小
下图一个是我的终端全屏的,一个是还原之后的
who
who也有两个代码,运行的结果是一样的,代码实现的功能是一样的,主要是从UTMP_FILE文件中读取信息到存储器中,然后再用标准输出函数打印到屏幕上,最后关闭文件
who命令是查询当前登录的每个用户,输出包括用户名、终端类型、登录日期及远程主机
who命令是读取/var/run/utmp文件来得到信息的
utmp这个文件,是二进制文件,里面保存的是结构体数组,这些数组是struct utmp结构体的
伪代码:
打开utmp文件
针对文件
读取一条记录
显示记录
关闭文件
如下是运行过程:
视频实践内容记录
代码托管
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 30/30 | |
第二周 | 300/500 | 1/3 | 20/50 | |
第三周 | 100/600 | 1/4 | 20/70 | |
第五周 | 300/900 | 1/5 | 30/100 | |
第六周 | 136/1036 | 1/6 | 20/120 | |
第七周 | 124/1160 | 1/7 | 20/140 | |
第八周 | 0/1160 | 3/10 | 20/160 | |
第九周 | 338/1498 | 1/11 | 25/185 | |
第十周 | 505/2003 | 2/13 | 25/210 |