C语言-将输入转换为代码

C语言-将输入转换为代码,c,string,variables,declaration,C,String,Variables,Declaration,大多数时候,我问的问题都与我做得不正确的代码的特定部分有关,或者与我忽略的一些bug有关,但这次,我不知道从哪里开始。我甚至不知道我想做的是否可能 我被分配了一个任务来编写一个代码,该代码获取一个类似于变量声明的字符串,例如intx,y是有效的输入字符c,*cptr,carray[80]是有效输入的另一个示例 代码将创建用户输入的内容,并将打印占用的内存量。 例如,在第一个示例(intx,y;)中,代码将创建2个整数,并打印“x需要4个字节,y需要4个字节” 在第二个示例中,代码将创建一个字符、

大多数时候,我问的问题都与我做得不正确的代码的特定部分有关,或者与我忽略的一些bug有关,但这次,我不知道从哪里开始。我甚至不知道我想做的是否可能

我被分配了一个任务来编写一个代码,该代码获取一个类似于变量声明的字符串,例如
intx,y是有效的输入<代码>字符c,*cptr,carray[80]是有效输入的另一个示例

代码将创建用户输入的内容,并将打印占用的内存量。 例如,在第一个示例(
intx,y;
)中,代码将创建2个整数,并打印“x需要4个字节,y需要4个字节”

在第二个示例中,代码将创建一个字符、一个字符指针和一个包含80个字符的字符串,并将打印“c需要1个字节,cptr需要4个字节,carray需要80个字节”


这可能吗?在代码开头之后声明变量是无效的代码。在C语言中,必须先声明它们。因此,如果您试图动态执行输入代码,据我所知,如果不存储代码,然后重新编译,就不可能做到这一点。

。然而,这似乎是一个非常恶劣和漫长的方法。但是,如果您只想从输入中计算声明的大小,那么我要做的就是获取接收到的字符串,调用一个分析/分解该字符串的函数。例如,如果字符串有“int”、“char”等。。我知道你会知道我在处理什么样的声明,在我知道我在处理什么声明之后,我可以计算声明的变量数量,并在你的例子中保留一个计数器,它是x,y。我会在计数器上循环并计算声明类型的大小以及声明的数量。

当然,这是可能的;这只是一点工作。您必须学习C声明语法,然后编写代码来识别它(基本上是一个小型编译器前端)

例如,在声明中

char c, *cptr, carray[80];
您有一系列令牌:

它将被识别为一个类型说明符(
char
),后跟三个声明符;直接声明器、指针声明器和数组声明器


您可以使用
malloc
calloc
动态创建对象空间。然后,您需要创建某种表来将标识符(变量名)映射到动态创建的对象。在常规C代码中,您将无法将这些内容作为常规变量处理;您将要进行大量的表查找和取消引用

这是一个解析问题——您需要解析输入字符串并找出它的含义。您不需要实际“创建”任何东西,只需要计算出编译器将为该代码创建的变量的大小

解析实际上是一个非常大的主题,有很多关于它的书籍和工具可以让它变得更容易。虽然您可以使用诸如或之类的工具来完成此任务,但它们可能有些过分——一个简单的递归下降手工编写的解析器可能是最好的方法

比如:

const char *parse_declaration(const char *p) {
    /* parse a declaration, printing out the names and sizes of the variables
     * 'p' points at the beginning of the string containing the declaration, and the
     * function returns the pointer immediately after the end or NULL on failure */
    int size;
    if (!(p = parse_declspecs(p, &size))) return 0;
    do {
        const char *name;
        int namelen, declsize;
        if (!(p = parse_declarator(p, size, &name, &namelen, &declsize))) return 0;
        printf("%.*s requires %d bytes\n", namelen, name, declsize);
        p += strspn(p, " \t\r\n");  /* skip whitespace */
    } while (*p++ == ',');
    if (p[-1] != ';') return 0;
    return p;
}

const char *parse_declspecs(const char *p, int *size) {
    /* parse declaration specifiers (a type), and output the size of that type
     * p points at the string to be parsed, and we return the point after the declspec */
    p += strspn(p, " \t\r\n");
    if (!isalpha(*p)) return 0;
    int len = 0;
    while (isalnum(p[len])) len++;
    if (!strncmp(p, "char", len)) {
        *size = sizeof(char);
          return p+len; }
    if (!strncmp(p, "int", len)) {
        *size = sizeof(int);
        return p+len; }
    ... more type tests here ...
    if (!strncmp(p, "unsigned", len)) {
        p += len;
        p += strspn(p, " \t\r\n");
        if (!isalpha(*p)) {
            *size = sizeof(unsigned);
            return p; }
        while (isalnum(p[len])) len++;
        if (!strncmp(p, "int", len)) {
            *size = sizeof(unsigned int);
            return p+len; }
        ... more type tests here ...
    }
    return 0;
}

const char *parse_declarator(const char *p, int typesize, const char **name, int *namelen, int *declsize) {
    /* parse a declarator */
    p += strspn(p, " \t\r\n");
    while (*p == '*') {
        typesize = sizeof(void *); /* assuming all pointers are the same size...*/
        p++;
        p += strspn(p, " \t\r\n"); }
    declsize = typesize;
    if (isalpha(*p)) {
        *name = p;
         while (isalnum(*p) | *p == '_') p++;
        *namelen = p - *name;
    } else if (*p == '(') {
        if (!(p = parse_declarator(p+1, typesize, name, namelen, declsize))) return 0;
        p += strspn(p, " \t\r\n");
        if (*p++ != ')') return 0;
    } else
        return 0;
    p += strspn(p, " \t\r\n");
    while (*p == '[') {
        int arraysize, len;
        if (sscanf(++p, "%d %n", &arraysize, &len) < 1) return 0;
        p += len;
        declsize *= arraysize;
        if (*p++ != ']') return 0;
        p += strspn(p, " \t\r\n"); }
    return p;
}
const char*parse_声明(const char*p){
/*解析一个声明,打印出变量的名称和大小
*“p”指向包含声明的字符串的开头,而
*函数在结束后立即返回指针,或在失败时返回NULL*/
整数大小;
if(!(p=parse_declspecs(p,&size))返回0;
做{
常量字符*名称;
int namelen,declsize;
if(!(p=parse_声明符(p,size,&name,&namelen,&declsize)))返回0;
printf(“%s需要%d个字节\n”、namelen、name、declsize);
p+=strspn(p,“\t\r\n”);/*跳过空格*/
}而(*p++=',');
如果(p[-1]!=';')返回0;
返回p;
}
常量字符*parse_declspecs(常量字符*p,int*size){
/*解析声明说明符(类型),并输出该类型的大小
*p指向要分析的字符串,我们返回declspec后面的点*/
p+=strspn(p,“\t\r\n”);
如果(!isalpha(*p))返回0;
int len=0;
而(isalnum(p[len]))len++;
if(!strncmp(p,“char”,len)){
*大小=sizeof(字符);
返回p+len;}
如果(!strncmp(p,“int”,len)){
*大小=sizeof(int);
返回p+len;}
…这里有更多的类型测试。。。
如果(!strncmp(p,“未签名”,len)){
p+=len;
p+=strspn(p,“\t\r\n”);
如果(!isalpha(*p)){
*size=sizeof(无符号);
返回p;}
而(isalnum(p[len]))len++;
如果(!strncmp(p,“int”,len)){
*size=sizeof(无符号整数);
返回p+len;}
…这里有更多的类型测试。。。
}
返回0;
}
const char*parse_声明符(const char*p,int typesize,const char**name,int*namelen,int*declsize){
/*解析声明符*/
p+=strspn(p,“\t\r\n”);
而(*p=='*')){
typesize=sizeof(void*);/*假设所有指针大小相同*/
p++;
p+=strspn(p,“\t\r\n”);}
declsize=字体大小;
如果(isalpha(*p)){
*name=p;
而(isalnum(*p)|*p=='''''p')p++;
*namelen=p-*名称;
}如果(*p=='('),则为else{
if(!(p=parse_声明符(p+1,typesize,name,namelen,declsize)))返回0;
p+=strspn(p,“\t\r\n”);
如果(*p++!=')),则返回0;
}否则
返回0;
p+=strspn(p,“\t\r\n”);
而(*p=='['){
内部阵列化,len;
如果(sscanf(++p、%d%n、&arraysize、&len)<1)返回0;
p+=len;
去LSIZE*=阵列化;
如果(*p++!=']'),则返回0;
p+=strspn(p,“\t\r\n”);}
返回p;
}

你应该开始…

当然,你可以用一个
const char *parse_declaration(const char *p) {
    /* parse a declaration, printing out the names and sizes of the variables
     * 'p' points at the beginning of the string containing the declaration, and the
     * function returns the pointer immediately after the end or NULL on failure */
    int size;
    if (!(p = parse_declspecs(p, &size))) return 0;
    do {
        const char *name;
        int namelen, declsize;
        if (!(p = parse_declarator(p, size, &name, &namelen, &declsize))) return 0;
        printf("%.*s requires %d bytes\n", namelen, name, declsize);
        p += strspn(p, " \t\r\n");  /* skip whitespace */
    } while (*p++ == ',');
    if (p[-1] != ';') return 0;
    return p;
}

const char *parse_declspecs(const char *p, int *size) {
    /* parse declaration specifiers (a type), and output the size of that type
     * p points at the string to be parsed, and we return the point after the declspec */
    p += strspn(p, " \t\r\n");
    if (!isalpha(*p)) return 0;
    int len = 0;
    while (isalnum(p[len])) len++;
    if (!strncmp(p, "char", len)) {
        *size = sizeof(char);
          return p+len; }
    if (!strncmp(p, "int", len)) {
        *size = sizeof(int);
        return p+len; }
    ... more type tests here ...
    if (!strncmp(p, "unsigned", len)) {
        p += len;
        p += strspn(p, " \t\r\n");
        if (!isalpha(*p)) {
            *size = sizeof(unsigned);
            return p; }
        while (isalnum(p[len])) len++;
        if (!strncmp(p, "int", len)) {
            *size = sizeof(unsigned int);
            return p+len; }
        ... more type tests here ...
    }
    return 0;
}

const char *parse_declarator(const char *p, int typesize, const char **name, int *namelen, int *declsize) {
    /* parse a declarator */
    p += strspn(p, " \t\r\n");
    while (*p == '*') {
        typesize = sizeof(void *); /* assuming all pointers are the same size...*/
        p++;
        p += strspn(p, " \t\r\n"); }
    declsize = typesize;
    if (isalpha(*p)) {
        *name = p;
         while (isalnum(*p) | *p == '_') p++;
        *namelen = p - *name;
    } else if (*p == '(') {
        if (!(p = parse_declarator(p+1, typesize, name, namelen, declsize))) return 0;
        p += strspn(p, " \t\r\n");
        if (*p++ != ')') return 0;
    } else
        return 0;
    p += strspn(p, " \t\r\n");
    while (*p == '[') {
        int arraysize, len;
        if (sscanf(++p, "%d %n", &arraysize, &len) < 1) return 0;
        p += len;
        declsize *= arraysize;
        if (*p++ != ']') return 0;
        p += strspn(p, " \t\r\n"); }
    return p;
}
void* q5(char* str_in)
{
    char runner;
    int i=0,memory,counter=0,arr_size;
    runner=str_in[i];
    while(1)
    {
        if(runner=='i') //the input is integer
        {
            memory=sizeof(int);
            break;
        }
        if(runner=='c') //input is char
        {
            memory=sizeof(char);
            break;
        }
        if(runner=='d') //input is double
        {
            memory=sizeof(double);
            break;
        }
        if(runner=='s') //input is short
        {
            memory=sizeof(short);
            break;
        }
        if(runner=='l') //input is long
        {
            memory=sizeof(long);
            break;
        }
        if(runner=='f') //input is float
        {
            memory=sizeof(float);
            break;
        }
    } //we know the type of data, skip in the string until first variable
    while(runner!=' ') //advance until you see empty space, signaling next variable
    {
        i++;
        runner=str_in[i];
    }
    while(runner==' ') //advance until you encounter first letter of new variable
    {
        i++;
        runner=str_in[i];
    } //runner is now first letter of first variable
    while(runner!=';') //run on the string until its over
    {
        if(runner==',') //if its ',', then spaces will occur, skip all of them to first char that isnt space
        {
            i++;
            runner=str_in[i];
            while(runner==' ')
            {
                i++;
                runner=str_in[i];
            } //runner now points to first letter of variable
            continue;
        }
        if(runner=='*') //current variable is a pointer
        {
            counter=counter+4; //pointers are always 4 bytes regardless of type!
            i++;
            runner=str_in[i];
            while((runner!=',')&&(runner!=';')) //while runner is still on this variable
            {
                printf("%c",runner);
                i++;
                runner=str_in[i];
            }
            printf(" requires 4 bytes\n"); //now runner is the first character after the variable we just finished
            continue;
        }
        while((runner!=',')&&(runner!=';')) //now is the case that runner is the first letter of a non pointer variable
        {
            printf("%c",runner);
            i++;
            runner=str_in[i];
            if((runner==',')||(runner==';')) //we are done
            {
                printf(" requires %d bytes\n",memory);
                counter+=memory;
                continue;
            }
            if(runner=='[') //this variable is an array
            {
                printf("[");
                i++;
                runner=str_in[i]; //runner is now MSB of size of array
                arr_size=0;
                while(runner!=']')
                {
                    printf("%c",runner);
                    arr_size*=10;
                    arr_size=arr_size+runner-48; //48 is ascii of 0
                    i++;
                    runner=str_in[i];
                } //arr_size is now whats written in the [ ]
                printf("] requires %d bytes\n",arr_size*memory);
                counter+=arr_size*memory;
                i++;
                runner=str_in[i]; // should be ',' since we just finished a variable
                continue;
            }
        }
    }
    printf("Overall %d bytes needed to allocate\n",counter);
    return (malloc(counter));
}