模板方法模式之三

上一节file_reader.c中:

int ret = processor(fp); 

返回的处理结果是int型的值,如果需要返回非int值怎么办?

typedef struct FileReaderContext{
    const char *pFname;
    void (* const processor)(struct FileReaderContext *pThis, FILE *fp);
}FileReaderContext;
 
如上,processor是文件的处理接口。这样processor就可以返回非int型了。
至于真正的文件内容处理的返回值可以通过继承来实现。
 
typedef struct MyFileReaderContext
{
    FileReaderContext base;
    float result;
}MyFileReaderContext;
以上result就保存真正的文件内容处理的返回值。
 
range.h
#ifndef _RANGE_H_
#define _RANGE_H_

#include "file_reader.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct MyFileReaderContext
{
    FileReaderContext base;
    float result;
}MyFileReaderContext;


float range(const char *pFname);
float sum(const char *pFname);

static float range_processor(FILE *fp);
static float sum_processor(FILE *fp);
static void calc_range(FileReaderContext *pThis, FILE *fp);
static void calc_sum(FileReaderContext *pThis, FILE *fp);

#ifdef __cplusplus
}
#endif

#endif
 
range.c
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include "file_reader.h"
#include "range.h"

static float range_processor(FILE *fp){
    float min = INT_MAX;
    float max = INT_MIN;
    char buf[256] = {0};

    while((fgets(buf, sizeof(buf), fp)) != NULL){  
        if(buf[0] == '\r'){
            printf("empty line\n");
            return -1;
        }
        char *temp = strtok(buf," ");
        while(temp != NULL){
            float value = atof(temp);
            min = min > value ? value : min;
            max = max < value ? value : max;
            temp = strtok(NULL," ");
        }
    }

    return max - min;
}

static float sum_processor(FILE *fp){
    float sum = 0;
    char buf[256] = {0};
    while((fgets(buf, sizeof(buf), fp)) != NULL){  
        if(buf[0] == '\r'){
            printf("empty line\n");
            return -1;
        }
        char *temp = strtok(buf," ");
        while(temp != NULL){
            float value = atof(temp);
            sum += value;
            temp = strtok(NULL," ");
        }
    }
    return sum;
}

static void calc_range(FileReaderContext *pThis, FILE *fp){
    MyFileReaderContext *pCtx = (MyFileReaderContext *)pThis;
    pCtx->result = range_processor(fp);
}

static void calc_sum(FileReaderContext *pThis, FILE *fp){
    MyFileReaderContext *pCtx = (MyFileReaderContext *)pThis;
    pCtx->result = sum_processor(fp);
}

float range(const char *pFname){
    MyFileReaderContext ctx = {{pFname, calc_range}, 0.0};
    
    if(read_file(&ctx.base) != 0){
        printf("Cannot open file '%s'\n", pFname);
    }
    return ctx.result;
}

float sum(const char *pFname){
    MyFileReaderContext ctx = {{pFname, calc_sum}, 0.0};
    
    if(read_file(&ctx.base) != 0){
        printf("Cannot open file '%s'\n", pFname);
    }
    return ctx.result;
}
 
file_reader.h
#ifndef _FILE_READER_H_
#define _FILE_READER_H_

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct FileReaderContext{
    const char *pFname;
    void (* const processor)(struct FileReaderContext *pThis, FILE *fp);
}FileReaderContext;

int read_file(FileReaderContext *pCtx);

#ifdef __cplusplus
}
#endif

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

int read_file(FileReaderContext *pCtx){
    FILE *fp = fopen(pCtx->pFname, "r");
    if(fp == NULL)
        return -1;
        
    pCtx->processor(pCtx, fp);

    fclose(fp);
    return 0;
}
 
range_test.c
#include <stdio.h>
#include "range.h"

int main(int argc, char const *argv[])
{
    float ret = range("nums.txt");
    printf("ret is %f\n", ret);
    ret = sum("nums.txt");
    printf("sum is %f\n", ret);
    return 0;
}
 
除了使用继承方法,本节没有太多意义。
posted @ 2019-12-09 18:35    阅读(137)  评论(0)    收藏  举报