简体   繁体   中英

Commands to execute functions in C

I'm using the LXLE 14.04 distribution of Linux. I want to write a C program to read commands, interpret and perform them. I'd like the program to be efficient, and I do not want to use a linked list. The commands are operations on sets. Each set can contain any of the values from 0 through 127 inclusive. I decided to represent a set as an array of characters, containing 128 bits. If bit at position pos is turned on then the number pos is in the set and if the bit at position pos is turned off then the number pos is not present in the set. For example, if the bit at position 4 is 1, then the number 4 is present in the set, if the bit at position 11 is 1 then the number 11 is present in the set.

The program should read commands and interpret them in a certain way. There are a few commands: read_set, print_set, union_set, intersect_set, sub_set and halt.

For example, the command read_set A,1,2,14,-1 in the terminal will cause the reading of values of the list into the specified set in the command. In this case the specified set in the command is A. The end of the list is represented by -1. So after writing this command, the set A will contain the elements 1,2,14.

This is what I have so far. Below is the file set.h

#include <stdio.h>

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



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

This is the file 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;
}

Clearly, it is not a good practice to write a bunch of switch statements and using strtok for each command, and repeating the code written in the main function for each command in order to call the different functions. I thought about using a pointer to a generic function, but since each function receives different parameters, I do not think this is going to work.

Is there a better way of doing this?

Thanks in advance!

Update #1: Here's the code. I've made some changes to it.

#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;
}

I get the following compile error: main.c:9:8: error: expected = , , , ; , asm or attribute before . token

What's my mistake? How can I fix this?

Thanks a lot! @Claim Yang

However,in your case, using switch is almost the best solution to this.

Another way without switch is using a simple way to get an index. Here is a simple solution.

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

Then if you need to read a command, another array of pointers to functions is needed. Like below:

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

And so on. The point is coverting your string to an int , so it can be seen as an index of an array.

Then call functions like functions[string_to_int(string)](set,char[]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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