gpt4 book ai didi

c - 如何从 fopen 转换为 open 函数?

转载 作者:行者123 更新时间:2023-11-30 14:50:25 25 4
gpt4 key购买 nike

我似乎不知道如何从 fopen 转换为 open。我没有太多的 c 经验,所以这对我来说是相当难以承受的。

这是它本身的内容:

在cache_reader.c文件中(只是打开和关闭函数):

void cr_close(cr_file* f){
free(f->buffer);
fclose(f->file);
}

cr_file* cr_open(char * filename, int buffersize)
{
FILE* f;
if ((f = fopen(filename, "r")) == NULL){
fprintf(stderr, "Cannot open %s\n", filename);
return 0; }

cr_file* a=(cr_file*)malloc(sizeof(cr_file));
a->file=f;
a->bufferlength=buffersize;
a->usedbuffer=buffersize;
a->buffer=(char*)malloc(sizeof(char)*buffersize);
refill(a);
return a;
}

在cache_reader.h文件中:

typedef struct{
FILE* file; //File being read
int bufferlength; //Fixed buffer length
int usedbuffer; //Current point in the buffer
char* buffer; //A pointer to a piece of memory
// same length as "bufferlength"
} cr_file;
//Open a file with a given size of buffer to cache with
cr_file* cr_open(char* filename, int buffersize);
//Close an open file
void cr_close(cr_file* f);
int refill(cr_file* buff);

在cache_example.c文件中:

int main(){
char c;

//Open a file
cr_file* f = cr_open("text",20);

//While there are useful bytes coming from it
while((c=cr_read_byte(f))!=EOF)
//Print them
printf("%c",c);

//Then close the file
cr_close(f);

//And finish
return 0;
}

我知道我需要将 fclose 更改为关闭,将 fopen 更改为打开。但我不明白其他大部分内容。我在所有事情上都遇到了大量的错误,而且我不确定指针是如何解决的,因为我几乎没有任何使用它们的经验。我尝试使用 int fileno(FILE *stream) ,方法是 int fd = fileno(FILE *f) 然后 fd = fopen(filename, "r")) == NULL)。这不起作用,我能找到的 open 函数的所有示例都只是使用文件名,而不是使用字符指针来指定文件名...我认为 cr_close 函数可以通过将 fclose 更改为 close 来完成,但这也行不通。我不确定是否还需要编辑cache_example.c 文件。

有人可以提供一些帮助,让我走上正确的道路吗?

最佳答案

来自评论

练习的目的是保持示例代码不变,但是重新实现其他代码以使用文件描述符而不是文件溪流。遗憾的是, header 不必要地暴露了结构的内部结构,所以需要重新编译该示例。您将把 FILE * 成员更改为 int。您不会使用任何采用文件流参数的函数。

header (cache_reader.h)应包含此内容(而不是结构定义):

typedef struct cr_file cr_file;

源代码 (cache_reader.c) 应包含:

struct cr_file
{
int file;
int bufferlength;
int usedbuffer;
char *buffer;
};

这为您在客户端(示例)代码中提供了一个不透明的类型,并允许您无需重新编译客户端代码即可更改结构(当然,尽管您必须重新编译实现 - 我们无法创造完全的奇迹)。

当然,您可以让您的客户在任何时候重新编译他们的代码对库的内部进行更改。然而,从长远来看,如果你能做到这一点,通常会更方便对您的库代码进行更改和改进,而不需要消费者(其他程序员)重新编译他们的代码。二进制兼容性对于大型库非常重要,例如给定平台上的标准 C 库。对于像这样的小项目来说,这并不重要——但你需要至少在适当的时候也了解更大范围的问题,如果你坚持将编程作为职业。

修改代码

请注意,我得出的结论是我需要一些不同的成员来支持您的用例 - 我需要知道分配的缓冲区的大小,缓冲区中实际的数据量以及当前位置阅读。我将成员重命名为 bufmax (您的 bufferlength)、bufpos (您的usedbuffer),并添加了buflen

我为 cr_read_byte() 编写了示例代码,它可以读取文件。

但是,支持写作还有大量工作要做,并在文件中移动而不是每次移动一个字节,等等。

cache_reader.h

#ifndef CACHE_READER_H_INCLUDED
#define CACHE_READER_H_INCLUDED

typedef struct cr_file cr_file;

extern cr_file *cr_open(char *filename, int buffersize);
extern void cr_close(cr_file *f);
extern int cr_read_byte(cr_file *f);

#endif /* CACHE_READER_H_INCLUDED */

cache_reader.c

#include "cache_reader.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct cr_file
{
int file; // File being read
int bufmax; // Fixed buffer length
int bufpos; // Current point in the buffer
int buflen; // Amount of data in the buffer
char *buffer; // A pointer to a piece of memory
};

static void cr_refill(cr_file *f)
{
if (f->bufpos >= f->buflen)
{
int nbytes = read(f->file, f->buffer, f->bufmax);
if (nbytes > 0)
{
f->buflen = nbytes;
f->bufpos = 0;
}
}
}

void cr_close(cr_file *f)
{
free(f->buffer);
close(f->file);
free(f);
}

cr_file *cr_open(char *filename, int buffersize)
{
int fd;
if ((fd = open(filename, O_RDWR)) < 0)
{
fprintf(stderr, "cannot open %s for reading and writing (%d: %s)\n",
filename, errno, strerror(errno));
return 0;
}

cr_file *a = (cr_file *)malloc(sizeof(cr_file));
char *b = (char *)malloc(sizeof(char) * buffersize);
if (a == 0 || b == 0)
{
free(a);
free(b);
close(fd);
fprintf(stderr, "cannot allocate %zu bytes of memory (%d: %s)\n",
sizeof(cr_file) + buffersize, errno, strerror(errno));
return 0;
}
a->file = fd;
a->bufmax = buffersize;
a->bufpos = 0;
a->buflen = 0;
a->buffer = b;
return a;
}

int cr_read_byte(cr_file *f)
{
if (f->bufpos >= f->buflen)
cr_refill(f);
if (f->bufpos >= f->buflen)
return EOF;
return f->buffer[f->bufpos++];
}

cache_example.c

#include "cache_reader.h"
#include <stdio.h>

int main(void)
{
cr_file *f = cr_open("text", 20);
if (f != 0)
{
int c;
while ((c = cr_read_byte(f)) != EOF)
putchar(c);
cr_close(f);
}
return 0;
}

makefile

CFLAGS  = -std=c11 -O3 -g -Wall -Wextra
LDFLAGS =
LDLIBS =

FILES.c = cache_example.c cache_reader.c
FILES.o = ${FILES.c:.c=.o}
FILES.h = cache_reader.h

PROG1 = cache_example

PROGRAMS = ${PROG1}

all: ${PROGRAMS}

${PROG1}: ${FILES.o}
${CC} -o $@ ${CFLAGS} ${FILES.o} ${LDFLAGS} ${LDLIBS}

${FILES.o}: ${FILES.h}
<小时/>

您可以在 GitHub 上我的 SOQ 中找到此代码(答案中显示的骨架 makefile 除外) (堆溢出问题)存储库作为文件在 src/so-4901-1302子目录。

关于c - 如何从 fopen 转换为 open 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49011302/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com