1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 《Linux编程》作业 ·003【文件I/O操作】

《Linux编程》作业 ·003【文件I/O操作】

时间:2022-05-07 09:19:42

相关推荐

《Linux编程》作业 ·003【文件I/O操作】

注:前言、目录见 /qq_44220418/article/details/108428971

友情提醒:仅供参考理解,请勿直接复制粘贴

友情提醒:仅供参考理解,请勿直接复制粘贴

友情提醒:仅供参考理解,请勿直接复制粘贴

文章目录

第一题第二题第三题第四题

第一题

简述Linux文件系统中的目录和inode节点在文件访问中的作用?硬链接和软链接有何区别?

目录文件中存储了该目录下的文件的索引信息。如果想要找到某个文件,首先需要找到这个文件所在目录的目录文件。

文件的主要属性信息都存放在inode节点中,Linux用inode号来识别不同的文件。

一个文件和另一个文件指向同一个inode节点,则称之为硬链接;一个文件的内容存储的是另一个文件的路径,则称之为软链接。

硬链接和软链接最明显的区别在于:

删除硬链接指向的其中一个文件后,由于只是将inode节点的链接数减少了111,仍有文件指向该inode节点,仍能正常访问其他相同inode节点的文件。删除软链接指向的源文件后,读取链接文件则会报错No such file or directory

第二题

编写C程序,完成将键盘输入的一组整数递减排序后输出到指定的磁盘文件中

/** 因为题目说键盘输入一组数,没有说怎么停止* 那我可以有以下三种解读:* ① 数据是一行字符串,读取后自行切割转换* ② 自己拓展——输入-999结束* ③ 自己拓展——先输入数据个数,再输入个数* 显然后②③自己拓展虽然好实现,但感觉还是①的理解最符合题目的本意* */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#define N 1000// 假定输入的整数个数少于1000#define I_N 10// 假定输入的整数长度少于10char *str = NULL; // 接受输入的C式字符串int a[N]; // 存储整数的数组int cnt = 0; // 存储输入整数的个数size_t len = 0;// 切割字符串长度参数char *part; // 存储切割部分的字符串char num[N]; // 存储要每次写入的内容字符串// 比较函数int cmp(const void*a, const void*b){return *(int*)(b)-*(int*)(a);}int main(int argc, char *argv[]){// 读取数组字符串scanf("%s", str);getline(&str, &len, stdin);char* buff = str;// 用strsep函数切割C式字符串while ((part = strsep(&buff, " ")) != NULL)a[cnt++] = atoi(part); // 用atoi函数将C式字符串转换为int并存入数组// 回收getline由于str为NULL而自动动态分配的空间free(str);// 用qsort函数降序排列qsort(a, cnt, sizeof(int), cmp);// 将数组写入文件int fd = open("res-2.txt", O_RDWR | O_CREAT | O_TRUNC, 0755);if (fd != -1){for (int i = 0; i < cnt; ++i){int bytes = sprintf(num, "%d ", a[i]);write(fd, num, bytes);}write(fd, "\n", strlen("\n"));}close(fd);return 0;}

示例截图

第三题

编写程序,可以将两个有序的数据子文件归并到一个有序的结果文件中

(如递减排序,可利用上一题生成整型数据文件)

/** 和上面第二题的方法一样* 只要从两个文件读取出两组输入字符串,拼接成一个字符串* 就划归到第二题了* */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#define N 1000// 假定两个文件总的输入的整数个数少于1000#define I_N 10// 假定两个文件总的输入的整数长度少于10#define LEN 500// 假定两个文件每个的输入的整数字符串长度少于500char str1[LEN];// 文件1读取的输入字符串char str2[LEN];// 文件2读取的输入字符串char str[2 * LEN] = ""; // 接受输入的C式字符串int a[N]; // 存储整数的数组int cnt = 0; // 存储输入整数的个数size_t len = 0;// 切割字符串长度参数char *part; // 存储切割部分的字符串char num[N]; // 存储要每次写入的内容字符串// 比较函数int cmp(const void*a, const void*b){return *(int*)(b)-*(int*)(a);}int main(int argc, char *argv[]){// 读取两个文件的数组字符串int fd1 = open("data1.txt", O_RDONLY);int fd2 = open("data2.txt", O_RDONLY);if (fd1 == -1 || fd2 == -1){perror("文件打开有误");exit(1);}read(fd1, str1, sizeof(str1) - 1);read(fd2, str2, sizeof(str2) - 1);close(fd1);close(fd2);// 去掉文尾的换行和空格拼接成为一个字符串str1[strlen(str1) - 1] = '\0';str2[strlen(str2) - 2] = '\0';strcat(str, str1);strcat(str, str2);char* buff = str;// 用strsep函数切割C式字符串while ((part = strsep(&buff, " ")) != NULL)a[cnt++] = atoi(part); // 用atoi函数将C式字符串转换为int并存入数组// 用qsort函数降序排列qsort(a, cnt, sizeof(int), cmp);// 将数组写入文件int fd = open("res-3.txt", O_RDWR | O_CREAT | O_TRUNC, 0755);if (fd == -1){perror("文件打开有误");exit(1);}for (int i = 0; i < cnt; ++i){int bytes = sprintf(num, "%d ", a[i]);write(fd, num, bytes);}write(fd, "\n", strlen("\n"));close(fd);return 0;}

