Linux C 编程,尝试编写:实现 FILE 系统模仿 [关闭]
Posted
技术标签:
【中文标题】Linux C 编程,尝试编写:实现 FILE 系统模仿 [关闭]【英文标题】:Linux C Programming, trying to write: implementing FILE system imitate [closed] 【发布时间】:2021-07-10 12:12:40 【问题描述】:我正在尝试实现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;
【问题讨论】:
这是开始学习调试器基本用法的好机会。你将花一个小时左右的时间来学习这将很快得到回报。 您正在关闭文件描述符,然后写入它(myfclose
)。这永远不会奏效。
@Jabberwocky TBH,我认为调试器在这里不会有太大帮助。但你说得对,它是一个有用的工具。
【参考方案1】:
一个关键的错误是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;
可能还有其他错误,但以上修复了其中两个。
【讨论】:
感谢您的友好和有益的解释。非常有帮助 :) 当然,感谢您发现错误。【参考方案2】:myfclose
调用close(fp->fd)
然后检查缓冲区中是否有任何内容。如果有,它会尝试用write(fp->fd, &buf, strlen(buf))
写入它。当然这会失败,因为文件已关闭。
先刷新缓冲区,最后关闭文件。
【讨论】:
我之前写过这段代码,没有注意到。我挣扎了好几个小时都没有注意到那个代码,非常感谢。以上是关于Linux C 编程,尝试编写:实现 FILE 系统模仿 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
c语言编程:编写程序,实现文本文件的复制。从一个文件中逐个字符输出,将其中的小写字母转换成大写字母