串,于我的理解就是字符串
一般认为有三种存储方式:定长顺序串,堆串,块链串(个人认为比较鸡肋)。定长顺序串类似于普通字符串,同数组的大小一样最长长度固定。堆串存储在堆中,空间大小可重新分配。块链串类似于定长顺序串的链表。
定长顺序串与堆串应用较多,定长顺序串的一些操作存在截断问题

ADT String{
  数据对象:串与字符串长度及当前串的最大长度
  结构关系:串中的字符间存在线性关系
  基本运算
  initString(S)  //初始化一个空串
  StringCat(S,T)  //将串T连接至串S末尾
  StringIndexOf(S,T)  //返回串S中第一次出现串T的位置
  StringLastIndexOf(S,T)  //返回串S中最后一次出现串T的位置
  StringInsert(S,pos,T)  //在串S的pos位置插入串T
  StringReplace(S,from,to)  //将串S中的第一个from子串替换为to
  StringReplaceAll(S,from,to)  //将串S中的所有子串from替换为to
  StringReserve(S)  //将串S翻转
  SubString(S,begin,end,T)  //从串S中begin至end取子串T
}ADT String


串的一些基本概念

  • 空串    S ="",串中没有字符,strlen(S) = 0
  • 空格串   "  ",串中的字符全为空格
  • 子串    串的一部分,设串T,串S,StringIndexOf(S,T)结果不为-1,则T为主串S的子串
  • 前缀    对于"abcde",“a”,“ab”,“abc”,“abcd”,“abcde”都是前缀
  • 后缀    对于"abcde",“e”,“de”,“cde”,“bcde”,“abcde”都是后缀
  • 前缀子串  从主串左侧第一个字符开始的所有子串
  • 后缀子串  在主串右侧最后一个字符结束的所有子串
  • 串相等   串长相同,串中每一个位置的字符相同
  • 模式匹配  在主串中寻找子串首次出现位置的运算
  • 真前/后缀(子串)  与主串不相等

堆串的一些基本运算的实现

typedef struct{char *str;int maxlen;
}String;void initString(String *s) {s->str = (char *)malloc(sizeof(char)*STR);s->maxlen = 100;
}int StringIndexOf(String *s, char sub[]) {//返回子串开始的下标,无则返回-1char *str = s->str;int i, j;for (i = 0; i < strlen(str); i++) {j = 0;for (j = 0; j < strlen(sub); j++) {if (str[i + j] != sub[j])break;}if (j == strlen(sub)) {return i;}}return -1;
}int StringIndexOf(String *s, char c) {char *str = s->str;for (int i = 0; i < strlen(str); i++) {if (str[i] == c)return i;}return -1;
}int StringLastIndexOf(String *s, char c) {char *str = s->str;for (int i = strlen(str) - 1; i >=0; i--) {if (str[i] == c)return i;}return -1;
}void StringCat(String *s , char sub[]) {char *str = s->str;char *re = NULL;int len = strlen(str) + strlen(sub);if ( len <= s->maxlen) {strcat(str,sub);}else {re = (char *)malloc(sizeof(char)*len + 25);strcpy(re, str);strcat(re, sub);free(str);s->str = re;s->maxlen = len + 24;}
}void StringReplace(String *s, char sub[], char obj[]) {//int pos = StringIndexOf(s, sub);if (pos == -1)return;char *str = s->str;int subLen = strlen(sub), objLen = strlen(obj);char tem[125], *re = NULL;strcpy(tem, &str[pos + subLen]);int len = strlen(str) - subLen + objLen;if (len <= s->maxlen) {strcpy(str + pos, obj);strcpy(&str[strlen(str)], tem);}else {re = (char *)malloc(sizeof(char)*len + 25);strncpy(re, str, pos);strcpy(&re[pos],obj);strcpy(&re[pos+objLen], tem);free(str);s->str = re;s->maxlen = len + 24;}
}void StringReplace(String *s, int pos, int subLen, char obj[]) {//char *str = s->str;int objLen = strlen(obj);char tem[125], *re = NULL;strcpy(tem, &str[pos + subLen]);int len = strlen(str) - subLen + objLen;if (len <= s->maxlen) {strcpy(str + pos, obj);strcpy(&str[strlen(str)], tem);}else {re = (char *)malloc(sizeof(char)*len + 25);strncpy(re, str, pos);strcpy(&re[pos], obj);strcpy(&re[pos + objLen], tem);free(str);s->str = re;s->maxlen = len + 24;}
}void StringReplaceAll(String *s, char sub[], char obj[]) {int pos;int subLen = strlen(sub);while ((pos = StringIndexOf(s, sub)) != -1) {StringReplace(s, pos, subLen, obj);}
}void StringInsert(String *s , int pos, char in[]) {//从指定位置开始插入字符串char *str = s->str;char *re = NULL;char tem[125];strcpy(tem, &str[pos]);int requirement = strlen(s->str) + strlen(in);if ( requirement <= s->maxlen) {//空间足够strcpy(&str[pos], in);strcpy(&str[strlen(str)], tem);}else {re = (char *)malloc(sizeof(char)*(requirement + 25));strncpy(re, str, pos);strcpy(&(re[pos]), in);strcpy(&re[strlen(re)], tem);free(str);s->str = re;s->maxlen = requirement + 24;}
}char *SubString(String *s, int begin, int end, char *des) {strncpy(des, &(s->str)[begin], end - begin + 1);des[end - begin + 1] = 0;return des;
}char *StringReverse(char *str) {int i, len = strlen(str);char c;for (i = 0; i < len / 2; i++) {c = str[i];str[i] = str[len - i - 1];str[len - i - 1] = c;}return str;
}