示例截图

第四题

编写一个程序listDIR.c

当执行listDIR sub1时,可以将指定sub1目录下的所有文件信息,按文件名、类型、长度进行列表

(子目录中的文件不再显示,类型标识是权限码的第一个字符,符号链接文件还需显示inode节点号)

思路一:得到运行参数的路径后,将其置为以/结尾,需要具体文件路径时再进行拼接

/** 考点:目录操作、文件属性获取* */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#define LEN 1000 // 假定路径字符串长度少于1000char path[LEN] = "";char path_tmp[LEN] = "";const char none[LEN] = "";// 获取文件类型对应字符char getType(__mode_t mode){if (S_ISDIR(mode)) return 'd';if (S_ISCHR(mode)) return 'c';if (S_ISBLK(mode)) return 'b';if (S_ISSOCK(mode)) return 's';if (S_ISFIFO(mode)) return 'p';if (S_ISLNK(mode)) return 'l';return '-';}int main(int argc, char *argv[]){// 如果没有传入参数,则默认选择当前目录if (argc < 2)strcpy(path, ".");elsestrcpy(path, argv[1]);// 格式化path,使之以`/`结尾if (path[strlen(path) - 1] != '/')strcat(path, "/");// 打开指定目录DIR * dir_ptr = opendir(path);struct dirent * dir;if (dir_ptr == NULL){perror("目录打开失败");exit(1);}// 读取每一个目录项,构造stat获取其属性struct stat buf;printf("%-30s%-20s%-30s%-30s\n", "filename", "type", "length(Byte)", "inode_num");printf("----------------------------------------------------------------------------------------------------\n");while ((dir = readdir(dir_ptr)) != NULL){// 构造完整的相对于参数目录的路径strcpy(path_tmp, none);strcat(path_tmp, path);strcat(path_tmp, dir->d_name);// 构造stat,读取文件属性并说出int res = lstat(path_tmp, &buf);if (res == 1){perror("读取文件属性失败");exit(2);}char ch = getType(buf.st_mode);if (ch == 'l')printf("%-30s%-20c%-30ld%-30ld\n", dir->d_name, ch, buf.st_size, buf.st_ino);elseprintf("%-30s%-20c%-30ld\n", dir->d_name, ch, buf.st_size);}return 0;}

思路二:得到运行参数的路径后,直接将当前工作目录置为该路径,然后在当前目录.下直接操作

/** 考点:目录操作、文件属性获取* 【缺陷已修正】:* 原来直接将参数目录用chdir切换工作目录,如果目录不存在并不会出错而停止运行* 现在已加上在chdir之前通过access判断目录是否存在* */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#define LEN 1000 // 假定路径字符串长度少于1000char path[LEN] = "";// 获取文件类型对应字符char getType(__mode_t mode){if (S_ISDIR(mode)) return 'd';if (S_ISCHR(mode)) return 'c';if (S_ISBLK(mode)) return 'b';if (S_ISSOCK(mode)) return 's';if (S_ISFIFO(mode)) return 'p';if (S_ISLNK(mode)) return 'l';return '-';}int main(int argc, char *argv[]){// 如果没有传入参数,则默认选择当前目录if (argc < 2)strcpy(path, ".");elsestrcpy(path, argv[1]);// 判断目录是否存在if (access(path, F_OK) == -1){sprintf(error, "错误:目标目录 %s 不存在", path);perror(error);exit(1);}// 切换当前工作目录int res = chdir(path);// 打开指定目录DIR * dir_ptr = opendir(".");struct dirent * dir;if (dir_ptr == NULL){perror("目录打开失败");exit(1);}// 读取每一个目录项,构造stat获取其属性struct stat buf;printf("%-30s%-20s%-30s%-30s\n", "filename", "type", "length(Byte)", "inode_num");printf("----------------------------------------------------------------------------------------------------\n");while ((dir = readdir(dir_ptr)) != NULL){// 构造stat,读取文件属性并说出int res = lstat(dir->d_name, &buf);if (res == -1){perror("读取文件属性失败");exit(2);}char ch = getType(buf.st_mode);if (ch == 'l')printf("%-30s%-20c%-30ld%-30ld\n", dir->d_name, ch, buf.st_size, buf.st_ino);elseprintf("%-30s%-20c%-30ld\n", dir->d_name, ch, buf.st_size);}return 0;}

示例截图

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。