当前位置: 首页 > 知识库问答 >
问题:

如何从fopen转换为open函数?

富辰阳
2023-03-14

我似乎不知道如何从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文件。

有人能帮我找到正确的方法来做这件事吗。。?

共有3个答案

柴英博
2023-03-14

请注意,我有两个选项,我可以将fopen转换为fcntl中的open。h如上所述,但这需要我将现有代码库中的许多函数签名从FILE*更改为int。相反,我决定使用fflushfsync,这是一个更简单的解决方案,同时仍然确保文件内容立即写入磁盘。fflushfsync更简单的原因是它们仍然允许我使用现有的文件指针。然后,为了确保文件立即写入磁盘,我使用以下命令。这基本上为您提供了一个潜在的替代解决方案:

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之间的区别

陶博涉
2023-03-14

建议的守则如下:

  1. 干净地编译
  2. 消除不需要/未使用的代码
  3. 包括#include语句以及需要它们的原因
  4. 执行所需的功能
  5. 使用(根据OPs请求)文件描述符而不是文件指针

现在,提议的代码

// 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;
}
阮喜
2023-03-14

来自评论

本练习的目的是保持示例代码不变,但重新实现其他代码以使用文件描述符而不是文件流。遗憾的是,头部不必要地暴露了结构的内部,因此需要重新编译该示例。您将把文件*成员更改为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 问题答案: 您应该改用日历:

  • 我有一个来自源代码的,根据规范,它应该是,但在类中没有看到任何方法将转换为。 最好的方法是什么?

  • 问题内容: 我想在Golang中将int转换为hex。在strconv中,有一种将字符串转换为十六进制的方法。是否有类似的方法从int获取十六进制字符串? 问题答案: 由于hex是Integer文字,因此您可以使用,和或格式向fmt包询问该整数的字符串表示形式。参观游乐场 输出:

  • 问题内容: 我正在一个项目中,所有从到的转换都是这样完成的: 我对Java不熟悉。我想这是通常的做法还是出了什么问题? 问题答案: 正常的方法是或。 串联可以工作,但是这是非常规的,可能会产生难闻的气味,因为这表明作者不了解上述两种方法(他们可能还不知道什么?)。 当与字符串一起使用时,Java对+运算符有特殊的支持(请参阅文档),它将你发布的代码转换为: 在编译时。它的效率稍低(最终会调用,这反

  • 我试图将我的Javascript撰写函数翻译成Python,但我对最后一个有问题。我如何推广未知数量的函数? 读完本文后,我想避免使用方法。 javascript: 蟒蛇: 感谢所有的改进。。。

  • 问题内容: 如何获取包含Python中当前正在执行的函数的变量?我不需要函数的名称。我知道我可以用来获取当前的函数名称。我想要实际的可调用对象。是否可以不使用检索函数名称,然后输入名称以获取可调用对象而完成此操作? 编辑: 我有这样做的理由,但它甚至不是一个很好的选择。我正在使用plac解析命令行参数。您可以通过使用来使用它,它会根据“ main”的函数签名生成一个ArgumentParser对象