2人の他人のリソースを処理

ファイルのオープン、クローズ一元管理。

ファイルを開く - ファイルハンドル - 近いファイル。

そして、ファイルアクセスの構造は、ファイル名、処理方法が含まれている必要があります。アクセスモード - 今回は、1人の以上のメンバーを追加します。それから

file_reader.h

#ifndefの_FILE_READER_H_
#define _FILE_READER_H_

書式#include <stdio.hに>
書式#include <stdbool.h>

#ifdefの__cplusplus
extern "C" {
#endifの

typedefは構造体FileAcessorContext {
    pFnameのconstのconstのchar *;
    PMODEのconstのconstのchar *;
    ボイド(* CONSTプロセッサ)(構造体FileAcessorContext * pThis、FILE * FP)。
} FileAcessorContext。

ブールaccess_file(FileAcessorContext * pCtx)。

#ifdefの__cplusplus
}
#endifの

#endifの
 
file_reader.c
 
#include "file_reader.h"

ブールaccess_file(FileAcessorContext * pCtx){
    FILE * FP =のfopen(pCtx-> pFname、pCtx-> PMODE)。
    (FP == NULL)の場合
        falseを返します。

    pCtx->プロセッサ(pCtx、FP)。

    FCLOSE(FP)。

    trueを返します。
}
 
上記のメモリ管理とリリースとはまったく同じです。
メモリを割り当てる - メモリのプロセスを - メモリを解放します。それから
buffer.h
#ifndefの_BUFFER_H_
#define _BUFFER_H_

書式#include <stdio.hに>
書式#include <stdbool.h>
書式#include <stdlib.h>に含ま

#ifdefの__cplusplus
extern "C" {
#endifの

typedef struct BufferContext{
    void *pBuf;
    size_t size;
    void (* const processor)(struct BufferContext *pThis);
}BufferContext;

bool buffer(BufferContext *pThis);

#ifdef __cplusplus
}
#endif

#endif
 
buffer.c
#include "buffer.h"

bool buffer(BufferContext *pThis){
    pThis->pBuf = malloc(pThis->size);
    if(pThis->pBuf == NULL)
        return false;
    
    pThis->processor(pThis);

    free(pThis->pBuf);

    return true;
}
 
接下来这个获取文件内数值的范围,就比较麻烦了。主要是因为打开、关闭文件、内存分配、释放的处理。
内存的分配又需要先知道文件的大小,要知道文件的大小首先要打开文件,获得了大小又要有一个变量来存储它,以备后续使用。
所以 获取文件大小的上下文结构体应该是要继承文件访问结构体,并加上一个变量size。
所以
typedef struct {
    FileAcessorContext base;
    long size;
}FileSizeGetterContext;
 
当获取文件大小时,我们仅有的信息是文件名,所以我们的file_size函数应该这样写:
static long file_size(const char * const pFname);
 
具体的实现是要定义一个FileSizeGetterContext(获取文件大小的上下文结构体)变量ctx。
这样访问文件之后,可以把文件大小保存在ctx的成员size里。如下:
static long file_size(const char * const pFname){
    FileSizeGetterContext ctx = {{pFname, "r", size_reader}, 0};

    if(!access_file(&ctx.base)){
        return -1;
    }

    return ctx.size;
}
按照这样的想法去写内存的分配、内存的操作、文件访问失败的处理,内存分配失败的处理。
内存的操作又包括读取文件的内容到内存,然后将内存做我们想要的处理,返回相应的结果。
 
int_range.h
#ifndef _INT_RANGE_H_
#define _INT_RANGE_H_

#include "file_reader.h"
#include "buffer.h"
#include "limits.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    FileAcessorContext base;
    long size;
}FileSizeGetterContext;

typedef enum {
    ERR_CAT_OK,
    ERR_CAT_FILE,
    ERR_CAT_MEMORY
}IntRangeError;

typedef struct {
    const char * const pFname;
    int errorCatgory;
}Context;

typedef struct {
    BufferContext base;
    Context *pAppCtx;
}MyBufferContext;

typedef struct {
    FileAcessorContext base;
    MyBufferContext *pBufCtx;
}MyFileAccessorContext;


IntRangeError int_range(const char * const pFname);

