简体   繁体   English

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

[英]Converting a string to a line of code in C

I am trying to find a way to convert a string to the lines of my code. 我正在尝试找到一种将字符串转换为代码行的方法。

For example, i want to try someting like this: 例如,我想尝试以下方法:

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

So that this program outputs "6" (3+3). 这样该程序将输出“ 6”(3 + 3)。 I want to this for building a function plotter.. But here I get stuck and can't find any way. 我要用它来构建函数绘图仪。。但是在这里我被卡住了,找不到任何方法。 Would you please show me a way to convert these strings to lines of code? 您能告诉我一种将这些字符串转换为代码行的方法吗?

That's not possible. 那不可能 C is not a reflective language and doesn't have any sort of eval() . C不是一种反射性语言,没有任何eval()

You could of course invoke an external compiler and run the resulting program, or you could try and find a compiler library that includes a C compiler in your program, but there's no "native" solution. 您当然可以调用外部编译器并运行生成的程序,或者可以尝试找到在程序中包含C编译器的编译器库,但是没有“本机”解决方案。

AC program is statically compiled, once, and the compiled binary retains no knowledge of the fact that it was written in C. The compilation process is entirely unconnected to the program runtime. AC程序一次被静态编译,并且编译后的二进制文件不知道它是用C编写的事实。编译过程完全与程序运行时无关。 Typically, only interpreted languages offer eval() , because the interpreter is active during program execution and can dynamically manipulate the program code. 通常,仅解释型语言提供eval() ,因为解释器在程序执行期间处于活动状态并且可以动态地操纵程序代码。 In a compiled language like C, this entire idea doesn't fit in, or make sense even. 在像C这样的编译语言中,整个想法不适合甚至不可行。

If you want to write a calculator, you'll have to implement your own parser and computation logic. 如果要编写计算器,则必须实现自己的解析器和计算逻辑。

You'd have to parse and evaluate expression yourself. 您必须自己分析和评估表达式。 C++ doesn't postpone till runtime what it can do at compile-time. C ++不会将其在编译时可以完成的工作推迟到运行时。

You cannot dynamically compile or evaluate code written in C (actually you can, but it is not that trivial, as it requires you to embed a compiler or an interpreter). 您不能动态地编译或评估用C语言编写的代码(实际上可以,但是它并不是那么简单,因为它要求您嵌入编译器或解释器)。 The best approach would be to use a scripting language like Lua, Python, JavaScript etc. 最好的方法是使用脚本语言,例如Lua,Python,JavaScript等。

Lua has a good interpreter written in C which is small and fast (Blizzard uses it to script WoW). Lua有一个很好的解释器,它用C编写,既小又快速(Blizzard使用它来编写WoW脚本)。 If you need more performance, look at V8, the JavaScript engine from Google Chrome, which is an advanced scripting engine that features JIT compilation and much more. 如果您需要更高的性能,请查看V8,这是来自Google Chrome的JavaScript引擎,它是具有JIT编译功能以及更多功能的高级脚本引擎。 Or you could use Python, Perl, Ruby or even PHP. 或者,您可以使用Python,Perl,Ruby甚至PHP。 The downside of using a scripting language is that you must learn a second language in order to build your program, but the benefits will show up shortly. 使用脚本语言的缺点是,您必须学习第二种语言才能构建程序,但是好处很快就会显现出来。