魔王语言解释器基于串的实现

两条规则
(1)α->β1β2…βn
(2)(θδ1δ2…δn)->θδnθδn-1…θδ1θ

总觉得跟语法解释器有一点点相似
但是想不到方法去自定义与上述两条规则这种层次的规则

只实现了基于规则(1)的自定义规则,任意字符串可替换为任意字符串
带括号的按规则(2)去解释 可嵌套括号

解释括号的算法

void EliminateBracket(String *s, int left, int right) {//left、right 左右括号的位置if (right <= left)return;char *str = s->str;char sub[NUM];SubString(s, left+2, right-1, sub);char re = str[left + 1];StringReverse(sub);char resub[NUM*2+1];int i, j;for (i = 0, j = 0; i < strlen(sub); i++) {resub[j++] = re;resub[j++] = sub[i];}resub[j++] = re;resub[j] = 0;StringReplace(s, left, right-left+1, resub);//int pos, int subLen  这个方法的第三个参数为被替换串的串长left = StringLastIndexOf(s, '('), right = StringIndexOf(s, ')');EliminateBracket(s, left, right);//递归消除括号
}

总体实现

//全局变量
int amount = 0;//规则条数
char source[NUM][LEN], object[NUM][LEN];//字符串数组,相同下标的两个source串和object串分别表示一条规则中的被替换串与用来替换的串void check_rule() {//打印规则system("cls");printf("\t\t高等规则\n");printf("\tα   →   β1β2…βm\n");printf("\t(θδ1δ2…δn)   →   θδnθδn-1… θδ1θ\n\n");printf("\t\t当前规则\n");int i = 0;while (i < amount) {printf("\t%d、\t%s   →   %s\n", i + 1, source[i], object[i]);i++;}
}int import_rule() {//从文件中读入规则int i = 0, j = 0;FILE *fp = fopen("TheLanguageOftheKingOftheDevil.rule", "r");if (fp == NULL) { printf("文件丢失!\n"); return 0; }while (fscanf(fp,"%s   →   %s", source[i++], object[j++]) != EOF);if (i != j) {printf("文件损坏!");}fclose(fp);return i-1;
}void write_rule() {//将规则写入文件int i;FILE *fp = fopen("TheLanguageOftheKingOftheDevil.rule", "w");for (i = 0; i < amount; i++) {fprintf(fp, "%s   →   %s\n", source[i], object[i]);}fclose(fp);
}void use_rule(String *s) {//使用规则int i;for (i = 0; i < amount;i++) {StringReplaceAll(s, source[i], object[i]);}EliminateBracket(s, StringLastIndexOf(s, '('), StringIndexOf(s, ')'));
}void add_rule() {char from[NUM], to[NUM];printf("请输入要转换的魔王词汇:");scanf("%s", from);printf("请输入该词汇对应的内容:");scanf("%s", to);if (confirm()) {strcpy(source[amount], from);strcpy(object[amount++], to);//保存到文件write_rule();}else {//取消printf("本次修改已取消");}
}void sort_rule() {printf("现在一共有%d条规则,如下所示:\n", amount);int i = 0, j;while (i < amount) {printf("\t%d、\t%s   →   %s\n", i + 1, source[i], object[i]);i++;}printf("输入%d个数表示当前规则的新序号,新序号-1则表示删除该条规则\n,保留的规则序号按先后顺序从小到大\n请输入:",amount);int order[NUM], cnt = 0;char Tsource[NUM][LEN], Tobject[NUM][LEN];for (i = 0; i < amount; i++) {scanf("%d", &order[i]);if (order[i] != -1)cnt++;strcpy(Tsource[i], source[i]);strcpy(Tobject[i], object[i]);}for (i = 1; i < cnt; i++) {//根据order排序for (j = 0; j < amount; j++) {if (order[j] == i)break;}strcpy(source[i - 1], Tsource[j]);strcpy(object[i - 1], Tobject[j]);}amount = cnt;write_rule();printf("修改已完成\n");
}void go_on() {printf("按任意键继续");getch();//getch();VS下可能需要两个getch()
}int confirm() {char choice[25] , flag = 1;printf("是否确认本次操作?(0/1):");do {if (flag == 0) {printf("请输入0或1表示选择\n");}scanf("%s", choice);} while (choice[0] != '0' && choice[0] != '1');return choice[0] - '0';
}int main() {//return 0;char choice[20];amount = import_rule();String ss;String *s = &ss;initString(s);while (1) {menu();scanf("%s", choice);switch (choice[0]){case '1':check_rule(); break;case '2':add_rule(); break;case '3':sort_rule(); break;case '4':printf("请输入待解释字符串:"); scanf("%s", s->str); use_rule(s); printf("结果为:%s\n",s->str); break;case '0':exit(0); break;default:printf("输入有误,请重新选择\n");break;}go_on();}return 0;
}

2018/10/13

串:串的基本定义及简单应用魔王语言相关推荐

  1. 串--串的定义,顺序、链式存储结构,BF、KMP模式匹配算法(C语言描述)

    此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢! 一.串(String)的定义: 串(String):由零个或多个字符组成的 ...

  2. mysql 管理instance_对于多instance安装的MYSQL来说,起停的过程相对复杂,可以定义一些简单的脚本来简化日常的管理。1# 环境变量脚本[mysql@mysql01 scri...

    对于多instance安装的MYSQL来说,起停的过程相对复杂,可以定义一些简单的脚本来简化日常的管理. 1# 环境变量脚本 [mysql@mysql01 scripts]$ cat mysql_en ...

  3. 数据结构之队列的定义与简单实现

    队列的定义与简单实现 和栈相反,队列是一种先进先出(FIFO)的线性表,队列仅在线性表的两端进行操作: 1.队头(Front):取出数据元素的一端: 2.队尾(Rear):插入数据元素的一端. 现实中 ...

  4. 实验3.2 定义一个简单的Computer类

    题目 定义一个简单的Computer类,有数据成员芯片(cpu).内存(ram).光驱(cdrom)等等,有两个公有成员函数run.stop.cpu为CPU类的一个对象,ram为RAM类的一个对象,c ...

  5. 数据库实验之《数据定义与简单查询》

    Mysql数据定义与简单查询 博客由来 实验目的 实验内容 查询练习 寄语 完整源码 博客由来 本人在校学生,希望能借助平台记录下自己的成长,同时也希望分享自己的一些独特的想法.本次上机使用的平台:W ...

  6. 最简单的c语言的编程题目,编程列入考题

    ① 简单的C语言考试题目!(不需要编程) 写入数据的时候,写入的是123,作为一个数处理的. 将printf("%d%d\n",k,n); 改成printf("%d %d ...

  7. c语言定义max和命令,C语言#define定义函数

    define是c语言中的预处理命令,它用于宏定义,可以提高源代码的可读性,为编程提供方便. 预处理命令以"#"号开头,如包含命令#include,宏定义命令#define等.一般都 ...

  8. C语言实现易语言变量框,c语言实现简单的易语言

    大家熟知的易语言底层其实就是c语言来实现的,c语言的32个关键字加上一些常用的其他,使用#define这种宏定义来实现简单的汉语替换 1.下面就先打开VisualStudio,在头文件目录下新建一个 ...

  9. antlr idea 入门_ANTLR入门:构建简单的表达语言

    antlr idea 入门 这是该系列的第一篇文章. 本系列的目的是描述如何创建有用的语言和所有支持工具. 在本文中,我们将开始研究一种非常简单的表达语言. 我们将在语言沙箱中构建它,因此我们将其称为 ...

最新文章

  1. 2019 Mac装Cocoapods的步(cai)骤(keng)记录
  2. GitHub 2W 星:一键生成前后端代码
  3. Bootstrap HTML 编码规范之布尔型属性
  4. Java常用集合类:ArrayList
  5. OpenShift 4 之Knative(3) - 通过事件触发Serverless服务
  6. unity已存在,您无法加载相同的版本
  7. 一篇关于arc下内存管理的老文章,包含各种冷门修饰符(关于内存),写的较好,mark...
  8. php 写入txt换行_PHP fwrite 函数:将字符串写入文件(追加与换行)
  9. Dllmain的作用
  10. git checkout -b
  11. Linux Postfix
  12. elementui中导航组件点击二级菜单页面跳转但是二级菜单关闭问题
  13. 《群山唱响》-- 爱的力量
  14. 金山打字专业文章计算机,计算机打字训练管理(范文).doc
  15. 评价模型——目标权重的确定
  16. python快速排名seo代码_seo评价机制图(python快速排名seo)
  17. 视频拆条VTS(Video Topics Segmentation)
  18. l003 Driller Augmenting Fuzzing Through Selective Symbolic Execution_2016_NDSS学习笔记
  19. 关于不能访问腾讯云服务器tomcat的问题解决
  20. Flutter开发之——Card

热门文章

  1. 使用Python自动化Microsoft Excel和Word
  2. Windows下 网络调试常用命令
  3. ipadpro分屏怎么操作_iPad Pro绝配?T-bao便携显示器深度体验
  4. 招商头条:黑龙江省起草28项措施创新人才政策;河南商丘185个重大项目集中投产
  5. matlab种群规模什么意思,matlab
  6. git使用ssh进行连接
  7. ubuntu/linux系统知识(36)linux网卡命名规则
  8. 2021-2027全球与中国石墨烯防腐涂料市场现状及未来发展趋势
  9. 1110道Java面试题及答案(最新Java初级面试题大汇总)
  10. lammps案例:Coreshell核壳模型模拟原理及力场参数设置