Я использую дистрибутив 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
Вы можете добавить тестовый случай тоже? – letmutx
'strtok (команда,« read_set »);' Пожалуйста, снова прочтите руководство 'strtok'. Вы не используете его правильно. Он не выполняет совпадение/поиск подстроки. Более подходящей функцией для ваших целей является ['strstr'] (https://linux.die.net/man/3/strstr). – kaylum
Что касается вашего вопроса, то, возможно, лучший способ - определить структуру команд, которая имеет имя команды и указатель функции для каждой команды. И тогда у вас есть массив/список этих структур, которые можно сопоставить в цикле. – kaylum