- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我似乎不知道如何从 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/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!