一.错误

1.检测错误

①函数返回值

1
fopen,malloc函数发生错误,返回NULL

②设置errno

errno为0表示没有错误;非0表示发生了某种错误

2.打印错误信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <errno.h>
#include <string.h>

int main(int argc,char* argv[]){
printf("errno=%d\n",errno); //0
FILE* fp=fopen("a.txt","r");
printf("errno=%d\n",errno); //2
//strerror() 方法会打印errno详细错误信息
printf("%s\n",strerror(errno));
//第一种方法
perror("前缀信息:自动添加到strerror(errno)前面");
//第二种方法
const char* prefix="not_exist.txt";
fprintf(stderr,"%s: %s\n",prefix,strerror(errno));
}

常用方法

1
2
3
#include <error.h>
error(0,errno,"not_exist.txt");
//第一个参数:0->不退出 非0->打印错误信息

二.目录

1.基本操作

①获取当前路径

getcwd

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <unistd.h>

#define MAXSIZE 512
int main(int argc,char* argv[]){
char buf[MAXSIZE];
char* cwd=getcwd(buf,MAXSIZE);
if(cwd==NULL){
error(1,errno,"getcwd");
}
puts(cwd);
}

申请合适大小的空间

1
2
3
4
5
int main(){
char* cwd=getcwd(NULL,0);
puts(cwd);
free(cwd);
}

②改变工作目录

chdir

1
2
3
4
5
6
7
8
9
10
11
#include <unistd.h>

int main(int argc,char* argv[]){
if(argc!=2){
error(1,0,"Usage: %s path",argv[0]);
}
//返回值不为0发生了错误
if(chdir(argv[1])){
error(1,errno,"chdir");
}
}

③创建目录

mkdir

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc,char* argv[]){
if(argc!=3){
error(1,0,"Usage: %s path mode",argv[0]);
}
mode_t mode;
//以八进制的形式解析权限字符串
sscanf(argv[2],"%o",&mode);
if(mkdir(argv[1],mode)){
error(1,errno,"mkdir");
}
}

④删除目录

rmdir

1
2
3
4
5
6
7
8
9
10
#include <unistd.h>

int main(int argc,char* argv[]){
if(argc!=2){
error(1,0,"Usage: %s path",argv[0]);
}
if(rmdir(argv[1])){
error(1,errno,"rmdir");
}
}

2.目录流

①打开目录

1
2
3
4
#include <sys/types.h>
#include <dirent.h>

DIR* opendir(const char* name);

②关闭目录

1
int closedir(DIR* dirp);

③读目录流

1
2
3
#include <dirent.h>
struct dirent* readdir(DIR* dirp);
//如果读到末尾,会返回NULL; 读取失败也会返回NULL,但是会设置errno值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <dirent.h>

int main(int argc,char* argv[]){
if(argc!=2){
error(1,0,"Usage: %s dir",argv[0]);
}
//1.打开目录流
DIR* stream=opendir(argv[1]);
if(!stream){
error(1,errn,"opendir");
}
//2.读取每个目录项
errno=0;
struct dirent* curr;
while((curr=readdir(stream))!=NULL){
printf("d_ino=%lld,d_type=%d,d_name=%s",curr->d_ino,curr->d_type,curr->d_name);
}
if(errno){
error(1,errno,"readdir");
}
//3.关闭目录流
closedir(stream);
}

3.递归打印目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <func.h>
#define MAXSIZE 1024
void dfs_print(const char* path,int width);
int main(int argc,char* argv[]){
//1.参数校验
if(argc != 2){
error(1, 0, "Usage: %s dir", argv[0]);
}
//2.打印根节点
puts(argv[1]);
//3.递归打印每一个目录项
dfs_print(argv[1]);
//4.打印统计信息
printf("\n%d directories, %d files\n", directories, files);
return 0;
}
void dfs_print(const char* path,int width){
DIR* stream=opendir(path);
if(!stream){
error(1, errno, "opendir");
}

errno=0;
struct dirent* curr;
while((curr = readdir(stream)) != NULL){
const char* filename=curr->d_name;
if(filename[0]=='.'){
continue;
}
for(int i=0;i<width;i++){
putchar(' ');
}
puts(filename);
if(curr->d_type==DT_DIR){
directories++;
char subpath[MAXSIZE];
sprintf(subpath,"%s/%s",path,filename);
dfs_print(subpath,width+4);
}else(curr->d_type==DT_REG){
files++;
}
}
if(errno){
error(1, errno, "readdir");
}
closedir(path);
}
类型 含义
DT_DIR 目录
DT_FIFO 管道
DT_LNK 符号链接
DT_REG 普通文件
DT_BLK 块设备
DT_CHR 字符设备