[C]字符串指令解释器

byAlex Feb2013 GNU GCC 、 MDK编译测试

这是一个通用字符串指令解释器,并且已经实现了四条指令(help、ver、echo、sort),方便移植的时候测试。


C++测试例程

#include <iostream>
#include <cstdio>
extern "C"{
    #include "interpretor.h"
}
using namespace std;
extern char itpin[ITPBUFSZ],itpout[ITPBUFSZ];
int main(void){
    do{
        cout<<"$ ";
        gets(itpin);
        interpret();
        cout<<itpout;
    }while(1);
    return 0;
}


C嵌入式应用例程(_recv函数片段,应用于telnet指令解释):

	  for(_di=0;_di<name->length;_di++)itpin[_di]=*(name->bytes+_di);
	  itpin[_di]='\0';
	  interpret();
	  tcp_write(pcb, itpout, strlen(itpout), 1);

FAQ

怎样编写一条指令?

所有需要的数据(至少是目前已知的)都在itpin数组中,借助已有的工具函数提取需要的信息,经过特定算法的加工产生了指令的结果反馈,然后通过格式化的输出方式输出到itpout数组中(如借用sprintf,strcat等),这样一条指令的处理流程就完成了。

如何添加指令?

  1. 仿照其他指令编写相应函数
  2. 仿照其他指令在mycmds中添加 “名称-指针 对”

它支持怎样形式的指令?
一般类似于UNIX 或者DOS的命令,即以一个指令的关键字开头,后面跟上若干参数,互相以至少一个空格相隔。
指令缓冲区默认设置了256字节的长度,也就是可以输入255个字符,如果需要修改,只要修改ITPBUFSZ宏就可以了。
提供了几个工具函数:获得参数、获得整数型参数、获得参数位置、获得参数个数
这也就意味着目前可以支持的解释功能有:自动映射指令处理程序、处理可变参数、处理数字(正数,可带一个字符的后缀,如 200m)

为什么采用“名称-指针 对”结构数组完成指令的映射?
通过这样的结构最简单得实现了指令的 自动映射,如果要添加一个指令,不需要修改interpret函数了,写好对应处理程序,再加一条映射就可以了。
如果需要枚举所有支持的指令也很简单,见help指令的实现。

interpretor.h

#ifndef __INTERPRETOR_H_
#define __INTERPRETOR_H_
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define ITPBUFSZ 256 //输入/输出缓冲区大小
#define ITPARGSZ 80 //参数(单个)缓冲大小 
#define ITPISTSZ 12 //表示整数的字符串大小
void interpret(void); //从itpin读取指令解释执行并把结果输出到itpout
#endif

interpretor.c

#include "interpretor.h"
char itpin[ITPBUFSZ],itpout[ITPBUFSZ]; //输入/输出缓冲区
int itpatoi(char *suf,const char *loc); //从loc所指向的位置开始截取一个参数,转换成整数型返回,并把后缀字符(如果存在)输出到suf
char* itpstrcpy(char *buf,const char *loc);//从loc所指向的位置开始截取一个参数,复制到buf,并返回指向buf的指针
char* itploc(int i); //获取指向第i个参数的指针
int itpargc(void); //获取参数个数

