串存儲(chǔ)結(jié)構(gòu)

串:由零個(gè)或多個(gè)字符組成的有限序列,又名字符串坚冀。

實(shí)現(xiàn)代碼如下:

// 串存儲(chǔ)結(jié)構(gòu)
#include <stdio.h>
#include <string.h>

#define OK 1      // 執(zhí)行成功
#define ERROR 0   // 執(zhí)行失敗
#define TRUE 1    // 返回值為真
#define FALSE 0   // 返回值為假

#define MAXSIZE 20 // 存儲(chǔ)空間初始分配大小

typedef int Status; // 函數(shù)返回結(jié)果類型

// 串的存儲(chǔ)結(jié)構(gòu)济赎,0下標(biāo)位置用來存放字符串長度
typedef char String[MAXSIZE + 1];

/**
 * 生成一個(gè)值等于字符串chars的字符串T
 * @param T 新生成的字符串
 * @param chars 原字符串
 * @return 執(zhí)行狀態(tài)
 */
Status StrAssign(String T, char *chars) {
    int i; // 用于遍歷元素

    // 字符串chars的長度大于字符串T的分配空間,生成失敗
    if (strlen(chars) > MAXSIZE) {
        return ERROR;
    } else {
        // 計(jì)算字符串chars的長度,存到T的0下標(biāo)位置
        T[0] = strlen(chars);

        for (i = 1; i <= T[0]; ++i) {
            // 將字符串chars的所有內(nèi)容存到字符串T中
            T[i] = *(chars + i - 1); //(T從1下標(biāo)開始存司训,chars從0下標(biāo)開始取值构捡,所以要減1)
        }
        return OK;
    }
}

/**
 * 將串S的所有內(nèi)容復(fù)制到串T中
 * @param T 新生成的串
 * @param S 被復(fù)制的串
 * @return 執(zhí)行狀態(tài)
 */
Status StrCopy(String T, String S) {
    int i; // 用于遍歷元素

    // 遍歷S的所有涌入
    for (i = 0; i <= S[0]; ++i) {
        T[i] = S[i];
    }
    return OK;
}

/**
 * 判斷串是否為空
 * @param S 串
 * @return 是否為空串
 */
Status StrEmpty(String S) {
    // 下標(biāo)為0的位置存儲(chǔ)串的長度,若等于0豁遭,串為空
    if (S[0] == 0) {
        return TRUE;
    } else {
        return FALSE;
    }
}

/**
 * 比較串S和T的大小
 * 若S>T叭喜,返回值>0;若S=T蓖谢,返回值為0捂蕴;若S<T,返回值<0
 * @param S 串
 * @param T 串
 * @return 串S是否比串T大
 */
int StrCompare(String S, String T) {
    int i; // 用于遍歷元素

    // 遍歷串的內(nèi)容
    for (i = 0; i <= S[0] && i <= T[0]; i++) {
        // 碰到對(duì)應(yīng)位置字符不相等
        if (S[i] != T[i]) {
            // 使用對(duì)應(yīng)位置
            return S[i] - T[i];
        }
    }
    // 使用兩個(gè)串的長度相減
    return S[0] - T[0];
}

/**
 * 返回串的元素個(gè)數(shù)
 * @param S 串
 * @return 串的元素個(gè)數(shù)
 */
int StrLength(String S) {
    return S[0];
}

/**
 * 將串的內(nèi)容清空
 * @param S 串
 * @return 執(zhí)行狀態(tài)
 */
Status ClearString(String S) {
    S[0] = 0; // 令串的長度為0
    return OK;
}

/**
 * 連接S1和S2成新的串T
 * 如果未截?cái)喾祷豑RUE闪幽,截?cái)鄤t返回FALSE
 * @param T 連接成的新串
 * @param S1 串
 * @param S2 串
 * @return 是否對(duì)連接成的字符串截?cái)? */
