简体   繁体   English

如何将存储在数组中的字符串与c中完整库中的函数名称进行比较

[英]How to compare my string, which is stored in an array, to function names from a complete library in c

After I enter a string in c and store it in for example char s[100], how can I compare that string to all function names in a math.h? 在c中输入字符串并将其存储在例如char s [100]之后,如何将该字符串与math.h中的所有函数名称进行比较? For example, I enter pow and the result will look like this in stored form. 例如,我输入pow,结果将以存储形式显示如下。

s[0]='p'
s[1]='o'
s[2]='w'
s[3]='\0'

Since my string is the equivalent of pow(), I want my program to recognise that and then call pow() during execution of my program. 由于我的字符串等效于pow(),因此我希望程序识别出该字符串,然后在程序执行期间调用pow()。 I know it is not that hard to do string comparison within the code, but that would mean that I would have to do string comparison for every function name in the library. 我知道在代码中进行字符串比较并不难,但这意味着我必须对库中的每个函数名称进行字符串比较。 I don't want to do that. 我不想那样做。 How is it possible to compare my string against all names in the library without hard coding every comparison? 如何在不对每个比较进行硬编码的情况下将我的字符串与库中的所有名称进行比较?

Thank you :) 谢谢 :)

You can't, not without doing work yourself. 您不能,除非没有自己做的工作。 There are no names of functions present at runtime in general, and certainly not of functions you haven't called. 通常,在运行时不存在函数名称,当然也没有未调用的函数。

C is not a dynamic language, names are only used when compiling/linking. C不是动态语言,名称仅在编译/链接时使用。

Regular expressions in C C中的正则表达式

Try parsing the header files using FILE and use aforementioned link as a guide to check whether the function exists or not. 尝试使用FILE解析头文件,并使用上述链接作为指南来检查该功能是否存在。

I tried to make a little sample about what I assume the questioner is looking for ( eval.c ): 我试图就假设提问者正在寻找的东西做一些示例( eval.c ):

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

/* mapping function names to function pointers and number of parameters */
struct Entry {
  const char *name; /* function name */
  double (*pFunc)(); /* function pointer */
  int nArgs; /* number of arguments */
} table[] = {
#define REGISTER(FUNC, N_ARGS) { #FUNC, &FUNC, N_ARGS }
  REGISTER(atan2, 2),
  REGISTER(pow, 2),
  REGISTER(modf, 2),
  REGISTER(sin, 1),
  REGISTER(cos, 1)
#undef REGISTER
};
/* let compiler count the number of entries */
enum { sizeTable = sizeof table / sizeof *table };

void printUsage(const char *argv0)
{
  int i;
  printf(
    "Usage:\n"
    "  %s FUNC\n"
    "  where FUNC must be one of:\n", argv0);
  for (i = 0; i < sizeTable; ++i) printf("  - %s\n", table[i].name);
}

int main(int argc, char **argv)
{
  int i;
  char *func;
  struct Entry *pEntry;
  /* read command line argument */
  if (argc <= 1) {
    fprintf(stderr, "ERROR: Missing function argument!\n");
    printUsage(argv[0]);
    return -1;
  }
  func = argv[1];
  /* find function by name */
  for (i = 0; i < sizeTable && strcmp(func, table[i].name) != 0; ++i);
  if (i >= sizeTable) {
    fprintf(stderr, "ERROR! Unknown function '%s'!\n", func);
    printUsage(argv[0]);
    return -1;
  }
  /* perform found function on all (standard) input */
  pEntry = table + i;
  for (;;) { /* endless loop (bail out at EOF or error) */
    switch (pEntry->nArgs) {
      case 1: {
        double arg1, result;
        /* get one argument */
        if (scanf("%lf", &arg1) != 1) {
          int error;
          if (error = !feof(stdin)) fprintf(stderr, "Input ERROR!\n");
          return error; /* bail out at EOF or error */
        }
        /* compute */
        result = (*pEntry->pFunc)(arg1);
        /* output */
        printf("%s(%f): %f\n", pEntry->name, arg1, result);
      } break;
      case 2: {
        double arg1, arg2, result;
        /* get two arguments */
        if (scanf("%lf %lf", &arg1, &arg2) != 2) {
          int error;
          if (error = !feof(stdin)) fprintf(stderr, "Input ERROR!\n");
          return error; /* bail out at EOF or error */
        }
        /* compute */
        result = (*pEntry->pFunc)(arg1, arg2);
        /* output */
        printf("%s(%f, %f): %f\n", pEntry->name, arg1, arg2, result);
      } break;
      default: /* should never happen */
        fprintf(stderr,
          "ERROR! Functions with %d arguments not yet implemented!\n",
          pEntry->nArgs);
        assert(0);
        return -1; /* bail out at error */
    }
  }
}

