c专家编程里面的分析c语言声明的代码问题

寒沧 2013-09-19 09:52:09
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64

enum type_tag
{
IDENTIFIER,
QUALIFIER,
TYPE
};

struct token
{
char type;
char string[MAXTOKENLEN];
};

int top = -1;
struct token stack[MAXTOKENS];
struct token thos;

#define pop stack[top--]
#define push(s) stack[++top] = s

enum type_tag classify_string(void)
/* 推断标识符的类型*/
{
char *s = thos.string;
if( !strcmp(s, "const") )
{
strcpy(s, "ready-only");
return QUALIFIER;
}


if( !strcmp(s, "volatile") ) return QUALIFIER;
if( !strcmp(s, "void") ) return TYPE;
if( !strcmp(s, "char") ) return TYPE;
if( !strcmp(s, "signde") ) return TYPE;
if( !strcmp(s, "unsigned") ) return TYPE;
if( !strcmp(s, "short") ) return TYPE;
if( !strcmp(s, "int") ) return TYPE;
if( !strcmp(s, "long") ) return TYPE;
if( !strcmp(s, "float") ) return TYPE;
if( !strcmp(s, "double") ) return TYPE;
if( !strcmp(s, "struct") ) return TYPE;
if( !strcmp(s, "union") ) return TYPE;
if( !strcmp(s, "enum") ) return TYPE;

return IDENTIFIER;

}

void gettoken(void)
/* 读取下一个标记到“this” */
{
char *p = thos.string;

/* 略过空白字符 */
while( (*p == getchar()) == ' ' );

if( isalnum(*p) )
/* 原型:extern int isalnum(int c); 说明:当c为数字0-9或字母a-z及A-Z时,返回非零值,否则返回零。 */
{
/*读入的字符以A-Z,0-9开头*/
while( isalnum( *++p = getchar() ) );
ungetc(*p, stdin);
*p = '\0';
thos.type = classify_string();
return;
}

if( *p == '*')
{
strcpy(thos.string, "pointer to");
thos.type = '*';
return ;
}
thos.string[1] = '\0';
thos.type = * p;
return;
}

void read_to_first_identifer()
{
gettoken();
while( thos.type != IDENTIFIER )
{
push(thos);
gettoken();
}
printf("%s is ",thos.string);
gettoken();
}

void deal_with_arrays()
{
while( thos.type == '[' )
{
printf("array ");
gettoken(); /* 数字或者 ']' */
if( isdigit(thos.string[0]) )
{
printf("0..%d ",atoi(thos.string)-1);
gettoken();
}
gettoken();
printf("of ");
}
}

void deal_with_function_args()
{
while( thos.type != ')' )
{
gettoken();
}
gettoken();
printf("function returning ");
}

void deal_with_pointers()
{
while( stack[top].type == '*' )
{
printf("%s ", pop.string);
}
}

void deal_with_declarator()
/* 处理标识符以后的可能存在的函数/数组 */
{
switch(thos.type)
{
case '[' :deal_with_arrays(); break;
case '(' :deal_with_function_args();
}

deal_with_pointers();

/* 处理读入到标识符之前压入到栈中的符号 */
while(top >= 0)
{
if(stack[top].type == '(')
{
pop;
gettoken(); //读取')'之后的符号
deal_with_declarator();
}
else
{
printf("%s ",pop.string);
}
}

}

int main(void)
{
/* 将标记压入堆栈中,直到遇见标识符 */
read_to_first_identifer();
deal_with_declarator();
printf("\n");


return 0;

}


代码看书核实了好几遍 但是却得不到想到的结果

不管输入什么 都只有单一的输出 求解求改错
...全文
294 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
wopabe 2013-09-27
  • 打赏
  • 举报
回复
这代码这么长,而且没有格式,太难看了
寒沧 2013-09-23
  • 打赏
  • 举报
回复
引用 15 楼 lin5161678 的回复:
有2处应该是有问题的: 1.while( (*p == getchar()) == ' ' );,应该是while((*p = getchar())==' '); 其他地方有没有问题,还待发现。
你提的第一处那不是错误 那只是一个代码风格的问题 不止是风格那么简单了 你把 = 写成了 ==[/quote] 好囧............
赵4老师 2013-09-22
  • 打赏
  • 举报
回复
不要使用
while (条件)
更不要使用
while (组合条件)
要使用
while (1) {
 if (条件1) break;
 //...
 if (条件2) continue;
 //...
 if (条件3) return;
 //...
}
因为前两种写法在语言表达意思的层面上有二义性,只有第三种才忠实反映了程序流的实际情况。
典型如:
下面两段的语义都是当文件未结束时读字符
whlie (!feof(f)) {
 a=fgetc(f);
 //...
 b=fgetc(f);//可能此时已经feof了!
 //...
}
而这样写就没有问题:
whlie (1) {
 a=fgetc(f);
 if (feof(f)) break;
 //...
 b=fgetc(f);
 if (feof(f)) break;
 //...
}
类似的例子还可以举很多。
赵4老师 2013-09-22
  • 打赏
  • 举报
