您的位置:首页 > 文旅 > 旅游 > 【操作系统】操作系统实验04-文件系统扩展

【操作系统】操作系统实验04-文件系统扩展

2024/12/23 22:28:03 来源:https://blog.csdn.net/weixin_52553215/article/details/139799938  浏览:    关键词:【操作系统】操作系统实验04-文件系统扩展

题目要求:

对【程序5_9】进行扩展,要求参数为目录名,且其下至少有三层目录,分别用深度遍历及广度遍历两种方法对此目录进行遍历,输出此目录下所有文件的大小及修改时间。

1. 程序代码(注意程序格式)

1)深度优先遍历

1.#include <unistd.h> 
2.#include <stdio.h>
3.#include <stdlib.h> 
4.#include <errno.h> 
5.#include <sys/types.h> 
6.#include <sys/stat.h> 
7.#include <dirent.h> 
8.#include <time.h> 
9.#include <string.h>
10.#include <ctype.h>
11.
12.static int get_file_size_time(const char *filename){ 
13.	struct stat statbuf; 
14.	if(stat(filename,&statbuf) == -1){ //取 filename 的状态
15.		printf("Get stat on %s Error:%s\n", filename, strerror(errno)); 
16.		return(-1); 
17. 	} 
18.	if(S_ISDIR(statbuf.st_mode)){//判断是否是目录文件
19.		printf("%s:\n", filename);	
20.		return(1);
21.	}	 
22. 	if(S_ISREG(statbuf.st_mode)) //判断是否是普通文件
23.		printf("%s size: %ld bytes modifiedat: %s",filename,statbuf.st_size,ctime(&statbuf.st_mtime)); //输出文件的大小和最后修改时间
24.	return(0); 
25.}
26.
27.void circulation(char *argv){
28.	DIR *dirp; 
29.	if((dirp = opendir(argv)) == NULL){ //打开目录,将打开的目录信息放至 dirp 中,若为空,则打开失败
30.  		printf("Open Directory %s Error: %s\n", argv, strerror(errno)); 
31.		exit(1); 
32. 	}
33.	struct dirent *direntp; 
34.	char path[1024];
35.		
36.	while((direntp = readdir(dirp)) != NULL){
37. 		memset(path, 0, 1024);
38. 		strcpy(path, argv);
39. 		strcat(path, "/");
40. 		strcat(path, direntp -> d_name);
41. 		int ret = 0;
42. 		if(strcmp(direntp->d_name,".") != 0 && strcmp(direntp->d_name,"..") != 0){
43. 			ret = get_file_size_time(path);
44. 		}
45. 		if(ret == -1) //读取 dirp 目录下文件,直到出错或结束,退出
46. 			break;
47. 		if(ret == 1){
48. 			circulation(path);
49.		}
50.	}
51.	closedir(dirp);
52.} 
53.
54.int main(int argc,char **argv){ 
55.	int stats; 
56. 	if(argc != 2){ //判断输入是否为两个参数
57.  		printf("invalid input"); 
58.		exit(1); 
59.	} 
60. 	if(((stats = get_file_size_time(argv[1])) == 0) || (stats == -1))
61. 		exit(1); //若 argv[1]为文件(输出文件大小和最后修改时间)或者 stats 错误,都退出
62. 	
63.	circulation(argv[1]);//深度优先遍历 
64. 	 
65. 	exit(1); 
}

2)广度优先遍历

