【问题标题】:Commands to execute functions in C在 C 中执行函数的命令
【发布时间】:2017-05-19 19:14:16
【问题描述】:

我正在使用 Linux 的 LXLE 14.04 发行版。 我想编写一个 C 程序来读取命令、解释并执行它们。我希望程序高效,但我不想使用 一个链表。 命令是对集合的操作。 每个集合可以包含从 0 到 127 的任何值(包括 0 到 127)。 我决定将一个集合表示为一个字符数组,包含 128 位。 如果位置 pos 的位打开,则数字 pos 在集合中,如果位置 pos 的位关闭,则数字 pos 是 不存在于集合中。例如,如果位置 4 的位为 1,则数字 4 存在于集合中,如果位置 11 的位为 1,则数字 集合中有 11 个。

程序应该读取命令并以某种方式解释它们。 有几个命令:read_set、print_set、union_set、intersect_set、sub_set 和 halt。

例如,终端中的命令 read_set A,1,2,14,-1 将导致将列表的值读取到命令中的指定集合中。 在这种情况下,命令中指定的集合是 A。列表的结尾由 -1 表示。所以写完这个命令后,集合 A 将包含元素 1,2,14。

这是我目前所拥有的。 下面是文件set.h

#include <stdio.h>

typedef struct
{
    char array[16]; /*Takes 128 bits of storage*/
}set;



extern set A , B , C , D , E , F;

这是 main.c 文件

#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>

set A , B , C , D , E , F; /*Variable definition*/




   void read_set(set s,char command[])
   {
        int i, number = 0 , pos; 

        char* str_num = strtok(NULL,"A, ");
        unsigned int flag = 1; 
        printf("I am in the function read_set right now\n");

        while(str_num != NULL) /*without str_num != NULL get        segmentation fault*/
       {
            number = atoi(str_num);
            if(number == -1)
                return;
             printf("number%d ",number);
             printf("str_num %c\n",*str_num);
            i = number/8;     /*Array index*/
            pos = number%8;  /*bit position*/
            flag = flag << pos;
            s.array[i] = s.array[i] | flag;

            str_num = strtok(NULL, ", ");

           if(s.array[i] & flag)
               printf("Bit at position %d is turned on\n",pos);
         else
            printf("Bit at position %d is turned off\n",pos);
       flag = 1;
    }

}

void print_set(set s)
{
    unsigned int flag = 1; int in_set = 0;
    int i = 0;
    while(s.array[i] != -1)
    {
        if(s.array[i] & flag)
        {
              in_set = s.array[i];
              printf("%d,",in_set );
        }
       i++;
      flag = 1;
   }

}
int main()
{ 
    #define CMD_LENGTH 256

    char command[CMD_LENGTH]; char* letter;
    printf("Please enter a command");
    gets(command);
    letter = strtok(command,"read_set ,");
    switch(*letter)
    {
        case 'A':
        {
           read_set(A,command);
            break;
       }
       case 'B':
       {
            read_set(B,command);
            break;
       }
       case 'C':
       {
         read_set(C,command);
         break;
        }
        case 'D':
        {
          read_set(D,command);
           break;
        }
       case 'E':
       {
           read_set(E,command);
           break;
       }
      case 'F':
      {
           read_set(F,command);
           break;
       }

   }



    return 0;
}

显然,为每个命令编写一堆 switch 语句并使用 strtok,并为每个命令重复编写在 main 函数中的代码以调用不同的函数,这不是一个好习惯。我考虑过使用指向泛型函数的指针,但由于每个函数接收不同的参数, 我认为这行不通。

有没有更好的方法来做到这一点?

提前致谢!

更新 #1: 这是代码。我已经对其进行了一些更改。

#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>

set A , B , C , D , E , F; /*Variable definition*/
set sets[6];
/*Below I want to initialize  sets so that set[0] = A set[1] =    B     etc*/
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;

