我似乎无法弄清楚如何从fopen转换为open。我没有多少经验,所以对我来说这是非常压倒性的。
这就是它本身的含义:
在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来关闭,但这也不起作用。我不确定是否还需要编辑cache_example.c文件。
有人能提供一些帮助,让我走上正确的道路吗?
答案 0 :(得分:1)
来自评论
练习的目的是保持示例代码不变,但是
重新实现其他代码以使用文件描述符而不是文件
流。
可悲的是,标题暴露了结构的内部,不必要地,
所以这个例子需要重新编译。
您将FILE *
成员更改为int
。
您不会使用任何带有文件流参数的函数。
标题(cache_reader.h
)应包含此内容(而不是结构
定义):
typedef struct cr_file cr_file;
来源(cache_reader.c
)应包含:
struct cr_file
{
int file;
int bufferlength;
int usedbuffer;
char *buffer;
};
这为您提供了客户端(示例)代码中的opaque类型,并允许 您无需重新编译客户端代码即可更改结构 (虽然你必须重新编译实现,当然 - 我们 无法完成奇迹)。
当然,无论何时,您都可以让客户重新编译代码 更改库的内部。 但是,如果你能做到,从长远来看往往更方便 库代码的更改和改进,无需使用 消费者(其他程序员)重新编译他们的代码。 二进制兼容性对于大型库非常重要,例如 给定平台上的标准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}
您可以在SOQ(堆栈)的GitHub上找到此代码(答案中显示的骨架makefile
除外)
溢出问题)存储库作为文件
src/so-4901-1302子目录。
答案 1 :(得分:0)
以下提议的代码:
#include
语句及其需要的原因现在,建议的代码
// following struct not actually used in this code
#if 0
typedef struct
{
int fd; // file descriptor number of input file
/*
* 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;
#endif
-------------------------
// following 3 header files for 'open()' and 'O_RDONLY'
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// following for 'read()' and 'close()'
#include <unistd.h>
// following for 'exit()' and 'EXIT_FAILURE'
#include <stdlib.h>
// following for 'printf()', 'perror()'
#include <stdio.h>
int main( void )
{
//Open a file
int fd = open("text", O_RDONLY);
if( 0 > fd )
{ // then open failed
perror( "open for input file failed" );
exit( EXIT_FAILURE );
}
// implied else, open successful
//While there are useful bytes coming from it
char buf;
while( read( fd, &buf, 1 ) > 0 )
{
printf( "%c", buf );
}
//Then close the file
close( fd );
//And finish
return 0;
}