Note that these are only few examples, but there are thousands of libraries that do this job really well, and you must decide which is the best for your particular needs. 请注意,这些只是几个示例,但是有成千上万个库确实可以很好地完成此工作,并且您必须确定哪种库最适合您的特定需求。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/*
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<pos;i++)//output until start position
        *buff++ = *s++;

    while(rep_count != count){
        if(cmp(s, find, len_f)){ //not match
            *buff++ = *s++;
        } else { //match
//          strncpy(buff, rep, len_r);
//          buff += len_r;
            for(i=0;i<len_r;i++)
                *buff++ = rep[i];
            s += len_f;
            rep_count++;
        }
        if(*s=='\0')//end of string
            break;
    }
    while(*s){ //rest string output
        *buff++ = *s++;
    }
    *buff = '\0';

    return rep_count;
}

#define MAXLEN    80
#define STACKSIZE 3

int calc(char *str){
/* "(3+5)*7-2" => 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

From what I understand, you would like to replace at runtime your 4th line str by anything the user gave on the standard input of your program. 据我了解,您希望在运行时用用户在程序标准输入中提供的任何内容替换第4行str In your example, the user would type something like below (at your program command prompt) : 在您的示例中,用户将键入以下内容(在程序命令提示符下):

(x+3);

and your 4th line of code would then look like : 然后您的第四行代码将如下所示:

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

It is not possible in C or C++ or any statically compiled language. 在C或C ++或任何静态编译的语言中是不可能的。 Your compilation procedure happens and has to successfully complete before you can go to runtime. 您的编译过程已经完成并且必须成功完成,然后才能进入运行时。 Thus, if you were able to modify the source code then, you would have to recompile before being able to execute a code taking into account your new line. 因此,如果您能够修改源代码,那么在考虑新行的情况下执行代码之前必须重新编译。 Clearly not a good approach to your problem. 显然,这不是解决问题的好方法。

If you are sure that you want to/have to do this in C and not in some interpreted language, have a look at Lex and Yacc. 如果您确定要/必须使用C而不是某种解释性语言来执行此操作,请查看Lex和Yacc。

As already stated by others here, C is not an interpreted language, thus you cannot use C to interprete commands right away. 正如这里其他人已经说过的那样,C不是解释语言,因此您不能立即使用C来解释命令。 In other words, you'd have to provide (develop) an interpreter in C. 换句话说,您必须提供(开发)C语言的解释器。

Lexx and Yacc greatly simplify the process of writing an interpreter, although this is a rather advanved topic, I'm afraid. 恐怕,尽管这是一个相当高级的话题,但Lexx和Yacc大大简化了编写解释器的过程。

Look here for a starter: http://epaperpress.com/lexandyacc/ 在此处查找入门: http : //epaperpress.com/lexandyacc/

Above all, I believe you don't understand well the problem you want to solve... Read more about interpreters 最重要的是,我相信您对您要解决的问题不太了解...阅读有关口译员的更多信息

First, the local x is not visible outside its block, so even if you had some magical meta-programming evaluator you won't be able to do what you want. 首先,局部x在其块外不可见,因此,即使您有一些神奇的元编程评估器,您也将无法执行所需的操作。

In addition of what other people suggest (coding your domain specific language, embedding an existing interpreter, ...) -and assuming you use Linux- you might consider using TinyCC which also gives a "libtcc.h" containing a tcc_compile_string function which compiles a string containing C code to (poor) machine code. 除了其他人的建议(编码您的域特定语言,嵌入现有的解释器,...)-并假设您使用Linux-您可能会考虑使用TinyCC ,它还会提供一个包含包含tcc_compile_string函数的“ libtcc.h”并进行编译包含C代码到(较差)机器代码的字符串。

You can also generate machine code with LLVM , GNU lightning , LibJit 您还可以使用LLVMGNU lightningLibJit生成机器代码

You could also generate C code, run its compilation into a shared object, and dynamically load it with dlopen 您还可以生成C代码,将其编译运行到共享库中,然后使用dlopen动态加载它

What you want to do is expression evaluation . 您要做的是表达评估 I suggest 2 methods which perhaps help you to get closer to the expected solution. 我建议两种方法可能会帮助您更接近预期的解决方案。

  1. Evaluate the expression with a binary tree: build a tree wich represents the expression and the precedence among the operators. 用二叉树评估表达式:构建一个树,该树表示表达式和运算符之间的优先级。

  2. May be it was mentioned above. 可能是上面提到的。 Polish-form, stack-based evaluation. 波兰语形式的基于堆栈的评估。 First build the polish-form of the original expression with a stack, and than evaluate the polish-form with a stack again. 首先使用堆栈构建原始表达式的修饰形式,然后再次使用堆栈评估修饰形式。 And the last: use google with these keywoards :) 最后:将google与这些关键技巧结合使用:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM