当定义了一个变量时,它是什么意思呢,这里是一个简单的一次性解释声明的小程序,之后再改一下,可以一次运行,重复输入就OK了。
// 无法重复循环该程序
#include <stdio.h>
#include <ctype.h> // isalnum()
#include <string.h> // strcpy()
#include <stdlib.h> // atoi()
#define MAXTOKENS 100
#define MAXTOKENLEN 64
enum type_tag { // 0, 1, 2
IDENTIFIER,
QUALIFIER,
TYPE
};
struct token {
char type;
char string[MAXTOKENS];
};
int top = -1;
struct token stack[MAXTOKENS]; // 保存第一个标识之前的所有标记
struct token this; // 保存刚读入的标记
#define pop stack[top--]
#define push(s) stack[++top] = s
enum type_tag classify_string();
void gettoken();
void read_to_first_identifier();
void deal_with_arrays();
void deal_with_function_args();
void deal_with_pointor();
void deal_with_declarator();
int main() {
// while (1) {
printf("> ");
read_to_first_identifier();
deal_with_declarator();
printf("\n");
// }
return 0;
}
enum type_tag classify_string() {
char *s = this.string;
if (!strcmp(s, "const")) {
strcpy(s, "read-only");
return QUALIFIER;
}
if (!strcmp(s, "volatile")) return QUALIFIER;
if (!strcmp(s, "void")) return TYPE;
if (!strcmp(s, "char")) return TYPE;
if (!strcmp(s, "signed")) 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() {
char *p = this.string;
while ((*p = getchar()) == ' '); // 跳过空格
if (isalnum(*p)) { // 字母/数字
while (isalnum(*++p = getchar()));
ungetc(*p, stdin); // 吐回最后那个不是字母/数字
*p = '\0'; // 字符串结束标识符
this.type = classify_string(); // 取得字符串类型
return;
}
if (*p == '*') {
strcpy(this.string, "pointer to");
this.type = '*';
return;
}
this.string[1] = '\0'; // {或[类型
this.type = *p;
return;
}
void read_to_first_identifier() { // 读至第一个标识符
gettoken(); // get a token
while (this.type != IDENTIFIER) { // if not IDENTIFIER, continue
push(this);
gettoken();
}
printf("%s: ", this.string); // print the IDENTIFIER
gettoken(); // the token after IDENTIFIER
}
// -----------------------------
void deal_with_arrays() {
while (this.type == '[') {
printf("array ");
gettoken(); // 数字或']'
if (isdigit(this.string[0])) {
printf("%d ", atoi(this.string));
gettoken(); // 读取']'
}
gettoken(); // 读取']'之后的一个;
printf("of ");
}
}
void deal_with_function_args() {
while (this.type != ')') {
gettoken();
}
gettoken();
printf("function returning ");
}
void deal_with_pointor() {
while (stack[top].type == '*') {
printf("%s ", pop.string);
}
}
void deal_with_declarator() {
// 处理标识符之后可能存在的数组/函数
switch (this.type) {
case '[':
deal_with_arrays();
break;
case '(':
deal_with_function_args();
}
deal_with_pointor();
// 处理在读入到标识符之前压入到堆栈中的符号
while (top >= 0) {
if (stack[top].type == '(') {
pop;
gettoken(); // 读取’)‘之后的符号
deal_with_declarator();
}
else {
printf("%s ", pop.string);
}
}
}
比如:
> char *(* c[10])(int **p);
c: array 10 of pointer to function returning pointer to char