由于最近上班比较无聊,遂想起朋友写电梯程序来打发时间,因此我也花了一天的时间搞一个电梯程序。
我的基本思路是,在程序的初始化阶段起两个线程,一个是用户输出线程,另一个是电梯运行线程。
这两个线程共享一个电梯(结构体),用户输出的命令会根据自己定下的规则加入到命令链表中,电梯线程会根据链表的命令执行。
以下是代码部分,有基详细注释
Main.c
#include "lift.h"
void main(){
// printf("begin\n"); initThreads();
waitThreads();
// while(1);
}
lift.h
#ifndef _LIFT_H_
#define _LIFT_H_
#include
#include
#include
#include
typedef enum{
STATUS_STAT = 0,
STATUS_STOPPING,
STATUS_RUNNING,
STATUS_WAITTING,
STATUS_END
}RUN_STATUS_E;
typedef enum{
DIRECTION_START = 0,
DIRECTION_UP,
DIRECTION_DOWN,
DIRECTION_NULL,
DIRECTION_END
}DIRECTION_E;
typedef struct _COMMAND_T{
int floor;
DIRECTION_E direction;
struct _COMMAND_T *next;
}COMMAND_T;
typedef struct _ONE_LIFT_T{
RUN_STATUS_E status; //current
status
int floor; //current floor
COMMAND_T* commands; //receive commands
DIRECTION_E direction; //running direction
}ONE_LIFT_T;
void initThreads();
void waitThreads();
COMMAND_T* creatCmd();
int addCmd(COMMAND_T* root , COMMAND_T* node);
int delCmd(COMMAND_T** root , int site);
int delFirstCmd(COMMAND_T** root);
#endif
lift.c
#include "lift.h"
ONE_LIFT_T *lift = NULL;
pthread_t lift_thread;
pthread_t user_thread;
ONE_LIFT_T* creatLift(){
ONE_LIFT_T *lift;
lift =
(ONE_LIFT_T*)malloc(sizeof(ONE_LIFT_T));
lift->status = STATUS_STOPPING;
lift->floor = 1;
lift->commands = creatCmd("1-"); //default
floor on 1
lift->direction = DIRECTION_NULL;
return lift;
}
void *liftThread(void* p){
ONE_LIFT_T *_lift = (ONE_LIFT_T*)p;
printf("lift cur floor is
%d\n",_lift->commands->floor);
while(1){
if(_lift->commands !=
NULL){
if(_lift->commands->next
!= NULL){
_lift->status
= STATUS_RUNNING; //set lift status
if(_lift->commands->floor
< _lift->commands->next->floor){
_lift->commands->floor++;
_lift->commands->direction
= DIRECTION_UP; //set lift running direction
}
else
if(_lift->commands->floor >
_lift->commands->next->floor){
_lift->commands->floor--;
_lift->commands->direction
= DIRECTION_DOWN;
}
else{
//_lift->commands->floor ==
_lift->commands->next->floor
delFirstCmd(&(_lift->commands));
printf("lift
is arrive : %d\n",_lift->commands->floor);
if(_lift->commands->next
!= NULL){
_lift->status
= STATUS_WAITTING;
}
else{
_lift->status
= STATUS_STOPPING;
_lift->commands->direction
= DIRECTION_NULL;
}
}
printf("lift
cur floor is %d\n",_lift->commands->floor);
}
}
sleep(2); //arrive next floor
need 2 sec
}
}
void *userThread(void* p){
ONE_LIFT_T *_lift = (ONE_LIFT_T*)p;
int ret;
while(1){
char
cmd[2];
scanf("%s",cmd);
//这里使用正则表达式最好
if((cmd[0]
>= '1' && cmd[0] <= '9') &&
(cmd[1] == '-' || cmd[1] == '+' || cmd[1] == '*') &&
(strlen(cmd) <= 2)
){
//if
user input correct cmd , it will create a cmd to list
ret
= addCmd(_lift->commands,creatCmd(cmd));
if(ret
!= 0)
printf("Add
user command fail!\nIt may be full!\n");
}
else{
printf("Usage:
nd n(1~9) d(-,+)\n"); }
}
}
void initThreads(){
lift = creatLift();
int ret;
ret =
pthread_create(&lift_thread,NULL,liftThread,(void*)lift);
if(ret != 0){
printf("Create lift thread
fail!\n"); }
ret =
pthread_create(&user_thread,NULL,userThread,(void*)lift);
if(ret != 0){
printf("Create user thread
fail!\n"); }
}
void waitThreads(){
if(lift_thread != 0){
pthread_join(lift_thread,NULL); } if(user_thread != 0){
pthread_join(user_thread,NULL); } }
lift_cmd.c
#include "lift.h"
COMMAND_T* creatCmd(char *u_cmd){
COMMAND_T* cmd;
cmd =
(COMMAND_T*)malloc(sizeof(COMMAND_T));
cmd->floor = u_cmd[0] - '0';
if(u_cmd[1] == '-'){ //user pressthe button out
side the lift and want to down
cmd->direction =
DIRECTION_DOWN; }
else if(u_cmd[1] == '+'){ //user
pressthe button out side the lift and want to up
cmd->direction =
DIRECTION_UP;
}
else if(u_cmd[1] == '*'){ //user
press the button in lift
cmd->direction =
DIRECTION_NULL;
}
cmd->next = NULL;
return cmd;
}
int addCmd(COMMAND_T* root , COMMAND_T* node){
COMMAND_T *cur = root;
COMMAND_T *tmp = root->next;
if(root->next == NULL){
cur->next = node;
return 0;
}
int nextFloor = cur->next->floor;
int addFloor = node->floor;
DIRECTION_E nextDire =
cur->next->direction;
DIRECTION_E addDire = node->direction;
if(addDire == DIRECTION_NULL){
cur->next = node;
node->next = tmp;
if(nextFloor >
addFloor)
tmp->direction
= DIRECTION_UP;
else if(nextFloor <
addFloor)
tmp->direction
= DIRECTION_DOWN;
}
else if(nextDire == addDire){
cur->next = node;
node->next = tmp;
}
else{
addCmd(cur->next,node);
}
return 0;
}
int delFirstCmd(COMMAND_T** root){
return delCmd(root,0);
}
int delCmd(COMMAND_T** root , int site){
COMMAND_T **cur = root;
COMMAND_T *tmp = *cur;
if(site == 0){
(*root) =
(*root)->next;
free(tmp);
return 0;
}
int _site = site - 1;
while(_site--){
if((*cur)->next ==
NULL)
return
-1; //no exist this floor
(*cur) =
(*cur)->next;
}
(tmp) = (*cur)->next;
if((tmp)->next != NULL){
(*cur)->next =
(tmp)->next;
}
else{
(*cur)->next = NULL;
} free(tmp);
return 0;
}