1. 程式人生 > >串:串的基本定義及簡單應用魔王語言

串:串的基本定義及簡單應用魔王語言

串,於我的理解就是字串
一般認為有三種儲存方式:定長順序串,堆串,塊鏈串(個人認為比較雞肋)。定長順序串類似於普通字串,同陣列的大小一樣最長長度固定。堆串儲存在堆中,空間大小可重新分配。塊鏈串類似於連結串列,是極端節省空間的堆串。
定長順序串與堆串應用較多,定長順序串的一些操作存在截斷問題

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[]) {//返回子串開始的下標,無則返回-1
	char *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 
            
           

相關推薦

基本定義簡單應用魔王語言

串 串,於我的理解就是字串 一般認為有三種儲存方式:定長順序串,堆串,塊鏈串(個人認為比較雞肋)。定長順序串類似於普通字串,同陣列的大小一樣最長長度固定。堆串儲存在堆中,空間大小可重新分配。塊鏈串類似於連結串列,是極端節省空間的堆串。 定長順序串與堆串應用較多,定長順序串的一些操作存

LTE關鍵技術之一OFDMA(OFDM基本原理簡單例項應用

       OFDM即正交頻分複用(Orthogonal Frequency Division Multiplexing),是多載波調製的一種,通俗來說就是通過多條互相沒有關係的通道傳輸不同的資訊。OFDM現在主要用於4G通訊上

達內科技NTD1712華為vlan定義簡單應用

system blog interface config ethernet 地址 col tag efault Vlan的定義:是物理設備上連接的不受物理限制的用戶的一個邏輯組。 Vlan的作用:交換機可以分割沖突域,但不能分割廣播域,為了解決這個問題,

泛型的基本定義使用

turn test 出現 span color nts extend 參數類型 子類                                     泛型 1、 基本概念: 範例: class Point<T>{//T的類型未知 T x; T y; P

SpringMVC配置簡單應用

新的 bat pan start rop jstl cast 版本 ans 1.在web.xml中配置前端控制器 <servlet>   <servlet-name>springmvc</servlet-name>   <servl

Djangopopup彈出框簡單應用實例

type 正在 elif sta alert cte cti cnblogs sha 效果:在p1.html頁面點擊,彈出p2的彈出框,填寫數據,在 popup_response頁面處理數據 1、視圖函數:views.py from django.shortcuts im

網絡啟動一之IPXE初識及其簡單應用

releases 依賴包 放置 art 配置 ces sdi ftw bootsect IPXE初識及其簡單應用 最近迷上了網絡啟動這回事,查詢了部分文檔,做了基本測試和總結,以供以後參考。 概述:PXE(preboot execute environm

Tesseract 在 windows 下的安裝簡單應用

打開 版本信息 文本 否則 選擇 分享 16px alt 運行 Tesseract 是一個開源的 OCR 引擎,可以識別多種格式的圖像文件並將其轉換成文本,最初由 HP 公司開發,後來由 Google 維護。下載地址:https://digi.bib.uni-mannhei

爬蟲基本知識簡單生成爬蟲

(1)爬蟲是什麼:一段自動抓取網際網路資訊的程式,網際網路是URL的互相連線,爬蟲就是從一個URL出發然後走到與它相關的所有URL並且提取需要的資料;價值:獲得更多網際網路資料,得到自己想用的資料; (2)簡單爬蟲構架:爬蟲排程端:URL管理器,包括已經爬取的URL和未訪問的URL,把待爬取的U

ETCD叢集安裝配置簡單應用

環境配置 CentOS Linux release 7.3.1611 (Core)  etcd-v3.2.6 192.168.108.128 節點1 192.168.108.129 節點2 192.168.108.130 節點3 ETCD

陣列定義基礎應用

java語言中,陣列是一種最簡單的複合資料型別。陣列是有序資料的集合,陣列中的每個元素具有相同的資料型別,可以用一個統一的陣列名和下標來唯一地確定陣列中的元素。陣列有一維陣列和多維陣列。 1.一維陣列的定義 type arrayName[ ]; 型別(type)可以為Java中任意的資料

Eureka概念簡單應用

1、為什麼使用Eureka?  在Spring Cloud中我們經常使用Eureka,是因為SpringCloud對Eureka支援力度非常大 ,Eureka的社群活躍多較高,版本更新的速度快。 Eureka簡介: Eureka是Netflix開發的服務發現元件,

06 awk基本用法 awk高階應用 總結和答疑

Top NSD SHELL DAY06 案例1:使用awk提取文字 案例2:awk處理條件 案例3:awk綜合指令碼應用 案例4:awk流程控制 案例5:awk擴充套件應用 1 案例1:使用awk提取文字 1.1 問題 本案例要求使用awk

分享知識-快樂自己Oracle中定義使用同義詞

Oracle 同義詞概念:   Oracle的同義詞(synonyms)從字面上理解就是別名的意思,和檢視的功能類似,就是一種對映關係。   它可以節省大量的資料庫空間,對不同使用者的操作同一張表沒有多少差別;它擴充套件了資料庫的使用範圍,能夠在不同的資料庫使用者之間實現無縫交互;Oracle資料庫中提供

建立型單例模式相關應用

文章目錄 單例模式(Singleton) 優缺點 重點 懶漢式實現 執行緒不安全 synchronized關鍵字 雙重校驗鎖 靜態內部類 餓漢式實現 單例模式

結構型裝飾者模式相關應用

文章目錄 裝飾者(Decorator) 優缺點 應用場景 Java I/O中的應用 Spring中的應用 MyBatis中的應用 參考資料 裝飾者(Decorator) 在不

結構型橋接模式相關應用

文章目錄 橋接(Bridge) 優缺點 應用場景 JDBC的應用 參考資料 橋接(Bridge) 將抽象部分與它的具體實現部分分離,使它們都可以獨立地變化。 通過組合的方式建立兩個類之間

使用python操作redis簡單應用

redis 連線例項是執行緒安全的,可以直接將redis連線例項設定為一個全域性變數,直接使用. pip install redis import redis >> r = redis.Redis(host='localhost',port=6379,password='', db=0

MySQL安裝mysqld系統基礎應用

MySQL篇 第一章、安裝mysqld系統及基礎應用 一、安裝 注意:mysql的標點符號只能是英文的標點符號。 1、設定配置檔案。 檔案格式:文字格式 檔案位置:Mysql的主目錄下 檔名稱:my.ini 檔案內容: [mysqld] port=3306(port表

在Windows下Kafka的基本配置簡單使用

首先下載zookeeper(版本zookeeper-3.4.13)和kafka(版本kafka_2.12-2.0.0),解壓就可以使用了。 1、zookeeper:在config目錄下,有zoo.conf這個配置檔案,可以配置埠和日誌儲存的位置,可以根據自己習慣更改。首先啟動zookeeper,如果環境變數