1.#include <unistd.h> 
2.#include <stdio.h>
3.#include <stdlib.h> 
4.#include <errno.h> 
5.#include <sys/types.h> 
6.#include <sys/stat.h> 
7.#include <dirent.h> 
8.#include <time.h> 
9.#include <string.h>
10.#include <ctype.h>
11.#include <queue>
12.#include <string>
13.#include <cstring>
14.
15.using namespace std;
16.
17.static int get_file_size_time(const char *filename){ 
18.	struct stat statbuf; 
19.	if(stat(filename,&statbuf) == -1){ //取 filename 的状态
20.		printf("Get stat on %s Error:%s\n", filename, strerror(errno)); 
21.		return(-1); 
22. 	} 
23.	if(S_ISDIR(statbuf.st_mode)){//判断是否是目录文件
24.		printf("%s:\n", filename);	
25.		return(1);
26.	}	 
27. 	if(S_ISREG(statbuf.st_mode)) //判断是否是普通文件
28.		printf("%s size: %ld bytes modifiedat: %s",filename,statbuf.st_size,ctime(&statbuf.st_mtime)); //输出文件的大小和最后修改时间
29.	return(0); 
30.}
31.
32.void circulation(char *argv){	
33.	struct dirent *direntp; 
34.	char path[1024];
35.	
36.	queue<string> q;
37.	q.push(argv);
38.	while(!q.empty()){
39.		string temp = q.front();
40.		q.pop();
41.		DIR *dirp; 
42.		if((dirp = opendir(temp.c_str())) == NULL){ //打开目录,将打开的目录信息放至 dirp 中,若为空,则打开失败
43.  			printf("Open Directory %s Error: %s\n", temp, strerror(errno)); 
44.			exit(1); 
45. 		}
46.		while((direntp = readdir(dirp)) != NULL){
47. 			memset(path, 0, 1024);
48. 			strcpy(path, temp.c_str());
49. 			strcat(path, "/");
50. 			strcat(path, direntp -> d_name);
51. 			int ret = 0;
52. 			if(strcmp(direntp->d_name,".") != 0 && strcmp(direntp->d_name,"..") != 0){
53. 				ret = get_file_size_time(path);
54. 			}
55. 			if(ret == -1) //读取 dirp 目录下文件,直到出错或结束,退出
56. 				break;
57. 			if(ret == 1){
58. 				q.push(path);
59.			}
60.		}
61.		closedir(dirp);		
62.	}	
63.} 
64.
65.int main(int argc,char **argv){ 
66.	int stats; 
67. 	if(argc != 2){ //判断输入是否为两个参数
68.  		printf("invalid input"); 
69.		exit(1); 
70.	} 
71. 	if(((stats = get_file_size_time(argv[1])) == 0) || (stats == -1))
72. 		exit(1); //若 argv[1]为文件(输出文件大小和最后修改时间)或者 stats 错误,都退出
73. 	
74.	circulation(argv[1]);//广度优先遍历 
75. 	 
76. 	exit(1); 
}

2. 运行结果截图

目录文件格式如图:

1)深度优先遍历

2)广度优先遍历

3. 总结

实现方法:

深度优先遍历:利用递归的思想,处理完当前节点后,判断此节点是否为目录节点(以此判断是否有子节点);若是,则先递归处理该节点,实现深度优先遍历;若不是,则不做处理。

广度优先遍历:利用队列存储当前目录下的子目录,当当前层遍历完后,从队列中取出头结点,对下一层文件进行遍历,以此规律实现广度优先遍历。

实验中遇到的问题与解决方法:

问题1:(深度优先遍历程序)运行程序,结果出现了无限循环的问题。

解决方法:最终发现是因为每个目录下默认有”.”与”..”的隐藏目录文件,因此递归时会无限递归本身以及上级目录。加入strcmp(direntp->d_name,".") != 0 && strcmp(direntp->d_name,"..") != 0判断条件得以解决问题。

问题2:(广度优先遍历程序)虽然加了<queue>头文件,程序编译过程中却出现如下报错:

解决方法:若要使用queue声明变量要引入std命名空间(using namespace std;)。

问题3:(广度优先遍历程序)程序编译过程中出现如下报错:

解决方法:原因是temp变量是string类型的,与函数需要的变量类型不一致。c_str()函数可以将const string*类型转化为const char*类型,将temp替换成temp.c_str()即可解决此问题。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com