如何将C数学运算符(+ – * /%)传递给函数result = mathfunc(x,+,y);?

我正在C程序中编写一些数学例程用于多精度整数,我希望能够轻松编写表达式,但是用我自己的函数处理数学。 所以我想要一些让我这样做的方法:

MPI x=mpi(5),y=mpi(6),z; z=mpimath(x,+,y); 

通过以某种方式对字符进行编码,这在C中是否可行? 我知道没有运算符重载所以它必须是一个函数调用,而+ -sign不能是函数名的一部分。

对的,这是可能的。

您可以使用宏连接到您的函数。 宏为代码的物理外观提供了额外的function。 特别是,您可以对参数进行字符串化 。 并且您可以将任何完整的C 令牌作为参数传递给宏。

所以做这样的事情:

 #define mpimath(X,F,Y) (mpimath)(X,#F,Y) /* stringify F */ 

然后定义您的函数以接受char *参数。 这将导致参数+的字符串"+" 。 通过对宏使用相同的名称,此函数的调用将被此宏拦截 ,因此调用如下:

 mpimath(p,*,r) /* macro invocation */ 

扩大到

 (mpimath)(p,"*",r) /* function call */ 

。 函数名称周围的parens在这里并不是绝对必要的,因为宏不允许递归,它会扩展到正确的东西。 但是包装parens也是明确调用函数绕过任何宏定义的方法,所以我发现它有助于自我文档代码在这里添加它们。

你可以使用像char *ops="+-*/"; int op=strstr(ops, f)-ops; char *ops="+-*/"; int op=strstr(ops, f)-ops; 将字符串映射到一个小整数(*) ,然后可以用它来索引一个函数表。 或者,您可以取消引用字符串以获取可在switch使用的char

 MPI mpimath(MPI x, char *f, MPI y){ switch(*f){ case '+': //... break; case '-': //... break; //etc. } 

或者您可以将解除引用移回宏。 它在宏观上看起来有点奇怪。 但我认为它使function看起来更好。

 #define mpimath(X,F,Y) (mpimath)(X,*#F,Y) /* stringify and deref F */ MPI mpimath(MPI x, char f, MPI y){ switch(f){ case '+': //etc. } } 

编辑:有关实际代码的一些细节,这些代码产生了这个共享 – 你的知识 q / a对。

将操作符作为char传递的动机是间接产生的,但从未以问题中显示的简化forms出现。 对于+函数,宏的当前使用类似于:

  BIN_MATH_FUNC(+,AV(z)[i],AV(a)[i],AV(w)[i],plusover,plusdomainI,plusdomainD) 

并且宏也直接处理intdouble等本机类型。 因此,mpi函数需要适合的框架已经设置为通过它们的实际C运算符(作为宏参数)来区分操作。 所以真实情况不允许使用enum符号。


(*) 礼貌地说,这不是一个很好的方法。 代码依赖于编译器将两个字符串压缩到编译程序的字符串表中的一个位置。 这是编译器要做的典型(有人甚至可能说是显而易见的 )优化,但任何标准都不能保证。 将字符串文字分配给char *变量并在两个地方使用变量会更好(尽管更详细)。 在对结果做任何事情之前,您可以(并且可能应该)测试strstr的结果为“NULL”。

你也可以使用枚举:

 enum MathOps {PLUS, MINUS, MULTIPLY}; MPI mathfunc(MPI x, enum MathOps operation, MPI y) { switch(operation){ case PLUS: //... break; case MINUS: //... break; case MULTIPLAY: // .... break; //etc. } Call: mathfunc(x,PLUS,y) 

这种方法的好处是,您可以轻松地在文件顶部看到您的函数将支持的操作。 如果你添加一个枚举但编译器也会抱怨,但是不要把它添加到可能很好的开关盒中。

编辑:实例: http : //ideone.com/GCJ9ro