Status Concat(String T, String S1, String S2) {
    int i; // 用于遍歷元素

    // 串T的大小可以裝下串S1和串S2的內(nèi)容
    if (S1[0] + S2[0] <= MAXSIZE) {
        // 復(fù)制S1的所有內(nèi)容到T中
        for (i = 1; i <= S1[0]; i++) {
            T[i] = S1[i];
        }
        // 復(fù)制S2的所有內(nèi)容到T中
        for (i = 1; i <= S2[0]; i++) {
            T[S1[0] + i] = S2[i]; // S2的內(nèi)容在S1的內(nèi)容之后
        }
        // 串T的長度等于S1和S2的長度之和
        T[0] = S1[0] + S2[0];
        return TRUE; // 表示S2字符串未被截?cái)?    }
    // 串T的大小不能裝下串S1和串S2的內(nèi)容啥辨,將截?cái)郤2
    else {
        // 復(fù)制S1的所有內(nèi)容到T中
        for (i = 1; i <= S1[0]; ++i) {
            T[i] = S1[i];
        }
        // 當(dāng)未超過T的最大長度時(shí),復(fù)制S2的內(nèi)容到T中
        for (i = 1; i <= MAXSIZE - S1[0]; i++) {
            T[S1[0] + i] = S2[i]; // S2的內(nèi)容在S1的內(nèi)容之后
        }
        // T的長度等于限定的最大長度
        T[0] = MAXSIZE;
        return FALSE; // 表示字符串S2被截?cái)?    }
}

/**
 * 用串Sub返回串S第pos個(gè)字符起長度為len的字符
 * @param Sub 截取的子串
 * @param S 原串
 * @param pos 開始截取位置
 * @param len 截取長度
 * @return 執(zhí)行狀態(tài)
 */
Status SubString(String Sub, String S, int pos, int len) {
    int i; // 用于遍歷元素

    // 截取的開始位置或長度不合理盯腌,截取失敗
    if (pos < 1 || pos > S[0] || len < 0 || len > S[0] - pos + 1) {
        return ERROR;
    }

    // 截取串S中從pos位置開始溉知,長度為len的內(nèi)容到串Sub中
    for (i = 1; i <= len; ++i) {
        Sub[i] = S[pos + i - 1];
    }
    // 將串Sub的長度設(shè)置為len
    Sub[0] = len;
    return OK;
}

/**
 * 定位子串T在串S第pos個(gè)字符之后的位置,若不存在則返回0
 * (此方法叫:樸素模式的匹配算法)
 * @param S 原字符串
 * @param T 子串
 * @param pos 在S中開始定位的位置
 * @return 子串T在串S第pos個(gè)字符之后的位置腕够,若不存在則返回0
 */
int Index(String S, String T, int pos) {
    int i = pos; // i等于串S開始定位的下標(biāo)
    int j = 1; // j用于記錄子串T中當(dāng)前下標(biāo)的位置

    // i小于串S的長度级乍,并且j小于串T的長度
    while (i <= S[0] && j <= T[0]) {
        // 若對(duì)應(yīng)位置的字符相等,i和j都加1
        if (S[i] == T[j]) {
            i++;
            j++;
        } else { // 若對(duì)應(yīng)位置的字符不相等
            i = i - j + 2; // i退回上次匹配首位的下一位
            j = 1; // j退回子串T的首位
        }
    }

    // 串T的所有元素都與S的某個(gè)子串相等
    if (j > T[0]) {
        return i - T[0]; // i位置減去串T的長度帚湘,得到子串的起始位置
    } else { // 未定位到串T
        return 0; 
    }
}

/**
 * 在串S的第pos個(gè)位置插入串T的值
 * 返回TRUE表示完全將T的內(nèi)容插入S中玫荣,F(xiàn)ALSE表示不能完全將T的內(nèi)容插入S中
 * @param S 串S
 * @param pos 下標(biāo)
 * @param T 串T
 * @return 執(zhí)行狀態(tài)
 */
Status StrInsert(String S, int pos, String T) {
    int i; // 用于遍歷元素

    // 插入位置不合理,插入錯(cuò)誤
    if (pos < 1 || pos > S[0] + 1) {
        return ERROR;
    }

    // 串T有足夠的位置完全插入串S中
    if (S[0] + T[0] <= MAXSIZE) {
        // 串S從i位置開始大诸,所有元素向后移動(dòng)串T的長度
        for (i = S[0]; i >= pos; i--) {
            S[i + T[0]] = S[i];
        }
        // 從第i個(gè)位置插入串T的值
        for (i = pos; i < pos + T[0]; i++) {
            S[i] = T[i - pos + 1];
        }
        // 設(shè)置S的長度為原來S的長度與T長度之和
        S[0] = S[0] + T[0];
        return TRUE; // 返回TRUE表示完全將T的內(nèi)容插入S中
    } else {  // 串T沒有有足夠的位置完全插入串S中捅厂,只能部分插入
        // 將S的pos位置開始的元素向后移動(dòng)T個(gè)位置
        for (i = MAXSIZE; i <= pos; i--) {
            S[i] = S[i - T[0]];
        }
        // 從第i個(gè)位置插入串T的值
        for (i = pos; i < pos + T[0]; i++) {
            S[i] = T[i - pos + 1];
        }
        S[0] = MAXSIZE; // S的長度為最大初始值
        return FALSE; // 返回FALSE表示不能完全將T的內(nèi)容插入S中
    }
}

/**
 * 從串S的第pos個(gè)位置開始,刪除len個(gè)長度的內(nèi)容
 * @param S 串S
 * @param pos 開始刪除的下標(biāo)
 * @param len 刪除的長度
 * @return 執(zhí)行狀態(tài)
 */
Status StrDelete(String S, int pos, int len) {
    int i; // 用于遍歷元素

    // 刪除位置不合理资柔,刪除失敗
    if (pos < 1 || pos > S[0] - len + 1 || len < 0) {
        return ERROR;
    }

    // 將被刪除位置的值用后面的值覆蓋
    for (i = pos + len; i <= S[0]; i++) {
        S[i - len] = S[i];
    }

    S[0] -= len; // S的長度減去len
    return OK;
}

/**
 * 串S中所有等于串T的內(nèi)容全都用串V進(jìn)行替換
 * @param S 串S
 * @param T 串T 被替換
 * @param V 串V 替換的新內(nèi)容
 * @return 執(zhí)行狀態(tài)
 */
Status Replace(String S, String T, String V) {
    int i = 1; // 從串S的第一個(gè)字符起查找串T

    // 串T是空串焙贷,替換失敗
    if (StrEmpty(T)) {
        return ERROR;
    }

    do {
        i = Index(S, T, i); // 定位子串T在串S第pos個(gè)字符之后的位置
        // 串T在串S中存在
        if (i) {
            StrDelete(S, i, StrLength(T)); // 在串S中刪除串T
            StrInsert(S, i, V); // 在原串T的位置刪除串V
            i += StrLength(V); // 在插入的串V的后面繼續(xù)查找串T
        }
    } while (i); // 當(dāng)串S中還有串T的存在
    return OK;
}

/**
 * 打印串的內(nèi)容
 * @param T 串T
 */
void StrPrint(String T) {
    int i; // 用于遍歷元素
    // 打印字符串中所有元素的值
    for (i = 1; i <= T[0]; i++) {
        printf("%c", T[i]);
    }
    printf("\n");
}

int main() {
    String t, s1, s2; // 串
    Status status; // 執(zhí)行狀態(tài)
    int index; // 起始坐標(biāo)

    status = StrEmpty(t); // 判斷字符串t是否為空

    printf("串t是否為空:%s\n", status == TRUE ? "是" : "否");

    /*** 將字符串S賦值為abcd ***/
    status = StrAssign(t, "ab");

    printf("串t的值為:");
    StrPrint(t); // 打印串t
    printf("串t的長度為:%d\n", StrLength(t)); // 獲取串的長度
    
    /*** 將字符串S賦值為abcd ***/
    status = StrAssign(s1, "abcd"); // 將字符串S賦值為abcd
    
    printf("將字符串S賦值為abcd后,串s1的值為:");
    StrPrint(s1); // 打印串s1
    printf("串s1的長度為:%d\n", StrLength(s1)); // 獲取串的長度

    /*** 復(fù)制串s1的內(nèi)容到s2中 ***/
    StrCopy(s2, s1); // 復(fù)制串s1的內(nèi)容到s2中
    printf("復(fù)制串s1的內(nèi)容到s2后贿堰,串s2的值為:");
    StrPrint(s2); // 打印串s2
    printf("串s2的長度為:%d\n", StrLength(s1)); // 獲取串的長度

    /*** 比較t和s1的大小 ***/
    status = StrCompare(t, s1);

    if (status > 0) {
        printf("t大于s1\n");
    } else if (status == 0) {
        printf("t等于s1\n");
    } else {
        printf("t小于s2\n");
    }

    /*** 清空字符串s2中的內(nèi)容 ***/
    status = ClearString(s2);
    printf("s2是否為空串:%s\n", StrEmpty(s2) == TRUE ? "是" : "否");

    /*** 將s1和s2連接后的值辙芍,賦值給串t ***/
    status = StrAssign(s2, "efg"); // 重新賦值串s2等于efg

    status = Concat(t, s1, s2); // 連接s1和s2的值,賦值給串t
    printf("連接s1和s2的值到t后官边,串t的值為:");
    StrPrint(t); // 打印串t

    /*** 截取串t的部分內(nèi)容到串s2 ***/
    status = SubString(s2, t, 2, 3); // 從串t的2下標(biāo)位置截取3個(gè)字符沸手,賦值給s2

    printf("截取串t的部分內(nèi)容后,串s2的值為:");
    StrPrint(s2); // 打印串

    /*** 定位子串s2在串t中的起始位置 ***/
    index = Index(t, s2, 0); // 定位子串s2在串t中的起始位置(從0下標(biāo)開始統(tǒng)計(jì))
    printf("串s2在t的位置為:%d\n", index);

    /*** 在串t下標(biāo)為4的位置插入串s1 ***/
    status = StrInsert(t, 4, s1); // 在串t下標(biāo)為4的位置插入串s1
    printf("下標(biāo)為4的位置插入s1后注簿,串t的值為:");
    StrPrint(t); // 打印串

    /*** 在串t下標(biāo)為4的位置刪除4個(gè)字符 ***/
    status = StrDelete(t, 4, 4); // 在串t下標(biāo)為4的位置刪除4個(gè)字符

    printf("下標(biāo)為4的位置刪除三個(gè)字符后契吉,串t的值為:");
    StrPrint(t); // 打印串

    /*** 替換串t中的abcd成123 ***/
    status = StrAssign(s2, "123"); // 重新賦值串s2等于123
    status = StrAssign(t, "abcdggggabcdggggabcd"); // 重新賦值給串t

    status = Replace(t, s1, s2); // 在串t中,用s2的值替換調(diào)s1的值

    printf("替換內(nèi)容后诡渴,串t的值為:");
    StrPrint(t); // 打印串
}
運(yùn)行結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捐晶,一起剝皮案震驚了整個(gè)濱河市菲语,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惑灵,老刑警劉巖山上,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異英支,居然都是意外死亡佩憾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門干花,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妄帘,“玉大人,你說我怎么就攤上這事池凄÷胀眨” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵肿仑,是天一觀的道長致盟。 經(jīng)常有香客問我,道長尤慰,這世上最難降的妖魔是什么馏锡? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮伟端,結(jié)果婚禮上眷篇,老公的妹妹穿的比我還像新娘。我一直安慰自己荔泳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布虐杯。 她就那樣靜靜地躺著玛歌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪擎椰。 梳的紋絲不亂的頭發(fā)上支子,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音达舒,去河邊找鬼值朋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛巩搏,可吹牛的內(nèi)容都是我干的昨登。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贯底,長吁一口氣:“原來是場噩夢啊……” “哼丰辣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤笙什,失蹤者是張志新(化名)和其女友劉穎飘哨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體琐凭,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卒暂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栽烂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拓提。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鸿吆,靈堂內(nèi)的尸體忽然破棺而出囤采,到底是詐尸還是另有隱情,我是刑警寧澤惩淳,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布蕉毯,位于F島的核電站,受9級(jí)特大地震影響思犁,放射性物質(zhì)發(fā)生泄漏代虾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一激蹲、第九天 我趴在偏房一處隱蔽的房頂上張望棉磨。 院中可真熱鬧,春花似錦学辱、人聲如沸乘瓤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衙傀。三九已至,卻和暖如春萨咕,著一層夾襖步出監(jiān)牢的瞬間统抬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國打工危队, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留聪建,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓茫陆,卻偏偏與公主長得像金麸,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盅弛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容