c - Linux C Programming,尝试写:实现FILE系统模仿
问题描述
我正在尝试实现像 fopen、fclose、fputc 和 fgetc 这样的模拟文件系统。
一切都很好,除了写作(关闭时)。
当它使用 myfclose 关闭时,我想将缓冲区中的剩余字符(如果有)写入文件。但它返回错误 -1, Bad file descriptor。
另一方面,如果我在 myfclose 函数中打开并新写入另一个文件,则没有问题。
我不知道它有什么问题。
这是代码:
我的文件.c
#include "mystdio.h"
int main()
{
char c;
MYFILE *fpin, *fpout;
if((fpin = myfopen("a", "r")) == NULL) {
perror("a");
exit(-1);
}
if ((fpout = myfopen("b", "w")) == NULL) {
perror("b"); exit(-1);
}
while((c = myfgetc(fpin)) != EOF) {
myfputc(c, fpout);
}
myfclose(fpin); myfclose(fpout);
}
mystdio.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define BUFSIZE 1024
#define READONLY_MODE 0
#define WRITEONLY_MODE 1
typedef struct {
int fd;
char mode;
char buf[BUFSIZE];
int length;
int offset;
} MYFILE;
MYFILE *myfopen(char *file, char *mode);
int myfclose(MYFILE *fp);
char myfgetc(MYFILE *fp);
void myfputc(char c, MYFILE *fp);
MYFILE *myfopen(char *file, char *mode)
{
MYFILE *fp = (MYFILE *)malloc(sizeof(MYFILE));
if (fp != NULL) {
// read mode
if (strcmp(mode, "r") == 0) {
if ((fp->fd = open(file, O_RDONLY)) < 0) {
free(fp);
return NULL;
}
fp->mode = READONLY_MODE;
}
else if (strcmp(mode, "w") == 0) {
if ((fp->fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) {
free(fp);
return NULL;
}
fp->mode = WRITEONLY_MODE;
}
else {
fprintf(stderr, "not supported mode: %s\n", mode);
free(fp);
return NULL;
}
fp->length = fp->offset = 0;
}
return fp;
}
int myfclose(MYFILE *fp)
{
if (fp == NULL) return EOF;
if (close(fp->fd) < 0) {
free(fp);
return EOF;
}
if (fp->mode == 1) {
if (fp->length > fp->offset) {
char buf[fp->offset - 1];
memcpy(buf, fp->buf, (fp->offset - 1));
buf[fp->offset - 1] = '\0';
printf("%d %s %lu\n", fp->fd, buf, sizeof(buf));
// ERROR CODE: return bad descriptor
if ((write(fp->fd, &buf, strlen(buf))) != strlen(buf)) {
perror("Write");
}
}
}
free(fp);
return 0;
}
char myfgetc(MYFILE *fp)
{
if (fp == NULL) return EOF;
if (fp->offset == fp->length) {
if ((fp->length = read(fp->fd, fp->buf, BUFSIZE)) < 1) return EOF;
fp->offset = 0;
}
return fp->buf[fp->offset++];
}
void myfputc(char c, MYFILE *fp)
{
if (fp == NULL) exit(-1);
fp->length = BUFSIZE;
if (fp->offset == fp->length) {
if ((write(fp->fd, fp->buf, BUFSIZE)) < BUFSIZE) {
fprintf(stderr, "failed to write");
exit(-1);
}
fp->offset = 0;
}
fp->buf[fp->offset++] = c;
}
解决方案
一个关键的错误是c
需要声明为int
因为EOF
不能用char
.
另一个错误是您在以myfclose
. 由于显而易见的原因,这将不起作用。关闭文件应该是你做的最后一件事。
改成:
int myfclose(MYFILE *fp)
{
if (fp == NULL) return EOF;
if (fp->mode == 1) {
if (fp->length > fp->offset) {
char buf[fp->offset - 1];
memcpy(buf, fp->buf, (fp->offset - 1));
buf[fp->offset - 1] = '\0';
printf("%d %s %lu\n", fp->fd, buf, sizeof(buf));
// ERROR CODE: return bad descriptor
if ((write(fp->fd, &buf, strlen(buf))) != strlen(buf)) {
perror("Write");
}
}
}
if (close(fp->fd) < 0) {
free(fp);
return EOF;
}
free(fp);
return 0;
}
可能还有其他错误,但上面修复了其中两个。
推荐阅读
- python - 如何在 Python 中每 x 秒将声音写入音频文件(例如 .mp3)?
- zuul-ci - 如何为特定项目的 Zuul CI 作业配置快速失败策略?
- html - 如何在表格中使用行跨度和列跨度设置列的宽度?
- python - Python openCV 从 webRTC janus 获取 VideoCapture
- dpdk - testpmd 无法运行,因为缺少 librte_pmd_bond.so
- python - 在 Docker 中运行 python cronjob 时缺少环境变量
- java - 迁移 Feign Load Balancer 实现以兼容 Spring cloud 2020.0.0
- python - return self.func(*args) TypeError: serchongoogle() missing 1 required positional argument: 'choice'
- flutter - ImagePicker 插件可以免费使用吗?
- r - R中权重的广义基尼