Convertir una cadena a una línea de código en C

Estoy tratando de encontrar una manera de convertir una cadena a las líneas de mi código.

Por ejemplo, quiero probar algo como esto:

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

Para que este progtwig produzca “6” (3 + 3). Quiero esto para construir un trazador de funciones … Pero aquí me quedo atascado y no puedo encontrar ninguna manera. ¿Podría por favor mostrarme una forma de convertir estas cadenas en líneas de código?

Lo que quieres hacer es evaluar la expresión . Sugiero 2 métodos que quizás lo ayuden a acercarse a la solución esperada.

  1. Evalúe la expresión con un árbol binario: construya un árbol que represente la expresión y la prioridad entre los operadores.

  2. Puede ser mencionado anteriormente. Forma polaca, evaluación basada en stack. Primero construya la forma polaca de la expresión original con una stack, y luego evalúe la forma polaca con una stack nuevamente. Y lo último: usa google con estos keywoards 🙂

Eso no es posible. C no es un lenguaje reflexivo y no tiene ningún tipo de eval() .

Por supuesto, podría invocar un comstackdor externo y ejecutar el progtwig resultante, o podría intentar encontrar una biblioteca de comstackdores que incluya un comstackdor de C en su progtwig, pero no existe una solución “nativa”.

El progtwig de CA se comstack de forma estática, una vez, y el binario comstackdo no tiene conocimiento del hecho de que se escribió en C. El proceso de comstackción está completamente desconectado del tiempo de ejecución del progtwig. Normalmente, solo los idiomas interpretados ofrecen eval() , porque el intérprete está activo durante la ejecución del progtwig y puede manipular dinámicamente el código del progtwig. En un lenguaje comstackdo como C, esta idea no encaja ni tiene sentido.

Si desea escribir una calculadora, tendrá que implementar su propio analizador y lógica de cálculo.

Tendrías que analizar y evaluar la expresión tú mismo. C ++ no pospone hasta el tiempo de ejecución lo que puede hacer en tiempo de comstackción.

No puede comstackr o evaluar dinámicamente el código escrito en C (en realidad puede hacerlo, pero no es tan trivial, ya que requiere que incruste un comstackdor o un intérprete). El mejor enfoque sería utilizar un lenguaje de scripting como Lua, Python, JavaScript, etc.

Lua tiene un buen intérprete escrito en C que es pequeño y rápido (Blizzard lo usa para escribir WoW). Si necesita más rendimiento, consulte V8, el motor de JavaScript de Google Chrome, que es un motor de secuencias de comandos avanzado que cuenta con la comstackción JIT y mucho más. O puedes usar Python, Perl, Ruby o incluso PHP. La desventaja de usar un lenguaje de scripting es que debe aprender un segundo idioma para construir su progtwig, pero los beneficios se mostrarán en breve.

Tenga en cuenta que estos son solo algunos ejemplos, pero hay miles de bibliotecas que hacen este trabajo realmente bien, y debe decidir cuál es la mejor para sus necesidades particulares.

 #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; } 

MANIFESTACIÓN

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

Por lo que entiendo, le gustaría reemplazar en el tiempo de ejecución su cuarta línea por cualquier cosa que el usuario haya dado en la entrada estándar de su progtwig. En su ejemplo, el usuario escribiría algo como a continuación (en el símbolo del sistema):

 (x+3); 

y tu cuarta línea de código se vería así:

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

No es posible en C o C ++ o en cualquier lenguaje comstackdo estáticamente. El procedimiento de comstackción se realiza y debe completarse correctamente antes de que pueda ir al tiempo de ejecución. Por lo tanto, si pudieras modificar el código fuente, deberías comstackrlo antes de poder ejecutar un código teniendo en cuenta tu nueva línea. Claramente no es un buen enfoque para su problema.

Si está seguro de que desea hacer esto en C y no en un lenguaje interpretado, eche un vistazo a Lex y Yacc.

Como ya lo han dicho otros aquí, C no es un lenguaje interpretado, por lo que no puede usar C para interpretar comandos de inmediato. En otras palabras, tendrías que proporcionar (desarrollar) un intérprete en C.

Lexx y Yacc simplifican enormemente el proceso de escribir un intérprete, aunque me temo que este es un tema bastante avanzado.

Busque aquí un motor de arranque: http://epaperpress.com/lexandyacc/

Por encima de todo, creo que no entiende bien el problema que desea resolver … Lea más acerca de los intérpretes

Primero, la x local no es visible fuera de su bloque, así que incluso si tuvieras un evaluador de meta-progtwigción mágico, no podrás hacer lo que quieras.

Además de lo que sugieren otras personas (codificar el lenguaje específico de su dominio, incrustar un intérprete existente, …) y, suponiendo que use Linux, puede considerar usar TinyCC, que también proporciona un “libtcc.h” que contiene una función tcc_compile_string que comstack una cadena que contiene código C a código de máquina (pobre).

También puede generar código de máquina con LLVM , GNU lightning , LibJit

También puede generar código C, ejecutar su comstackción en un objeto compartido y cargarlo dinámicamente con dlopen