void read_set(set s,char all_command[])
{
    int i, number = 0 , pos; 

    char* str_num = strtok(NULL,"A, ");
    unsigned int flag = 1; 
    printf("I am in the function read_set right now\n");

while(str_num != NULL) /*without str_num != NULL get segmentation fault*/
{ 
        number = atoi(str_num);
         if(number == -1)
        return;
       printf("number%d ",number);
       printf("str_num %c\n",*str_num);
       i = number/8;     /*Array index*/
       pos = number%8;  /*bit position*/
       flag = flag << pos;
      s.array[i] = s.array[i] | flag;

       str_num = strtok(NULL, ", ");

       if(s.array[i] & flag)
           printf("Bit at position %d is turned on\n",pos);
      else
         printf("Bit at position %d is turned off\n",pos);
       flag = 1;
    }

}


typedef struct 
{
    char *command;
    void (*func)(set,char*);
} entry;

entry chart[] = { {"read_set",&read_set} };

void (*getFunc(char *comm) ) (set,char*)
{
   int i;
   for(i=0; i<2; i++)
   {
       if( strcmp(chart[i].command,comm) == 0)
            return chart[i].func;
   }
   return NULL;
}

int main()
{

   #define PER_CMD 256

    char all_comm[PER_CMD];    void (*ptr_one)(set,char*) = NULL; char* comm; char* letter; 

    while(  (strcmp(all_comm,"halt") != 0 ) & (all_comm != NULL))
    {
        printf("Please enter a command");
        gets(all_comm);
        comm = strtok(all_comm,", ");
        ptr_one = getFunc(comm);
        letter = strtok(NULL,",");
        ptr_one(A,all_comm);
        all_comm[0] = '\0';
        letter[0] = '\0';
    }

    return 0;
}

我收到以下编译错误: main.c:9:8:错误:预期 ��=���、��、����、��;��、��asm��� 或��属性���� 在��.�� 标记之前

我的错误是什么?我该如何解决这个问题?

非常感谢! @Claim 杨

【问题讨论】:

  • 你也可以添加一个测试用例吗?
  • strtok(command,"read_set ,"); 请再次阅读strtok 手册。您没有正确使用它。它不进行子字符串匹配/搜索。更适合您的目的的函数是strstr
  • 至于您的问题,可以说更好的方法是定义一个命令结构,该结构具有每个命令的命令名称和函数指针。然后有一个可以在循环中匹配的这些结构的数组/列表。
  • 非常感谢!我一直在尝试创建一个结构,其中包含指向函数的指针数组,例如 typedef struct { void(*functions[6])(set,char[]); }命令;每个数组元素都包含一个对应于某个命令的函数。我不确定如何从这里开始以及如何防止代码重复。我做错了吗?你能更详细地解释一下吗?谢谢!
  • 我阅读了手册,但我似乎无法弄清楚为什么我以错误的方式使用 strtok。我的错误是什么?谢谢!

标签: c function set command


【解决方案1】:

但是,在您的情况下,使用 switch 几乎是解决此问题的最佳方法。

没有switch 的另一种方法是使用一种简单的方法来获取索引。这是一个简单的解决方案。

set sets[6];
read_set(sets[*letter - 'A'], command);

然后,如果您需要读取命令,则需要另一个指向函数的指针数组。如下:

void (*functions[3])(set,char[]);
functions[0] = read_set;

等等。 重点是将您的string 转换为int,因此可以将其视为数组的索引。

然后调用functions[string_to_int(string)](set,char[]);之类的函数

【讨论】:

  • OP 还有另一个问题,这个答案没有解决:“为每个命令重复编写在 main 函数中的代码以调用不同的函数”。即如何避免重复switch语句调用“print_set、union_set、intersect_set、sub_set和halt”。
  • 然后需要另一个指向函数的指针数组。您还需要将命令转换为索引。对于初学者来说,事情变得越来越困难..@kaylum
  • 它是否变得困难是无关紧要的。答案应充分解决问题提出的问题。建议您相应地更新您的答案。
  • 据我了解,集合将包含字符“A”到“F”。
  • 可以,但是你可以更改将char转换为整数而不是*letter - 'A'的规则,并扩大sets.@Tree的大小
猜你喜欢
  • 2017-11-30
  • 2012-11-06
  • 2015-03-06
  • 2015-05-13
  • 2016-02-04
  • 1970-01-01
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
相关资源
最近更新 更多