回复
//char (*(*x[3])())[5];//x是什么类型的变量?
//
//分析C语言声明,关键是搞清楚这个变量是个什么东西(函数、指针、数组),
//是函数那么剩下的就是他的参数和返回值,
//是指针那剩下部分是说明他指向什么,
//是数组剩下的部分就是说明数组的成员是什么类型。
//解析C语言声明规则:
//从左侧第一个标识符开始,按照优先级进行结合。*表示是..的指针,const表示只读的,volatile表示可变的,[]表示是数组,()表示是函数。
//
//x和[3]结合说明是一个大小为3的数组,该数组指向了一个指针,该指针指向一个函数,该函数的无参数,返回一个指针,该指针指向一个大小为5的char型数组
#include <stdio.h>
#include <typeinfo.h>
char num[5];
char (*x00())[5] {
    return #
}
int main() {
    char (*x000)[5];//返回值
    char (*(x00)())[5];//函数原型,参数为空,返回值为指针
    char (*(*x0)())[5];//数组的元素,是个函数指针
    char (*(*x[3])())[5];//是个数组,大小为3

    x0 = x00;
    x[0] = x0;
    x[1] = x0;
    x[2] = x0;
    printf("typeid(x).name() is %s\n",typeid(x).name());
    return 0;
}
//typeid(x).name() is char (* (__cdecl**)(void))[5]
lin5161678 2013-09-22
  • 打赏
  • 举报
回复
有2处应该是有问题的: 1.while( (*p == getchar()) == ' ' );,应该是while((*p = getchar())==' '); 其他地方有没有问题,还待发现。[/quote]你提的第一处那不是错误 那只是一个代码风格的问题 不止是风格那么简单了 你把 = 写成了 ==
赵4老师 2013-09-22
  • 打赏
  • 举报
回复
引用 13 楼 u011669700 的回复:
[quote=引用 11 楼 zhao4zhong1 的回复:]
不要使用
while (条件)
更不要使用
while (组合条件)
要使用
while (1) {
 if (条件1) break;
 //...
 if (条件2) continue;
 //...
 if (条件3) return;
 //...
}
因为前两种写法在语言表达意思的层面上有二义性,只有第三种才忠实反映了程序流的实际情况。
典型如:
下面两段的语义都是当文件未结束时读字符
whlie (!feof(f)) {
 a=fgetc(f);
 //...
 b=fgetc(f);//可能此时已经feof了!
 //...
}
而这样写就没有问题:
whlie (1) {
 a=fgetc(f);
 if (feof(f)) break;
 //...
 b=fgetc(f);
 if (feof(f)) break;
 //...
}
类似的例子还可以举很多。
那为何c和指针还有c专家编程还要推荐前两种的代码风格呢?[/quote] 因为每个专家在哪方面更专各有不同。
寒沧 2013-09-22
  • 打赏
  • 举报
回复
引用 11 楼 zhao4zhong1 的回复:
不要使用
while (条件)
更不要使用
while (组合条件)
要使用
while (1) {
 if (条件1) break;
 //...
 if (条件2) continue;
 //...
 if (条件3) return;
 //...
}
因为前两种写法在语言表达意思的层面上有二义性,只有第三种才忠实反映了程序流的实际情况。
典型如:
下面两段的语义都是当文件未结束时读字符
whlie (!feof(f)) {
 a=fgetc(f);
 //...
 b=fgetc(f);//可能此时已经feof了!
 //...
}
而这样写就没有问题:
whlie (1) {
 a=fgetc(f);
 if (feof(f)) break;
 //...
 b=fgetc(f);
 if (feof(f)) break;
 //...
}
类似的例子还可以举很多。
那为何c和指针还有c专家编程还要推荐前两种的代码风格呢?
寒沧 2013-09-22
  • 打赏
  • 举报
回复
引用 9 楼 u011729265 的回复:
[quote=引用 8 楼 u011669700 的回复:] [quote=引用 7 楼 u011729265 的回复:] 有2处应该是有问题的: 1.while( (*p == getchar()) == ' ' );,应该是while((*p = getchar())==' '); 2.while( isalnum( *++p = getchar() ) );,应该是while( isalnum( *(++p) = getchar() ) ); 其他地方有没有问题,还待发现。
你提的第一处那不是错误 那只是一个代码风格的问题 至于你说的第二处 那我只能会所你对于运算符的优先级一点都不理解[/quote] 这样修改可以得出一些结果,你要觉得不是问题,那就这样吧。[/quote] 你说的我改过 输出结果没有任何的改变 我用的是c-free
军说网事 2013-09-21
  • 打赏
  • 举报
