【原创】自制编程语言-5 变量的赋值(1)
首先我们先看这个函数:
void put_value(const char *name){
for(int i=0;i<value_ptr;i++){
if(strcmp(value[i].name,s)==0){
if(value[i].type==0)printf("%d",value[i].vnum);
else printf("%s",value[i].vstring);
}
}
}
这个函数写得不是很好,因为首先根据变量名找变量的功能可能会在很多情况下使用到,每次都写一个for循环很麻烦,所以,我们可以单独把这个功能提取出来,写成一个函数的形式。
至于函数名,就叫getpos吧。pos是position的缩写。
int getpos(const char *vname){
for(int i=0;i<value_ptr;i++){
if(strcmp(value[i].name,vname)==0)return i;//下标
}
return -1;//未找到
}
根据变量名,反复的循环比较变量名,直到找到正确的数字,返回这个下标。如果没有,返回-1。
根据这段代码,我们就可以简化put_value。
void put_value(const char *name){
int i=getpos(name);
if(i==-1)error();
if(value[i].type==0)printf("%d",value[i].vnum);
else printf("%s",value[i].vstring);
}
我们来运行一下试试。结果应该还是正常的。接下来我们就进入正题,变量的赋值语句。一般的赋值语句应该都长成这样:
变量名 = 表达式
为了读入方便,这里规定:变量名和"="和后面的表达式中间必须加上空格,这样直接用scanf("%s")就可以读入了,不用人工分割单词。
else if(isvalue(s)){//变量的赋值语句
char sa[255],sb[255];
get_word(sa);get_word(sb);
if(strcmp(sa,"=")!=0)error();
if(value[getpos(s)].type==0)value[getpos(s)].vnum=getnum(sb);
else {
sb[strlen(sb)-1]='\0';//去掉最后的双引号
strcpy(value[getpos(s)].vstring,sb+1);//复制的时候去掉前面的双引号
}
}
首先读入sa和sb,s存放要赋值的变量,sa存放等号,sb存放后面的表达式。这里,分两种情况进行赋值。如果是数字,把表达式sb求出数字,放入value,如果是字符串,去掉前后引号放进去。
然后是getnum。这个函数需要实现表达式求值的功能。例如,
a = 1+2*3+4
这样的语句,必须根据运算优先级求出这样长的表达式。当然,我们一步一步来,先实现把一个字符串转换为常数的功能。
int getnum(const char *s){
int i;
sscanf(s,"%d",&i);
return i;
}
实际上,把一个字符串转换为常数非常简单,使用sscanf往字符串读入常数即可。关于sscanf的用法,可以自行在网上搜索。
我们用如下的代码测试一个:
dim a as int
dim str as string
a = 123
str = "hello"
print a
print str
exit
运行非常成功,输出“123hello”。完。
顺便把完整版代码贴一下,一共109行。
#include<bits/stdc++.h>
using namespace std;
char s[100];
struct VALUE{
char name[30];//变量名
int type;//类型,0表示int,1表示string
int vnum;//int类型的数值
char vstring[255];//string类型
};
int value_ptr=0;
struct VALUE value[1000];
void get_word(char *s){//读入单词
scanf("%s",s);
}
void get_string(char *s){
int i=0,flag=0;
for(i=0;i<100;i++){
next:
s[i]=getchar();
if(flag==0 && s[i]==' ')goto next;
else flag=1;
if(s[i]=='\n')break;
}
s[i]='\0';//结束掉字符串
}
void error(){
cout<<"Error in program.\n";
exit(0);//退出程序
}
int isnumber(const char *s){
for(int i=0;i<strlen(s);i++)
if(s[i]<='0' || s[i]>='9')return 0;//不是数字字符
return 1;
}
int isvalue(const char *s){
for(int i=0;i<value_ptr;i++){
if(strcmp(value[i].name,s)==0)return 1;
}
return 0;
}
int getpos(const char *vname){
for(int i=0;i<value_ptr;i++){
if(strcmp(value[i].name,vname)==0)return i;//下标
}
return -1;//未找到
}
void put_value(const char *name){
int i=getpos(name);
if(i==-1)error();
if(value[i].type==0)printf("%d",value[i].vnum);
else printf("%s",value[i].vstring);
}
int getnum(const char *s){
int i;
sscanf(s,"%d",&i);
return i;
}
int main(int argc,char** argv){
if(argc!=2){//有一个要解释的文件参数
cout<<"Cannot find source file.\n";
return 0;
}
freopen(argv[1],"r",stdin);
for(;;){
get_word(s);
if(strcmp(s,"print")==0){//调用print输出
get_string(s);
if(isnumber(s))cout<<s;
else if(s[0]=='\"' && s[strlen(s)-1]=='\"'){
for(int i=1;i<strlen(s)-1;i++){
if(s[i]=='\\' && s[i+1]=='n'){
printf("\n");i++;
}
else printf("%c",s[i]);
}
}
else if(isvalue(s)){
put_value(s);
}
else error();
}
else if(strcmp(s,"exit")==0){//退出程序
return 0;
}
else if(strcmp(s,"dim")==0){//声明变量
char sa[255],sb[255],sc[255];
get_word(sa);get_word(sb);get_word(sc);
if(strcmp(sb,"as")!=0)error();
strcpy(value[value_ptr].name,sa);
if(strcmp(sc,"int")==0)value[value_ptr].type=0;
else if(strcmp(sc,"string")==0)value[value_ptr].type=1;
else error();
value_ptr++;
}
else if(isvalue(s)){//变量的赋值语句
char sa[255],sb[255];
get_word(sa);get_word(sb);
if(strcmp(sa,"=")!=0)error();
if(value[getpos(s)].type==0)value[getpos(s)].vnum=getnum(sb);
else {
sb[strlen(sb)-1]='\0';//去掉最后的双引号
strcpy(value[getpos(s)].vstring,sb+1);//复制的时候去掉前面的双引号
}
}
else{
error();
}
}
}