本节课的主要内容是:文件读写。在C语言中,我们可以使用fopen,fclose等函数进行文件操作。但下放到操作系统层次,就是一些文件的系统调用了。本节的主要内容也就是介绍下与文件相关的一些系统调用。
我发现自己写的,远没有老师提供的资料全面。所以在这里,我就直接用图片说明内容啦~
以上就是本节的主要理论学习内容,下面还有三个作业进行巩固,我就把自己的答案附在上面,可能不是很简洁,但我后面会慢慢的进行修改完善滴~
一、练习一:
#include<stdio.h>
int main(int argc, char *argv[]) {
// argc的参数计算是从头开始的,所以使用./a.out也算一个,真正的参数是从索引1开始
for (int i=1; i<argc; i++) {
// argv是指针数组,使用的时候要注意。因为这里面测试的样例是字符,所以用%s和%c都可以
//但是puts不可以,puts输出的只能是常量字符串
printf("%s ", argv[i];
printf("%c ", *(argv[i]));
// puts(argv)
}
printf("\n");
}
写这个的时候,遇到这样一个直接的问题:不定参数如何输入?原来在main函数中,它的参数列表就可以作为它的不定输入。设定argc和argv。其中argc代表输入参数个数,argv代表输入参数内容。更为详细的内容的可以参考:https://www.cnblogs.com/x_wukong/p/5326557.html
还有就是,输出的时候会出现一种这样的情况:输出的最后总是有个%,这是怎么回事呢?其实这个就是Linux下一个习惯,提示输出到了最后。如果不想要的话,可以在最后增加一个换行符(这个问题困扰了我很久,感谢https://segmentfault.com/q/1010000004687388)
二、练习二:
思路:因为文件内内容长度的不确定性,不想数据库那样有严格的结构体。这里利用read读文件如果到文件底会返回0做判断,同时read返回值就是文件读出来的字节count改变偏移量offset。以offset作为lseek偏移数,不断累加,进行读取。源码如下:
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
// 输出错误提示信息
void panic(char *message) {
perror(message);
exit(EXIT_FAILURE);
}
int fd;
struct record {
char content[100];
};
// 打开文件,使用系统调用open
void db_open(char *path) {
mode_t mode = 0777;
fd = open(path, O_RDWR | O_APPEND | O_CREAT, mode);
if (fd < 0)
panic("open");
}
// 关闭文件,使用系统调用close
void db_close() {
close(fd);
}
// 文件内容输出,使用系统调用lseek,read
void db_dump() {
int offset = 0;
while (1) {
lseek(fd, offset, SEEK_SET);
struct record record;
int count = read(fd, &record, 100);
if (count == 0)
break;
else {
offset += count;
printf("%s\n", record.content);
}
}
}
int main(int argc, char *argv[]) {
db_open(argv[1]);
db_dump();
db_close();
return 0;
}
效果图如下:
三、练习三:
思路:读取文件部分与问题二一致,同时增加写文件部分,文件名为第二个传入的参数值。源代码如下(代码是有问题的,问题在下面说):
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
// 输出错误信息
void panic(char *message) {
perror(message);
exit(EXIT_FAILURE);
}
int fd_source;
int fd_target;
struct record {
char content[100];
};
// 打开源文件
void db_open_source(char *path) {
mode_t mode = 0777;
fd_source = open(path, O_RDWR | O_APPEND | O_CREAT, mode);
if (fd_source < 0)
panic("open_source");
}
// 生成目标文件
void db_open_target(char *path) {
mode_t mode = 0777;
fd_target = open(path, O_RDWR | O_APPEND | O_CREAT, mode);
if (fd_target < 0)
panic("open_target");
}
void db_close() {
close(fd_source);
close(fd_target);
}
// 目标文件内容填入(尾部填充)
void db_append(char *content) {
struct record record;
strcpy(record.content, content);
int count = write(fd_target, &record, 100);
if (count < 0)
panic("write");
}
// 从源文件读,向目标文件写
void db_dump() {
int offset = 0;
int num = 0;
while (1) {
lseek(fd_source, offset, SEEK_SET);
struct record record;
int count = read(fd_source, &record, sizeof(record));
if (count == 0)
break;
else {
offset += count;
db_append(record.content);
printf("%s", record.content);
}
}
printf("\n");
}
int main(int argc, char *argv[]) {
db_open_source(argv[1]);
db_open_target(argv[2]);
db_dump();
db_close();
return 0;
}
问题:这个代码在执行的时候,在终端输出的是没有问题的。但写入到目标文件中的内容,最终会出现一行乱码(长度恰好是100),如下图:
有问题是好事,等我解决了,再补充说明吧~
呼,第二次实验结束,继续加油!
因作者水平有限,如有错误之处,请在下方评论区指出,谢谢各位!