回复
引用 8 楼 u011669700 的回复:
[quote=引用 7 楼 u011729265 的回复:] 有2处应该是有问题的: 1.while( (*p == getchar()) == ' ' );,应该是while((*p = getchar())==' '); 2.while( isalnum( *++p = getchar() ) );,应该是while( isalnum( *(++p) = getchar() ) ); 其他地方有没有问题,还待发现。
你提的第一处那不是错误 那只是一个代码风格的问题 至于你说的第二处 那我只能会所你对于运算符的优先级一点都不理解[/quote] 这样修改可以得出一些结果,你要觉得不是问题,那就这样吧。
寒沧 2013-09-21
  • 打赏
  • 举报
回复
引用 7 楼 u011729265 的回复:
有2处应该是有问题的: 1.while( (*p == getchar()) == ' ' );,应该是while((*p = getchar())==' '); 2.while( isalnum( *++p = getchar() ) );,应该是while( isalnum( *(++p) = getchar() ) ); 其他地方有没有问题,还待发现。
你提的第一处那不是错误 那只是一个代码风格的问题 至于你说的第二处 那我只能会所你对于运算符的优先级一点都不理解
军说网事 2013-09-20
  • 打赏
  • 举报
回复
有2处应该是有问题的: 1.while( (*p == getchar()) == ' ' );,应该是while((*p = getchar())==' '); 2.while( isalnum( *++p = getchar() ) );,应该是while( isalnum( *(++p) = getchar() ) ); 其他地方有没有问题,还待发现。
寒沧 2013-09-20
  • 打赏
  • 举报
回复
引用 4 楼 u011729265 的回复:
先说下这段代码要实现什么功能。
我在标题说了啊 分析c语言的声明 类似 char * (*c[10])(int **p)
寒沧 2013-09-20
  • 打赏
  • 举报
回复
人呢
军说网事 2013-09-19
  • 打赏
  • 举报
回复
先说下这段代码要实现什么功能。
寒沧 2013-09-19
  • 打赏
  • 举报
回复
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64

enum type_tag
{
	IDENTIFIER,
	QUALIFIER,
	TYPE
};

struct token
{
	char type;
	char string[MAXTOKENLEN];
};

int top = -1;
struct token stack[MAXTOKENS];
struct token thos;

#define pop stack[top--]
#define push(s) stack[++top] = s

enum type_tag classify_string(void)
/* 推断标识符的类型*/
{
	char *s = thos.string;
	if( !strcmp(s, "const") )
	{
		strcpy(s, "ready-only");
		return QUALIFIER;
	}
	
	
	if( !strcmp(s, "volatile") )  return QUALIFIER;
	if( !strcmp(s, "void") )  return TYPE;
	if( !strcmp(s, "char") )  return TYPE;
	if( !strcmp(s, "signde") )  return TYPE;
	if( !strcmp(s, "unsigned") )  return TYPE;
	if( !strcmp(s, "short") )  return TYPE;
	if( !strcmp(s, "int") )  return TYPE;
	if( !strcmp(s, "long") )  return TYPE;
	if( !strcmp(s, "float") )  return TYPE;
	if( !strcmp(s, "double") )  return TYPE;
	if( !strcmp(s, "struct") )  return TYPE;
	if( !strcmp(s, "union") )  return TYPE;
	if( !strcmp(s, "enum") )  return TYPE;
	
	return IDENTIFIER;
	
}

void gettoken(void)
/* 读取下一个标记到“this” */
{
	char *p = thos.string;
	
	/* 略过空白字符 */ 
	while( (*p == getchar()) == ' ' );
	
	if( isalnum(*p) ) 
	/* 原型:extern int isalnum(int c); 说明:当c为数字0-9或字母a-z及A-Z时,返回非零值,否则返回零。 */
	{
		/*读入的字符以A-Z,0-9开头*/
		while( isalnum( *++p = getchar() ) );
		ungetc(*p, stdin);
		*p = '\0';
		thos.type = classify_string();
		return;
	}
	
	if( *p == '*')
	{
		strcpy(thos.string, "pointer to");
		thos.type = '*';
		return ;
	}
	thos.string[1] = '\0';
	thos.type = * p;
	return;
}

void read_to_first_identifer()
{
	gettoken();
	while( thos.type != IDENTIFIER )
	{
		push(thos);
		gettoken();
	}
	printf("%s is ",thos.string);
	gettoken();
}