I compiled and tested this with gcc in cygwin on Windows (64 bit): 我在Windows(64位)上的cygwin中使用gcc进行了编译和测试:

$ gcc -std=c11 -o eval eval.c

$ ./eval
ERROR: Missing function argument!
Usage:
  ./eval FUNC
  where FUNC must be one of:
  - atan2
  - pow
  - modf
  - sin
  - cos

$ echo "1 2 3 4 5 6 7 8 9 10" | ./eval pow
pow(1.000000, 2.000000): 1.000000
pow(3.000000, 4.000000): 81.000000
pow(5.000000, 6.000000): 15625.000000
pow(7.000000, 8.000000): 5764801.000000
pow(9.000000, 10.000000): 3486784401.000000

$ echo "1 2 3 4 5 6 7 8 9 10" | ./eval sin
sin(1.000000): 0.841471
sin(2.000000): 0.909297
sin(3.000000): 0.141120
sin(4.000000): -0.756802
sin(5.000000): -0.958924
sin(6.000000): -0.279415
sin(7.000000): 0.656987
sin(8.000000): 0.989358
sin(9.000000): 0.412118
sin(10.000000): -0.544021

The usage of this application: the name of the function to apply is provided as command line argument. 该应用程序的用法:要应用的函数的名称作为命令行参数提供。 The values (to apply function to) are provided via standard input. 值(将功能应用于)通过标准输入提供。 In the sample session, I used echo and a pipe ( | ) to redirect the output of echo to the input of eval . 在示例会话中,我使用echo和管道( | )将echo的输出重定向到eval的输入。 (If eval is called stand-alone the numbers may be typed in by keyboard.) (如果将eval称为独立,则可以通过键盘输入数字。)

Notes: 笔记:

  1. The table does the actual mapping of strings to function pointers. table将字符串实际映射到函数指针。 To solve that issue about the number of parameters, I considered this in struct Entry also. 为了解决有关参数数量的问题,我也在struct Entry考虑了这一点。

  2. The REGISTER macro is a trick to use the identifier as string constant also. REGISTER宏也是将标识符用作字符串常量的一种技巧。 The #FUNC is a stringize macro-operation (a typical C trick to prevent errors due to typos). #FUNC是一个字符串化宏操作(一种典型的C技巧,可以防止由于错别字引起的错误)。

  3. The sizeTable is another trick to prevent redundant definitions. sizeTable是防止冗余定义的另一个技巧。 I let the compiler count the number of entries. 我让编译器计算条目数。 Thus, new entries may be added and it still will work without any other editing. 因此,可以添加新条目,并且无需任何其他编辑即可继续使用。

  4. The actual trick is to provide a function pointer where the arguments are "left out". 实际的技巧是提供一个函数指针,其中的参数“被忽略”。 When it is called, the correct number of arguments is used and it works. 调用它时,将使用正确数量的参数,并且可以正常工作。 (assuming, of course, the table initialization has been implemented carefully.) However, it would be a pain to do this in C++ because the functions with distinct number of arguments would need an appropriate function pointer with matching signature - horrible casts would be necessary. (当然,假设table初始化已经仔细实现了。)但是,在C ++中这样做很痛苦,因为带有不同数量参数的函数将需要带有匹配签名的适当函数指针-可怕的强制转换。 (Try to compile this with g++ -std=c++11 -c eval.c to see what I mean.) (尝试使用g++ -std=c++11 -c eval.c进行g++ -std=c++11 -c eval.c以了解我的意思。)

  5. For a productive solution, I would sort the entries by names (lexicographically) and apply a binary search (or even use hashing to be faster and more sophisticated). 对于高效的解决方案,我将按名称(按字典顺序)对条目进行排序,并应用二进制搜索(甚至使用散列来更快,更复杂)。 For this sample, I wanted to keep it simple. 对于此样本,我想保持简单。

  6. math.h provides a lot of functions in " float flavor" also. math.h还提供了许多“ float flavour”功能。 These may not be added to this sample without additional effort. 如果不付出额外的努力,可能不会将这些添加到此样本中。 To support other than double arguments 支持除double引数以外的其他参数

    1. some type info had to been added to the table entries 一些类型信息必须添加到表条目中
    2. the type info has to be considered somehow in the switch statement of evaluation. 在评估的switch语句中必须以某种方式考虑类型信息。
  7. ...not to mention functions where argument types are distinct to each other (or return type). ...更不用说参数类型彼此不同(或返回类型)的函数了。 (I cannot remember whether math.h even provides such functions.) (我不记得math.h是否提供了此类功能。)

Btw. 顺便说一句。 this will work for non- math.h functions also... 这也适用于非math.h函数...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM