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