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-&gt;fd) 然后检查缓冲区中是否有任何内容。如果有,它会尝试用write(fp-&gt;fd, &amp;buf, strlen(buf)) 写入它。当然这会失败,因为文件已关闭。

先刷新缓冲区,最后关闭文件。

【讨论】:

我之前写过这段代码,没有注意到。我挣扎了好几个小时都没有注意到那个代码,非常感谢。

以上是关于Linux C 编程,尝试编写:实现 FILE 系统模仿 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Linux平台Makefile文件的编写基础篇

c语言编程:编写程序,实现文本文件的复制。从一个文件中逐个字符输出,将其中的小写字母转换成大写字母

linux系统 C语言编程

在Linux系统系下vi操作中C语言编程,如何进行复制粘贴?求救!

用C语言编写一个学生管理系统。

Linux实验 shell的编程