我似乎不知道如何从fopen转换为open。我没有太多的c经验,所以这对我来说是相当压倒性的。
以下是它本身的情况:
在高速缓存读卡器中。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更改为close,fopen更改为open。但我不懂其他的大部分东西。我每件事都会犯很多错误,我不确定指针是如何解决的,因为我几乎没有任何使用指针的经验。我试着使用int-fileno(FILE*stream),先说int-fd=fileno(FILE*f),然后说fd=fopen(filename,“r”)==NULL。这不起作用,我能找到的所有打开函数示例都只使用文件名,而不是字符指针来指定文件名。。。我以为只要将fclose更改为close就可以实现cr_close功能,但这也不起作用。我不确定是否需要编辑cache_示例。c文件。
有人能帮我找到正确的方法来做这件事吗。。?
请注意,我有两个选项,我可以将fopen
转换为fcntl中的
如上所述,但这需要我将现有代码库中的许多函数签名从open
。hFILE*
更改为int
。相反,我决定使用fflush
和fsync
,这是一个更简单的解决方案,同时仍然确保文件内容立即写入磁盘。fflush
和fsync
更简单的原因是它们仍然允许我使用现有的文件
指针。然后,为了确保文件立即写入磁盘,我使用以下命令。这基本上为您提供了一个潜在的替代解决方案:
FILE *fp = fopen(myfilename, "w+");
if (fp) {
// write contents of buffer to OS
if (0 != fflush(fp)) {
// error handling here
}
// Tell OS to write contents of buffers to storage media
if (0 != fsync(fileno(fp))) {
// more error handling
} else {
// steps to do on success
}
} else {
// debug log could not complete task
}
这是chqrlie在这篇文章中解释的:fflush和fsync之间的区别
建议的守则如下:
#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;
}
来自评论
本练习的目的是保持示例代码不变,但重新实现其他代码以使用文件描述符而不是文件流。遗憾的是,头部不必要地暴露了结构的内部,因此需要重新编译该示例。您将把文件*
成员更改为int
。您不会使用任何接受文件流参数的函数。
标题(cache\u reader.h
)应包含以下内容(而不是结构定义):
typedef struct cr_file cr_file;
源(cache\u reader.c
)应包含:
struct cr_file
{
int file;
int bufferlength;
int usedbuffer;
char *buffer;
};
这在客户端(示例)代码中为您提供了一个不透明的类型,并允许您在不需要重新编译客户端代码的情况下更改结构(当然,您必须重新编译实现——我们不能创造完整的奇迹)。
当然,每当您对库的内部进行更改时,您可以让您的客户端重新编译他们的代码。然而,从长远来看,如果您可以对库代码进行更改和改进,而不需要消费者(其他程序员)重新编译他们的代码,这通常会更方便。二进制兼容性对于大型库非常重要,比如给定平台上的标准C库。对于这样一个小项目来说,这并不重要——但是如果你坚持以编程为职业,你也需要了解更大规模的问题,至少在适当的时候是这样。
请注意,我的结论是,我需要一些不同的成员来支持您的用例——我需要知道分配的缓冲区的大小、缓冲区中实际的数据量以及读取的当前位置。我将成员重命名为bufmax
(您的缓冲区长度
),bufpos
(您的used缓冲区
),并添加了buflen
。
我为cr\u read\u byte()
编写了示例代码,它可以读取文件。
但是,要支持写入,以及在文件中移动,而不是一次一个字节,还有大量的工作要做,等等。
#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 */
#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++];
}
#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;
}
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上的src/so-4901-1302子目录中的文件中找到此代码(答案中显示的骨架makefile
除外)。
问题内容: 即 此代码 给我 : 2012-16-02 05:16:17 什么时候 返回: 2012-01-02 05:16:17.0 问题答案: 您应该改用日历:
我有一个来自源代码的,根据规范,它应该是,但在类中没有看到任何方法将转换为。 最好的方法是什么?
我试图将我的Javascript撰写函数翻译成Python,但我对最后一个有问题。我如何推广未知数量的函数? 读完本文后,我想避免使用方法。 javascript: 蟒蛇: 感谢所有的改进。。。
问题内容: 我想在Golang中将int转换为hex。在strconv中,有一种将字符串转换为十六进制的方法。是否有类似的方法从int获取十六进制字符串? 问题答案: 由于hex是Integer文字,因此您可以使用,和或格式向fmt包询问该整数的字符串表示形式。参观游乐场 输出:
问题内容: 我正在一个项目中,所有从到的转换都是这样完成的: 我对Java不熟悉。我想这是通常的做法还是出了什么问题? 问题答案: 正常的方法是或。 串联可以工作,但是这是非常规的,可能会产生难闻的气味,因为这表明作者不了解上述两种方法(他们可能还不知道什么?)。 当与字符串一起使用时,Java对+运算符有特殊的支持(请参阅文档),它将你发布的代码转换为: 在编译时。它的效率稍低(最终会调用,这反
问题内容: 如何获取包含Python中当前正在执行的函数的变量?我不需要函数的名称。我知道我可以用来获取当前的函数名称。我想要实际的可调用对象。是否可以不使用检索函数名称,然后输入名称以获取可调用对象而完成此操作? 编辑: 我有这样做的理由,但它甚至不是一个很好的选择。我正在使用plac解析命令行参数。您可以通过使用来使用它,它会根据“ main”的函数签名生成一个ArgumentParser对象