如何使用不同的运算符重用相同的C代码

如何使用不同的运算符重用相同的C代码,c,operators,semantics,code-reuse,C,Operators,Semantics,Code Reuse,我正在用C构建一个库,其中一个函数是库的一部分,类似于: void myFunction(double *inPtr, double start, double step, double *outPtr, int N, t_shape shape) { int i; switch (shape) { default: case ShapeLinear: /* more stuff going on */

我正在用C构建一个库,其中一个函数是库的一部分,类似于:

void myFunction(double *inPtr, double start, double step, double *outPtr, int N, t_shape shape)
{
    int i;

    switch (shape) {

        default:
        case ShapeLinear:
            /* more stuff going on */
            for (i = 0; i < N; i++) {
                *(outPtr++) = *(inPtr++) * start;
                start += step;
            }
            /* more stuff going on */
            break;

        case ShapeExponential:
            /* more stuff going on */
            for (i = 0; i < N; i++) {
                *(outPtr++) = *(inPtr++) * start;
                start *= step;
            }
            /* more stuff going on */
            break;

        case ShapeSquared:
            /* more stuff going on */
            for (i = 0; i < N; i++) {
                *(outPtr++) = *(inPtr++) * start * start;
                start += step;
            }
            /* more stuff going on */
            break;

        case ShapeCubed:
            /* more stuff going on */
            for (i = 0; i < N; i++) {
                *(outPtr++) = *(inPtr++) * start * start * start;
                start += step;
            }
            /* more stuff going on */
            break;
    }
}
void myFunction(双*inPtr、双启动、双步骤、双*outPtr、int N、t_形)
{
int i;
开关(形状){
违约:
箱型线:
/*更多的事情正在发生*/
对于(i=0;i
这是一个简化版本,仅用于演示。
库中的实际函数有更多的案例,每个案例都更长、更复杂

现在,我想创建完全相同的函数的另一个版本,唯一的区别是,我想添加并分配它,而不是将值分配给outPtr

void myFunctionAdd(double *inPtr, double start, double step, double *outPtr, int N, t_shape shape)
{
    int i;

    switch (shape) {

        default:
        case ShapeLinear:
            /* more stuff going on */
            for (i = 0; i < N; i++) {
                *(outPtr++) += *(inPtr++) * start;
                start += step;
            }
            /* more stuff going on */
            break;

        case ShapeExponential:
            /* more stuff going on */
            for (i = 0; i < N; i++) {
                *(outPtr++) += *(inPtr++) * start;
                start *= step;
            }
            /* more stuff going on */
            break;

        case ShapeSquared:
            /* more stuff going on */
            for (i = 0; i < N; i++) {
                *(outPtr++) += *(inPtr++) * start * start;
                start += step;
            }
            /* more stuff going on */
            break;

        case ShapeCubed:
            /* more stuff going on */
            for (i = 0; i < N; i++) {
                *(outPtr++) += *(inPtr++) * start * start * start;
                start += step;
            }
            /* more stuff going on */
            break;
    }
}
void myfunctionDD(双*inPtr、双启动、双步骤、双*outPtr、int N、t_形)
{
int i;
开关(形状){
违约:
箱型线:
/*更多的事情正在发生*/
对于(i=0;i
正如我所说的,我正在处理的实际函数更长、更复杂,因此必须重写相同的代码两次是我不想做的事情。
这将是糟糕的编程实践,并且更难维护

有没有C编程技术来解决这个问题?
块(闭包)在这种情况下有用吗?
我是否需要以某种方式重构代码?

如何解决这个问题?

使用一个函数来代替运算符,该函数采用一些常量来定义函数的功能。通过这种方式,您可以以相同的方式构造许多逻辑,并且只改变函数的参数,以确定函数中的实际操作

函数也可以是一系列重载,以帮助您避免重复太多代码。请注意,您必须重构代码以传入分配(或非分配)的目标


请注意,对于这样的解决方案,唯一重要的“形状”是操作数的计数。

经典的c解决方案是传入一个函数,该函数被调用以执行您想要改变的操作。然而,这取决于操作的基本形状是否相同


在您的情况下,这感觉有点强迫,因为我们必须传入outPtr的旧值,您尝试执行的操作或多或少类似于映射操作。相反,我会定义一个函数映射,并用不同的输入函数调用它。下面是一个可编译的示例。希望您可以扩展它以适应您的问题

#include <assert.h>
#include <stdio.h>

#define LEN(array) (sizeof (array) / sizeof (array)[0])

typedef double (*Function)(double x);

static void Map(Function f, const double arr[], int arrLen, double result[], int resultLen)
{
    int i;

    assert(resultLen >= arrLen);

    for (i = 0; i < arrLen; i++) {
        result[i] = f(arr[i]);
    }
}


static double Square(double x)
{
    return x * x;
}


int main(void)
{
    double arr[] = {1.0, 2.0, 3.0, 4.0};
    double result[LEN(arr)];
    int i;

    Map(Square, arr, LEN(arr), result, LEN(result));

    for (i = 0; i < LEN(result); i++) {
        printf("%f\n", result[i]);
    }
    return 0;
}
#包括
#包括
#定义LEN(数组)(sizeof(数组)/sizeof(数组)[0])
typedef double(*函数)(双x);
静态无效映射(函数f,常量双arr[],int arrLen,双结果[],int resultLen)
{
int i;
断言(resultLen>=arrLen);
对于(i=0;i
感谢您的回复,但我不认为这有助于我避免重复代码。opType==1时调用的代码与opType==2时调用的代码相同。opType==2时唯一不同的是赋值运算符。但是这意味着我仍然需要复制我的代码。谢谢你,但是我不知道如何才能不用使用你的策略来复制我的代码。我仍然需要编写两个do_what()函数。一个会将outPtr添加到结果中,另一个不会。诚然,我可以提出一个有条件的声明,但它会对效率产生影响。除此之外,我并不热衷于在循环中调用函数,除非这是绝对必要的。是的,但do_what函数只有一行-请参见编辑
typedef int (*func_ptr)(int,int); 
myFunction(....... func_ptr do_what)
{
int i;

switch (shape) {

    default:
    case ShapeLinear:
        /* more stuff going on */
        for (i = 0; i < N; i++) {
            *(outPtr++) = func_ptr(*(inptr++), outPtr);
            start += step;
        }
        /* more stuff going on */
        break;
}

int assign(int a, int b)
{
return a;
}

int add_assign(int a, int b)
{
return a + b;
}
 myFunction(......assign);
myfunction(......add_assign);
#include <assert.h>
#include <stdio.h>

#define LEN(array) (sizeof (array) / sizeof (array)[0])

typedef double (*Function)(double x);

static void Map(Function f, const double arr[], int arrLen, double result[], int resultLen)
{
    int i;

    assert(resultLen >= arrLen);

    for (i = 0; i < arrLen; i++) {
        result[i] = f(arr[i]);
    }
}


static double Square(double x)
{
    return x * x;
}


int main(void)
{
    double arr[] = {1.0, 2.0, 3.0, 4.0};
    double result[LEN(arr)];
    int i;

    Map(Square, arr, LEN(arr), result, LEN(result));

    for (i = 0; i < LEN(result); i++) {
        printf("%f\n", result[i]);
    }
    return 0;
}