static long file_size(const char * const pFname);
static void size_reader(FileAcessorContext *p, FILE *fp);
static long buffer_allocate(long size, Context *pAppCtx);
static void file_error(Context *pCtx);
static void buffer_error(Context *pCtx);
static void do_with_buffer(BufferContext *p);
static void reader(FileAcessorContext *p, FILE *fp);
static void writer(FileAcessorContext *p, FILE *fp);
static int range_processor(char *buf, size_t size);


#ifdef __cplusplus
}
#endif

#endif
 
int_range.c
#include "int_range.h"

static long file_size(const char * const pFname){
    FileSizeGetterContext ctx = {{pFname, "r", size_reader}, 0};

    if(!access_file(&ctx.base)){
        return -1;
    }

    return ctx.size;
}

static void size_reader(FileAcessorContext *p, FILE *fp){
    FileSizeGetterContext *pThis = (FileSizeGetterContext *)p;
    pThis->size = -1;

    if(fseek(fp, 0, SEEK_END) == 0)
        pThis->size = ftell(fp);
}

static long buffer_allocate(long size, Context *pAppCtx){
    MyBufferContext bufCtx = {{NULL, size, do_with_buffer}, pAppCtx};
    if(!buffer(&bufCtx.base)){
        return -1;
    }
    return size;
}

IntRangeError int_range(const char * const pFname){
    Context ctx = {pFname, ERR_CAT_OK};

    long size = file_size(pFname);
    if(size == -1){
        file_error(&ctx);
        return ctx.errorCatgory;
    }

    long buffer_size = buffer_allocate(size, &ctx);
    if(buffer_size == -1){
        buffer_error(&ctx);
        return ctx.errorCatgory;
    }
}

static void file_error(Context *pCtx){
    printf("Failed to open File: %s\n", pCtx->pFname);
    pCtx->errorCatgory = ERR_CAT_FILE;
}

static void buffer_error(Context *pCtx){
    printf("Failed to malloc memory\n");
    pCtx->errorCatgory = ERR_CAT_MEMORY;
}

static void do_with_buffer(BufferContext *p) {
    MyBufferContext *pBufCtx = (MyBufferContext *)p;
    MyFileAccessorContext readFileCtx = {{pBufCtx->pAppCtx->pFname, "rb", reader}, pBufCtx};

    if(!access_file(&readFileCtx.base)){
        file_error(pBufCtx->pAppCtx);
        return;
    }

    int value = range_processor(p->pBuf, p->size);
    printf("value is %d\n", value);

    MyFileAccessorContext writeFileCtx = {{pBufCtx->pAppCtx->pFname, "wb", writer}, pBufCtx};

    if(!access_file(&readFileCtx.base)){
        file_error(pBufCtx->pAppCtx);
        return;
    }    
}

static void reader(FileAcessorContext *p, FILE *fp){
    MyFileAccessorContext *pFileCtx = (MyFileAccessorContext *)p;
    MyBufferContext *pBufCtx = pFileCtx->pBufCtx;

    if(pBufCtx->base.size != fread(pBufCtx->base.pBuf, 1 , pBufCtx->base.size, fp)){
        file_error(pBufCtx->pAppCtx);
    }
}

static void writer(FileAcessorContext *p, FILE *fp){
    MyFileAccessorContext *pFileCtx = (MyFileAccessorContext *)p;
    MyBufferContext *pBufCtx = pFileCtx->pBufCtx;

    if(pBufCtx->base.size != fwrite(pBufCtx->base.pBuf, 1, pBufCtx->base.size, fp)){
        file_error(pBufCtx->pAppCtx);
    }
}

static int range_processor(char *buf, size_t size){
    int min = INT_MAX;
    int max = INT_MIN;

    for(int i = 0; i < size; i+=4){
        min = min > (*(int *)(buf + i)) ? (*(int *)(buf + i)) : min;
        max = max < (*(int *)(buf + i)) ? (*(int *)(buf + i)) : max;
    }

    return max - min;
}
 
测试文件很简单
range_test.c
#include "int_range.h"

int main(int argc, char const *argv[])
{
    int_range("nums.bat");
    return 0;
}
 
nums.bat里是若干个int型数据。函数返回这些数据的数值范围。
 

おすすめ

転載: www.cnblogs.com/vonyoven/p/12016859.html
おすすめ