void deal_with_arrays()
{
	while( thos.type == '[' )
	{
		printf("array ");
		gettoken(); /* 数字或者 ']' */
		if( isdigit(thos.string[0]) )
		{
			printf("0..%d ",atoi(thos.string)-1);
			gettoken();
		}
		gettoken();
		printf("of ");
	}
}

void deal_with_function_args()
{
	while( thos.type != ')' )
	{
		gettoken();
	}
	gettoken();
	printf("function returning ");
}

void deal_with_pointers()
{
	while( stack[top].type == '*' )
	{
		printf("%s ", pop.string);
	}
}

void deal_with_declarator()
/* 处理标识符以后的可能存在的函数/数组 */
{
	switch(thos.type)
	{
		case '[' :deal_with_arrays(); break;
		case '(' :deal_with_function_args();
	}
	
	deal_with_pointers();
	
	/* 处理读入到标识符之前压入到栈中的符号 */
	while(top >= 0)
	{
		if(stack[top].type == '(')
		{
			pop;
			gettoken(); //读取')'之后的符号 
			deal_with_declarator(); 
		}
		else
		{
			printf("%s ",pop.string);
		}
	}
		
}

int main(void)
{
	/* 将标记压入堆栈中,直到遇见标识符 */
	read_to_first_identifer();
	deal_with_declarator();	
	printf("\n"); 

	
	return 0;
	
}
寒沧 2013-09-19
  • 打赏
  • 举报
回复
#include<stdio.h> #include<string.h> #include<ctype.h> #include<stdlib.h> #define MAXTOKENS 100 #define MAXTOKENLEN 64 enum type_tag { IDENTIFIER, QUALIFIER, TYPE }; struct token { char type; char string[MAXTOKENLEN]; }; int top = -1; struct token stack[MAXTOKENS]; struct token thos; #define pop stack[top--] #define push(s) stack[++top] = s enum type_tag classify_string(void) /* 推断标识符的类型*/ { char *s = thos.string; if( !strcmp(s, "const") ) { strcpy(s, "ready-only"); return QUALIFIER; } if( !strcmp(s, "volatile") ) return QUALIFIER; if( !strcmp(s, "void") ) return TYPE; if( !strcmp(s, "char") ) return TYPE; if( !strcmp(s, "signde") ) return TYPE; if( !strcmp(s, "unsigned") ) return TYPE; if( !strcmp(s, "short") ) return TYPE; if( !strcmp(s, "int") ) return TYPE; if( !strcmp(s, "long") ) return TYPE; if( !strcmp(s, "float") ) return TYPE; if( !strcmp(s, "double") ) return TYPE; if( !strcmp(s, "struct") ) return TYPE; if( !strcmp(s, "union") ) return TYPE; if( !strcmp(s, "enum") ) return TYPE; return IDENTIFIER; } void gettoken(void) /* 读取下一个标记到“this” */ { char *p = thos.string; /* 略过空白字符 */ while( (*p == getchar()) == ' ' ); if( isalnum(*p) ) /* 原型:extern int isalnum(int c); 说明:当c为数字0-9或字母a-z及A-Z时,返回非零值,否则返回零。 */ { /*读入的字符以A-Z,0-9开头*/ while( isalnum( *++p = getchar() ) ); ungetc(*p, stdin); *p = '\0'; thos.type = classify_string(); return; } if( *p == '*') { strcpy(thos.string, "pointer to"); thos.type = '*'; return ; } thos.string[1] = '\0'; thos.type = * p; return; } void read_to_first_identifer() { gettoken(); while( thos.type != IDENTIFIER ) { push(thos); gettoken(); } printf("%s is ",thos.string); gettoken(); } void deal_with_arrays() { while( thos.type == '[' ) { printf("array "); gettoken(); /* 数字或者 ']' */ if( isdigit(thos.string[0]) ) { printf("0..%d ",atoi(thos.string)-1); gettoken(); } gettoken(); printf("of "); } } void deal_with_function_args() { while( thos.type != ')' ) { gettoken(); } gettoken(); printf("function returning "); } void deal_with_pointers() { while( stack[top].type == '*' ) { printf("%s ", pop.string); } } void deal_with_declarator() /* 处理标识符以后的可能存在的函数/数组 */ { switch(thos.type) { case '[' :deal_with_arrays(); break; case '(' :deal_with_function_args(); } deal_with_pointers(); /* 处理读入到标识符之前压入到栈中的符号 */ while(top >= 0) { if(stack[top].type == '(') { pop; gettoken(); //读取')'之后的符号 deal_with_declarator(); } else { printf("%s ",pop.string); } } } int main(void) { /* 将标记压入堆栈中,直到遇见标识符 */ read_to_first_identifer(); deal_with_declarator(); printf("\n"); return 0; }
寒沧 2013-09-19
  • 打赏
  • 举报
回复
发到这里怎么缩进这么难看 大家将就一下

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