//help指令:help
//显示解释器具体实现的功能,并枚举所有已映射指令
void helpcmd(void);
//ver指令:ver
//显示版本等信息
void vercmd(void){
	strcpy(itpout,"TELROV byAlex Feb. 2013\r\n");
}
//sort指令(可以用来测试整型参数提取(itpatoi函数)是否正确运行):sort ...
//升序排序正整数整数并输出(用一个空格隔开),例:
//sort 40 33  21
//21 33 40
void sortcmd(void){
	int data[25],n,i,j,t;
	char stmp[ITPISTSZ];
	n=itpargc()-1;
	if(n>0){
		for(i=0;i<n;i++)data[i]=itpatoi(NULL,itploc(i+1));
		for(i=n-1;i>0;i--){
			for(j=0;j<=i;j++){
				if(data[j]>data[i]){
					t=data[j];
					data[j]=data[i];
					data[i]=t;
				}
			}
		}
		itpout[0]='\0';
		for(i=0;i<n;i++){
			sprintf(stmp,"%d ",data[i]);
			strcat(itpout,stmp);
		}
		strcat(itpout,"\r\n");
	}
	else strcpy(itpout,"No data.\r\n");
}
//echo指令(可以用来测试参数提取(itpstrcpy函数)是否正确运行):echo ...
//按照原来的次序输出各个参数(用一个空格隔开),例:
//echo quick   brown   fox   jumps   over the lazy dog
//quick brown fox jumps over the lazy dog
void echocmd(void){
	int n,i;
	char stmp[ITPARGSZ];
	n=itpargc()-1;
	if(n>0){
		itpout[0]='\0';
		for(i=0;i<n;i++){
			itpstrcpy(stmp,itploc(i+1));
			strcat(itpout,stmp);
			strcat(itpout," ");
		}
		strcat(itpout,"\r\n");
	}
	else itpout[0]='\0';
}
//已映射的指令个数
#define CMDCT (sizeof(mycmds)/sizeof(struct mycmd))
//指令映射(“名称-指针 对”形式的结构数组)
struct mycmd{
	char *name;
    void (*func)(void);
}
mycmds[]={
	{"help",helpcmd},
	{"ver",vercmd},
	{"sort",sortcmd},
	{"echo",echocmd}
};
//help指令:help
//显示解释器具体实现的功能,并枚举所有已映射指令
void helpcmd(void){
	int rmsp,i;
	const char description[]="TELROV:Rover commander using telnet.\r\n";
	strcpy(itpout,description);
	rmsp=ITPBUFSZ-7-strlen(description);
	for(i=0;i<CMDCT;i++){
		if(rmsp>strlen(mycmds[i].name)){
			strcat(itpout,mycmds[i].name);
			strcat(itpout,"\t");
		}
		else break;
	}
	if(i!=CMDCT)strcat(itpout," ...");
	strcat(itpout,"\r\n");
}
//从itpin读取指令解释执行并把结果输出到itpout
void interpret(void){
	int icmd;char stmp[ITPARGSZ];
	if(itpargc()>0){
		itpstrcpy(stmp,itploc(0));
		for(icmd=0;icmd<CMDCT;icmd++)if(strcmp(stmp,mycmds[icmd].name)==0)break;
		if(icmd<CMDCT)mycmds[icmd].func();
		else{
			strcpy(itpout,"Uninterpretable:'");
			strcat(itpout,stmp);
			strcat(itpout,"'\r\n");
		}
	}
	else itpout[0]='\0';
}
//从loc所指向的位置开始截取一个参数,复制到buf,并返回指向buf的指针
char* itpstrcpy(char *buf,const char *loc){
	const char *p;int i=0;
	if(buf==NULL||loc==NULL)return NULL;
	else
        for(p=loc;*p!=' '&&*p!='\r'&&*p!='\n'&&*p!='\0';p++)
            buf[i++]=*p;
	buf[i]='\0';
	return buf;
}
//从loc所指向的位置开始截取一个参数,转换成整数型返回,并把后缀字符(如果存在)输出到suf
int itpatoi(char *suf,const char *loc){
	char strn[ITPISTSZ];int i=0;const char *p;
	if(loc==NULL)return suf!=NULL?(*suf=0):0;
	else{
		for(p=loc;*p!=' '&&*p!='\r'&&*p!='\n'&&*p!='\0';p++){
			if(*p>='0'&&*p<='9')strn[i++]=*p;
			else if(suf!=NULL){*suf=*p;break;}
		}
		strn[i]='\0';
		return atoi(strn);
	}
}
//获取指向第i个参数的指针
char* itploc(int i){
	char *p,pre=' ';int ct=0;
	for(p=itpin;*p!='\0';p++){
		if(*p!=' '){if(*p!='\r'&&*p!='\n'&&ct==i)return p;}
		else if(pre!=' ')ct++;
		pre=*p;
	}
	return NULL;
}
//获取参数个数
int itpargc(void){
	const char *p;char pre=' ';int ct=0;
	for(p=itpin;*p!='\0';p++){
		if(*p!=' '){
			if(*p=='\r'||*p=='\n')break;
			if(pre==' ')ct++;
		}
		pre=*p;
	}
	return ct;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值