参考C++ Program to implement Symbol Table
写此代码是为了方便bc计算器的完成,代码与参考很接近,特点是全部使用c完成,对flex/bison兼容性强。
以下是代码:
- 头文件:
// SymbolTable.h
#define MAX 100
/*
*一个标识符为一个节点,所有节点为一个链表
*/
typedef struct node {
char *identifier;
double value;
struct Node *next;
void (*print)(struct Node *p);
}Node;
/*
*节点初始化
*只允许头文件中进行内部调用
*/
Node *newNode();
Node *newNodeWith(char *id, double value);
/*调试使用函数*/
static void print(Node *p);
/*
*符号表
*使用hash数组存储标识符节点的指针
*/
typedef struct symbolTable
{
struct Node *head[MAX];
/*绑定指针函数*/
int (*hashf)(char* id);
int (*insert)(struct symbolTable* s,char* id, double value);
double (*find)(struct symbolTable* s,char* id);
int (*deleteRecord)(struct symbolTable* s,char* id);
int (*modify)(struct symbolTable* s,char* id);
}SymbolTable;
/*符号表初始化函数*/
SymbolTable *newSymbolTable();
/*计算hash值*/
static int hashf(char* id);
/*插入一个标识符及对应值*/
static int insert(SymbolTable* s,char* id,double value);
/*寻找标识符的值*/
static double find(SymbolTable* s,char* id);
/*删除标识符*/
static int deleteRecord(SymbolTable* s,char* id);
/*修改标识符的值*/
static int modify(SymbolTable* s,char* id,double value);
- 主文件
// SymbolTable.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"SymbolTable.h"
Node *newNode()
{
Node *p = (Node *)malloc(sizeof(*p));
if(p==NULL){
return NULL;
}
p->value = 0;
p->next = NULL;
p->print = &print;
return p;
}
Node *newNodeWith(char* key, double value)
{
Node *p = (Node *)malloc(sizeof(*p));
if(p==NULL){
return NULL;
}
p->identifier = key;
p->value = value;
p->next = NULL;
p->print = &print;
return p;
}
static void print(Node *p)
{
printf("Identifier's Name:%s\n",p->identifier);
printf("Line Number:%lf\n",p->value);
}
SymbolTable *newSymbolTable()
{
SymbolTable *p = (SymbolTable *)malloc(sizeof(*p));
for (int i=0; i<MAX; i++)
p->head[i] = NULL;
p->ExistedNodes = 0;
p->hashf = &hashf;
p->insert = &insert;
p->find = &find;
p->deleteRecord = &deleteRecord;
p->modify = &modify;
return p;
}
static int hashf(char* id)
{
int asciiSum = 0;
for (int i=0; i<strlen(id); i++) {
asciiSum = asciiSum + id[i];
}
return (asciiSum % 100);
}
static int insert(SymbolTable* s, char* id, double value)
{
int index = s->hashf(id);
Node* p = newNodeWith(id, value);
if (s->head[index] == NULL) {
s->head[index] = p;
//printf("id:%s inserted\n",id);
s->ExistedNodes++;
return 1;
}else{
Node* start = s->head[index];
while (start->next != NULL)
start = start->next;
start->next = p;
//printf("id:%s inserted\n",id);
s->ExistedNodes++;
return 1;
}
return 0;
}
static double find(SymbolTable* s,char* id)
{ /*如果查找失败的话将返回double的最大值__DBL_MAX__*/
int index = s->hashf(id);
Node* start = s->head[index];
/*查找失败情况一:当前位置无节点*/
if (start == NULL)
return __DBL_MAX__;
/*查找成功*/
if (!strcmp(start->identifier,id)) {
//start->print(start);
return start->value;
}
/*查找链表*/
start = start->next;
int count = 0;
while (start != NULL) {
/*查找成功*/
if (!strcmp(start->identifier,id)) {
//start->print(start);
return start->value;
}
start = start->next;
count++;
/*查找失败情况二:遍历整个链表查找失败*/
if (count == s->ExistedNodes) {
return __DBL_MAX__;
}
}
/*查找失败情况三:不存在这种情况的*/
return __DBL_MAX__;
}
static int deleteRecord(SymbolTable* s,char* id)
{
int index = s->hashf(id);
Node* tmp = s->head[index];
Node* par = s->head[index];
if (tmp == NULL) {
return 0;
}
if (!strcmp(tmp->identifier, id) && tmp->next == NULL) {
tmp->next = NULL;
free(tmp);
return 1;
}
while (!strcmp(tmp->identifier, id) && tmp->next != NULL) {
par = tmp;
tmp = tmp->next;
}
if (strcmp(tmp->identifier, id) && tmp->next != NULL) {
par->next = tmp->next;
tmp->next = NULL;
free(tmp);
return 1;
}else {
par->next = NULL;
tmp->next = NULL;
free(tmp);
return 1;
}
return 0;
}
static int modify(SymbolTable* s,char* id,double value)
{
/*如果不存在当前变量,便转移到insert*/
if (s->find(s,id) == __DBL_MAX__) {
//printf("当前变量不存在,进行插入操作!\n");
s->insert(s,id,value);
return 1;
}
/*如果存在再进行修改*/
int index = s->hashf(id);
Node* start = s->head[index];
if (start == NULL)
return -1;
while (start != NULL) {
if (!strcmp(start->identifier,id)) {
start->value = value;
return 1;
}
start = start->next;
}
return 0;
}