将字符串转换为C中的代码行

我试图找到一种方法将字符串转换为我的代码行。

例如,我想尝试像这样:

int x=3; char str[80]; gets(str); // Assuming the user gives input: "x + 3" y = str; printf("%d",y); // Output: "6" (3 + 3) 

这样程序输出“6”(3 + 3)。 我想建立一个function绘图仪。但在这里我卡住了,找不到任何办法。 你能告诉我一种将这些字符串转换为代码行的方法吗?

你想做的是表达评估 。 我建议使用2种方法来帮助您更接近预期的解决方案。

  1. 使用二叉树评估表达式:构建一个表示运算符之间的表达式和优先级的树。

  2. 可能是上面提到的。 波兰forms,基于堆栈的评估。 首先使用堆栈构建原始表达式的抛光forms,然后再次使用堆栈评估抛光forms。 最后一个:使用google与这些keywoards 🙂

那是不可能的。 C不是reflection语言,也没有任何eval()

您当然可以调用外部编译器并运行生成的程序,或者您可以尝试在程序中找到包含C编译器的编译器库,但是没有“本机”解决方案。

AC程序被静态编译一次,并且编译的二进制文件不保留它用C语言编写的事实。编译过程完全与程序运行时无关。 通常,只有解释型语言才提供eval() ,因为解释器在程序执行期间处于活动状态,并且可以动态操作程序代码。 在像C这样的编译语言中,这整个想法都不适合,甚至没有意义。

如果你想编写一个计算器,你必须实现自己的解析器和计算逻辑。

您必须自己解析和评估表达式。 C ++不会推迟到运行时它在编译时可以做什么。

你不能动态编译或评估用C编写的代码(实际上你可以,但它并不是那么简单,因为它要求你嵌入编译器或解释器)。 最好的方法是使用Lua,Python,JavaScript等脚本语言。

Lua有一个用C编写的很好的解释器,它很小而且很快(暴雪使用它来编写WoW脚本)。 如果您需要更高的性能,请查看V8,这是Google Chrome的JavaScript引擎,它是一个高级脚本引擎,具有JIT编译function等等。 或者您可以使用Python,Perl,Ruby甚至PHP。 使用脚本语言的缺点是,您必须学习第二语言才能构建您的程序,但好处很快就会显现出来。

请注意,这些只是少数几个例子,但是有成千上万的库可以很好地完成这项工作,您必须确定哪个库最适合您的特定需求。

 #include  #include  #include  #include  /* int replace(source_string, search_string, replace_string, start_position, replace_limit, ignore_case, output_buff) return value : count of replace */ int replace(const char *s, const char *find, const char *rep, size_t pos, int count, int ignore, char *buff){ size_t i, len_f, len_r; int rep_count=0; int (*cmp)(const char*, const char*, size_t); cmp = (ignore) ? strnicmp : strncmp; len_f = strlen(find); len_r = strlen(rep); for(i=0;i 54 */ char cstack[STACKSIZE]; /* op stack */ int vstack[STACKSIZE]; /* value stack */ int vsp,csp; int level; int sign=0; int wk=0; char buff[MAXLEN]; char *p,*pwk,cwk; /* trim */ for(pwk=p=str;*p;p++) if(*p=='\t' || *p==' ') continue; else *pwk++=*p; *pwk=*p; vsp=csp=STACKSIZE; cstack[--csp]='@';/* empty mark */ p=str; while(*p){ if(isdigit(*p)){ if(sign==0)sign=1; wk=wk*10+ *p++ - '0'; } else { /* Characters except the number of occurrences -> determined the number */ if(sign!=0)vstack[--vsp]=sign*wk; /* push num */ wk=0; /* wk initialize for next step */ sign=0; switch(*p){ case '*': case '/': cwk=cstack[csp]; if(cwk=='@' || cwk=='+' || cwk=='-') cstack[--csp]=*p; else{ if(cwk=='*') vstack[vsp+1]*=vstack[vsp]; else if(cwk=='/') vstack[vsp+1]/=vstack[vsp]; vsp++; cstack[csp]=*p; } p++; break; case '-': if(str==p){ sign=-1; p++; break; } else if(NULL!=strchr("*/+-",*(p-1))){ sign=-1; p++; break; } case '+': cwk=cstack[csp]; if(cwk=='@') cstack[--csp]=*p; else { switch(cwk){ case '+': vstack[vsp+1]+=vstack[vsp];break; case '-': vstack[vsp+1]-=vstack[vsp];break; case '*': vstack[vsp+1]*=vstack[vsp];break; case '/': vstack[vsp+1]/=vstack[vsp];break; } vsp++; cstack[csp]=*p; } p++; break; case '(': /* (expression) -> call calc(expression) */ p++; level=1; sign=1; for(pwk=buff;*p;p++){ if(*p==')'){ if(--level==0){ *pwk='\0'; wk=calc(buff); break; } } else if(*p=='('){ level++; } *pwk++=*p; } if(level){/* paren unmatch */ *pwk='\0'; wk=calc(buff); } else p++; break; case ')':/* never */ p++; fprintf(stderr,"too many ')'\n"); break; default: fprintf(stderr, "'%c'is not allowed\n",*p++); } } } vstack[--vsp]=sign*wk; while('@'!=(cwk=cstack[csp++])){ switch(cwk){ case '+': vstack[vsp+1]+=vstack[vsp];break; case '-': vstack[vsp+1]-=vstack[vsp];break; case '*': vstack[vsp+1]*=vstack[vsp];break; case '/': vstack[vsp+1]/=vstack[vsp];break; } vsp++; } return (vstack[vsp]); } int main(void){ int x = 3, y; char str[128]; char buff[128]; char strX[16]; sprintf(strX, "%d", x); gets(str); replace(str, "x", strX, 0, -1, 1, buff); y = calc(buff); printf("%d\n", y); return 0; } 

DEMO

 >calc x + 3 6 >calc x * x + 2 * x + 1 16 >calc (3+5)*7-2 54 

根据我的理解,您希望在运行时替换用户在程序标准输入上提供的任何内容。 在您的示例中,用户将键入类似下面的内容(在程序命令提示符下):

 (x+3); 

然后你的第四行代码如下:

 y = (x+3); // assuming y was declared as an integer somewhere before 

它不可能用C或C ++或任何静态编译的语言。 您的编译过程已经发生,必须先成功完成才能进入运行时。 因此,如果您能够修改源代码,则必须重新编译才能在考虑新行的情况下执行代码。 显然不是解决问题的好方法。

如果您确定要/必须在C中执行此操作而不是某种解释语言,请查看Lex和Yacc。

正如其他人已经说过的那样,C不是解释语言,因此您不能使用C来立即解释命令。 换句话说,你必须用C语言提供(开发)一个翻译。

Lexx和Yacc大大简化了编写口译员的过程,虽然这是一个相当有利的话题,我担心。

在这里寻找一个入门者: http : //epaperpress.com/lexandyacc/

最重要的是,我相信你不太了解你想要解决的问题…阅读更多关于口译员的信息

首先,本地x在其块之外是不可见的,所以即使你有一些神奇的元编程评估器,你也无法做到你想要的。

除了其他人建议的内容(编写您的域特定语言,嵌入现有的解释器,……) – 并假设您使用Linux-您可以考虑使用TinyCC ,它还提供包含tcc_compile_string函数的“libtcc.h”,该函数可编译包含C代码到(差)机器代码的字符串。

您还可以使用LLVM , GNU闪电 , LibJit生成机器代码

您还可以生成C代码,将其编译运行到共享对象中,并使用dlopen动态加载它