2017-01-05 6 views
0

Я использую дистрибутив Linux LXLE 14.04. Я хочу написать программу на C, чтобы читать команды, интерпретировать и выполнять их. Я хочу, чтобы программа была эффективной, и я не хочу использовать связанный список . Команды - это операции над наборами. Каждый набор может содержать любое из значений от 0 до 127 включительно. Я решил представить набор как массив символов, содержащий 128 бит. Если бит в положении pos включен, тогда число pos находится в наборе, и если бит в позиции pos выключен, то число pos равно , отсутствующему в наборе. Например, если бит в позиции 4 равен 1, то число 4 присутствует в наборе, если бит в позиции 11 равен 1, тогда число 11 присутствует в наборе.Команды для выполнения функций в C

Программа должна читать команды и интерпретировать их определенным образом. Существует несколько команд: 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; 
} 

Очевидно, что это не очень хорошая практика, чтобы написать кучу заявлений коммутатора и с помощью strtok для каждой команды , и повторяя код, записанный в основной функции для каждой команды, чтобы вызвать разные функции. Я думал об использовании указателя на общую функцию, но поскольку каждая функция получает разные параметры, Я не думаю, что это сработает.

Есть ли лучший способ сделать это?

Заранее благодарен!

Обновление # 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 Yang

+0

Вы можете добавить тестовый случай тоже? – letmutx

+0

'strtok (команда,« read_set »);' Пожалуйста, снова прочтите руководство 'strtok'. Вы не используете его правильно. Он не выполняет совпадение/поиск подстроки. Более подходящей функцией для ваших целей является ['strstr'] (https://linux.die.net/man/3/strstr). – kaylum

+0

Что касается вашего вопроса, то, возможно, лучший способ - определить структуру команд, которая имеет имя команды и указатель функции для каждой команды. И тогда у вас есть массив/список этих структур, которые можно сопоставить в цикле. – kaylum

ответ

-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[]);

+0

У ОП есть еще одна проблема, с которой этот ответ не адресуется: «повторяя код, записанный в основной функции для каждой команды, чтобы вызвать разные функции». То есть, как избежать повторения оператора switch для вызова «print_set, union_set, intersect_set, sub_set и halt». – kaylum

+0

Тогда нужен еще один массив указателей на функции. И вам также нужно преобразовать команды в индексы. Вещи становятся трудными для новичков. @ Kaylum –

+1

Становится ли это трудным или нет, кроме того. Ответ должен адекватно решать вопросы, поднятые вопросом. Предложите вам соответствующим образом обновить свой ответ. – kaylum