C语言实现字符串
- 简单描述
- 代码
- 运行结果
简单描述
- 用codeblocks编译通过
- 源码参考连接
https://gitee.com/IUuaena/data-structures-c.git
代码
- guistar_string.h
#ifndef GUISTAR_STRING_H_INCLUDED
#define GUISTAR_STRING_H_INCLUDED/*! @brief 函数返回值枚举 */
typedef enum Status
{OK = 0, //!< 正确NON_ALLOCATED, //!< 内存分配失败NON_EXISTENT, //!< 不存在OVERFLOW, //!< 溢出ERROR, //!< 其他错误
} status_t;/*! @brief 字符串 */
typedef struct
{char* buffer; //!< char缓存数组int length; //!< 长度
} string_t;// 字符串赋值
status_t StringAssign(string_t* str, const char* chars, int str_len);// 字符串复制
status_t StringCopy(string_t* dest_str, string_t* src_str);// 是否为空字符串
int StringEmpty(string_t* str);// 字符串比较
int StringCompare(string_t* str1, string_t* str2);// 字符串长度
int StringLength(string_t* str);// 字符串清空
status_t StringClear(string_t* str);// 字符串拼接
status_t StringConcat(string_t* resulting_string, string_t* str1, string_t* str2);// 字符串子串
status_t StringSubStr(string_t* str, string_t* sub_str, int offset, int sub_str_len);// 字符串插入
status_t StringInsert(string_t* str, int index, string_t* insert_str);// 字符串暴力匹配(BF)
int StringBruteForceSearch(string_t* str, string_t* pattern, int offset);// 字符串KMP匹配
int StringKMPSearch(string_t* str, string_t* pattern, int offset);#endif // GUISTAR_STRING_H_INCLUDED
- guistar_string.c
/*!* @file cyberdash_string.c* @author CyberDash计算机考研, cyberdash@163.com(抖音id:cyberdash_yuan)* @brief 字符串源文件* @version 1.0.0* @date 2022-07-10* @copyright Copyright (c) 2021* CyberDash计算机考研*/#include <stdlib.h>
#include <string.h>
#include "guistar_string.h"/*!* @brief **字符串赋值*** @param str 字符串(指针)* @param chars char数组* @param str_len 字符串长度* @return 执行结果* @note* 字符串赋值* ---------* ---------** <span style="color:#FF6700">* The most valuable things in life are not measured in monetary terms. \n* The really important things are not houses and lands, stocks and bonds, \n* automobiles and real state, but friendships, trust, confidence, empathy, \n* mercy, love and faith. \n* </span>* <span style="color:#FF6700"> \n*      *      *      * -- Bertrand Arthur William Russell </span>** ---------* - 释放str->buffer* - 处理str_len等于0的情况* - str->buffer分配内存, 并置0* - 填充buffer内容, 并设置length*/
status_t StringAssign(string_t* str, const char* chars, int str_len)
{// 释放str->bufferif (str->buffer){free(str->buffer);}// 处理str_len等于0的情况if (str_len == 0){str->buffer = NULL; // str->buffer设置为NULLstr->length = 0; // 字符串长度设置为0return OK;}// 3 str->buffer分配内存str->buffer = (char*)malloc(str_len + 1);if (!str->buffer){return NON_ALLOCATED;}// 字符串buffer调用memset置0memset(str->buffer, 0, sizeof(char) * (str_len + 1));// 4 填充buffer内容for (int i = 0; i < str_len; i++){str->buffer[i] = chars[i];}str->length = str_len; // 设置lengthreturn OK;
}/*!* @brief **字符串复制*** @param dest_str 目标串(指针)* @param src_str 被复制串(指针)* @return 执行结果* @note* 字符串复制* -------------* -------------** <span style="color:#FF6700">* Ctrl+c / Ctrl+v :-)* </span>** -------------* ### 1 释放目标串的buffer###* ### 2 目标串的buffer分配内存###*   **if** 内存分配失败 :\n*    返回NON_ALLOCATED \n*   目标串buffer调用memset置0\n* ###3 填充buffer内容, 并设置length###*/
status_t StringCopy(string_t* dest_str, string_t* src_str)
{// 1 ----- 释放目标串的buffer -----if (dest_str->buffer){free(dest_str->buffer);}// 2 ----- 目标串的buffer分配内存 -----if (!(dest_str->buffer = (char*)malloc(src_str->length + 1))) // if 内存分配失败{// 返回NON_ALLOCATEDreturn NON_ALLOCATED;}// 目标串buffer调用memset置0memset(dest_str->buffer, 0, sizeof(char) * (src_str->length + 1));// 3 ----- 填充buffer内容, 并设置length -----for (int i = 0; i < src_str->length; i++){dest_str->buffer[i] = src_str->buffer[i];}dest_str->length = src_str->length;return OK;
}/*!* @brief **是否为空字符串*** @param str 字符串* @return 结果* 是否为空字符串* ------------* ------------** <span style="color:#FF8100">* 可能是寂寞, 空气变得很稀薄* </span>** ------------* 直接返回 str->length == 0*/
int StringEmpty(string_t* str)
{return str->length == 0;
}/*!* @brief **字符串比较*** @param str1 字符串1(指针)* @param str2 字符串2(指针)* @return 比较结果* @note* 字符串比较* ---------* ---------** <span style="color:#FF8100">* one by one* </span>** ---------* ### 1 依次遍历两个字符串, 每趟对两个遍历字符进行比较###* ### 2 如果过程1没有得出结果, 比较长度###*/
int StringCompare(string_t* str1, string_t* str2)
{// 1 依次遍历两个字符串, 每趟对两个遍历字符进行比较for (int i = 0; i < str1->length && i < str2->length; i++){if (str1->buffer[i] != str2->buffer[i]){return str1->buffer[i] - str2->buffer[i];}}// 2 如果过程1没有得出结果, 比较长度return str1->length - str2->length;
}/*!* @brief **字符串长度*** @param str 字符串* @return 长度* 字符串长度* ---------* ---------** <span style="color:#FF6700">* 光年是长度单位* </span>** ---------*/
int StringLength(string_t* str)
{return str->length;
}/*!* @brief **字符串清空*** @param str 字符串* @return 执行结果* @note* 字符串清空* ---------* ---------** <span style="color:#DF5A00">* 离开你其实我不见得过得比你快乐\n* 我不懂怎么割舍,只想把你留着\n* 我很认真改变自己努力活着\n* 面对人前人后的苛责,我还要等\n* </span>** ---------* ###1 释放buffer###* ###2 length置0###*/
status_t StringClear(string_t* str)
{// 释放bufferif (str->buffer){free(str->buffer);str->buffer = NULL;}str->length = 0; // length置0return OK;
}/*!* @brief **字符串拼接*** @param resulting_string 结果串* @param str1 字符串1* @param str2 字符串2* @return 执行结果* @note* 字符串拼接* ---------* ---------** ---------* ### 1 释放结果串的buffer###* ### 2 结果串的buffer分配内存###* ###3 对结果串依次填充两个字符串###* - 两个循环遍历, 执行字符填充* + 字符串str1填充* + 字符串str2填充* - 设置结果串的length*/
status_t StringConcat(string_t* resulting_string, string_t* str1, string_t* str2)
{// ----- 1 释放结果串的buffer -----if (resulting_string->buffer){free(resulting_string->buffer);}// ----- 2 结果串的buffer分配内存 -----if (!(resulting_string->buffer = (char*)malloc(str1->length + str2->length + 1))){return NON_ALLOCATED;}memset(resulting_string->buffer, 0, sizeof(char) * (str1->length + str2->length + 1));// ----- 3 对结果串依次填充两个字符串 -----// 字符串str1填充for (int i = 0; i < str1->length; i++){resulting_string->buffer[i] = str1->buffer[i];}// 字符串str2填充for (int i = 0; i < str2->length; i++){resulting_string->buffer[str1->length + i] = str2->buffer[i];}// 设置结果串的lengthresulting_string->length = str1->length + str2->length;return OK;
}/*!* @brief **字符串子串*** @param str 字符串* @param sub_str 子串* @param offset 字符串偏移量* @param sub_str_len 子串长度* @return 执行结果* @note* 字符串子串* ---------* ---------** ---------* ###1 边界条件判断###*   **if** 若干边界条件错误 :\n*    返回OVERFLOW \n* ###2 释放子串sub_str->buffer###* ###3 空子串处理###*   **if** 子串长度为0\n*    buffer为NULL, length为0\n*    返回OK\n* ###4 构造子串###* - 分配子串buffer内存 \n*   **if** 内存分配失败 :\n*    返回OVERFLOW \n*/
status_t StringSubStr(string_t* str, string_t* sub_str, int offset, int sub_str_len)
{// ----- 1 边界条件判断 -----// if 若干边界条件错误if (offset < 0 || offset > str->length ||sub_str_len < 0 || sub_str_len > str->length - offset + 1){return OVERFLOW; // 返回OVERFLOW}// ----- 2 释放子串sub_str->buffer -----if (sub_str->buffer){free(sub_str->buffer);}// ----- 3 空子串处理 -----if (sub_str_len == 0) // if 子串长度为0{sub_str->buffer = NULL; // buffer为NULLsub_str->length = 0; // length为0return OK;}// ----- 4 构造子串 -----sub_str->buffer = (char*)malloc(sub_str_len); // - 分配子串buffer内存if (sub_str->buffer == NULL) // if 内存分配失败{return OVERFLOW;}// 子串buffer每个字符赋值for (int i = 0; i < sub_str_len; i++){sub_str->buffer[i] = str->buffer[offset + i];}sub_str->length = sub_str_len; // 更新子串lengthreturn OK;
}/*!* @brief **字符串插入*** @param str 被插入的字符串* @param index 插入位置(插入到该位置前)* @param insert_str 待插入字符* @return 执行结果* @note* 字符串插入* ---------* ---------** ---------* ###1 非法插入位置处理###*   返回OVERFLOW* ###2 待插入字符串为空串处理###*   直接返回OK* ###3 重新分配内存###*   新申请的字符串长度: str->length + insert_str->length\n*   使用realloc重新对被插入字符串分配内存\n*   **if** 申请内存失败 :\n*    返回NON_ALLOCATED\n* ###4 执行插入###* - **移动被插入字符串的插入位置后侧(包含)的所有字符**\n*   索引[index ... str->length - 1], 一共str->length - index个字符,\n*   向后侧移动insert_str->length个位置 \n*   更新被插入字符串的length*/
status_t StringInsert(string_t* str, int index, string_t* insert_str)
{// ----- 1 非法插入位置处理 -----if (index < 0 || index > str->length){return OVERFLOW;}// ----- 2 待插入字符串为空串处理 -----if (insert_str->length == 0){return OK;}// ----- 3 重新分配内存 -----int new_length = str->length + insert_str->length; // 新申请的字符串长度: str->length + insert_str->lengthstr->buffer = (char*)realloc(str->buffer, sizeof(char) * (new_length + 1)); // 使用realloc重新对被插入字符串分配内存if (str->buffer == NULL) // if 申请内存失败{return NON_ALLOCATED; // 返回NON_ALLOCATED}// ----- 4 执行插入 -----// 移动被插入字符串的插入位置后侧(包含)所有字符int i = str->length - 1;for (; i >= index; i--) // 索引[index ... str->length - 1], 一共str->length - index个字符{str->buffer[i + insert_str->length] = str->buffer[i]; // 向后侧移动insert_str->length个位置}// 使用待插入字符串赋值for (i = 0; i < insert_str->length; i++) // 遍历insert_str{str->buffer[index + i] = insert_str->buffer[i]; // insert_str向str相应位置赋值}// 更新被插入字符串的lengthstr->length = new_length;return OK;
}/*!* @brief **字符串暴力匹配(BF)*** @param str 目标串* @param pattern 模式串* @param offset 目标串偏移量* @return 目标串的匹配索引* @note* 字符串暴力匹配(BF)* ----------------* ----------------** <span style="color:#FF8100">* 虽然这个方法看着不高级, 但是它不需要开辟额外的内存, 很多场景下比KMP更实用 :-)* </span>** ----------------* ###1 目标串的匹配索引初始化为-1###* ###2 执行BF算法###*   **for loop** 遍历目标串(starting_index为每次失配后, 下一趟匹配目标串的起始索引, 初始化为offset) :\n*    模式串索引0开始\n*    **while** 模式串遍历未结束 :\n*     **if** 目标串遍历字符 不匹配 模式串遍历字符 :\n*      跳出循环\n*     模式串索引加1(向后移动1位) \n*    **if** 模式串遍历结束 :\n*     目标串匹配索引为starting_index\n*     跳出循环\n*/
int StringBruteForceSearch(string_t* str, string_t* pattern, int offset)
{// 1 ----- 目标串的匹配索引初始化为-1 -----int match_index = -1;// 2 ----- 执行BF算法 -----// 遍历目标串(starting_index为每次失配后, 下一趟匹配的目标串的起始索引, 初始化为offset)for (int starting_index = offset; starting_index <= str->length - pattern->length; starting_index++){int pattern_index = 0; // 模式串索引0开始while (pattern_index < pattern->length) // while 模式串遍历未结束{// if 目标串遍历字符不匹配模式串遍历字符: 跳出循环if (str->buffer[starting_index + pattern_index] != pattern->buffer[pattern_index]){break;}pattern_index++; // 模式串索引加1(向后移动1位)}if (pattern_index == pattern->length) // if 模式串遍历结束{match_index = starting_index; // 目标串匹配索引为starting_indexbreak; // 跳出for循环}}return match_index; // 返回match_index
}/*!* @brief **KMP算法求next数组*** @param pattern 模式串* @param pattern_len 模式串长度* @param next next数组(int二级指针)* @return 执行结果* @note* KMP算法求next数组* ----------------* ----------------** <span style="color:#FFC921">* 这不是后退, 这只是换个合适的位置, 再一次进攻* </span>** ----------------** 求next数组的意义:\n*   发掘模式串的内在信息, 当模式串在某个位置(i)的字符失配时,* **下一趟不再从模式串首字符重新开始匹配, 而是从位置next[i]开始*** ###1 初始化index/starting_index/next[0]###* - **index**\n*   模式串进行匹配的索引, 初始化为 **0** \n* - **starting_index**\n*   模式串在某个索引位置的字符失配后, 重新开始进行匹配的索引, 初始化为 **-1**\n* - **next[0]**\n*   设置为 **-1**\n* ###2 递归构造next数组 ###*   **while** 遍历模式串 :\n*    **if** starting_index != -1 (非起始字符匹配过程) :\n*     **if** pattern[index]和pattern[starting_index]相同 (此时需要进行两侧区域扩展):\n*      index加1(向后移动1位)\n*      starting_index加1(向后移动1位)\n*      更新next数组index索引位置的值为starting_index(扩展完成)\n* ```* 示例:* pattern[index]和pattern[starting_index], 左右两侧的相同字符串区域扩展** a b c d 5 6 a b c d 7* a b ...* ^ ... a b* | ^* | |* starting_index |* index** 此时:* index == 8 (右侧区域遍历至索引8)* starting_index == 2 (左侧区域遍历至索引2)** 执行:* 判断pattern[8]是否等于pattern[2]:* 相同(都为'c') --> 走if( == )分支:* index++ -> 9,* starting_index++ -> 3* 更新next[index] => next[9] = 3 (如果在模式串位置9失配, 下一次匹配点直接从3开始)** 执行结果:* a b c d 5 6 a b c d 7* a b c ...* ^ ... a b c* | ^* | |* starting_index |* index** ```*     **else** (两侧区域收缩)\n*      令starting_index = next[starting_index]\n* ```* 示例:* pattern[index]和pattern[starting_index], 左右两侧的相同字符串区域扩展** a b c d 5 6 a b c d c y b e r d a s h a b c d 5 6 a b c e* a b c d 5 6 a b c ...* ^ ... a b c d 5 6 a b c* | ^* | |* starting_index |* index** 此时:* index == 28 (右侧区域遍历至索引28)* starting_index == 9 (左侧区域遍历至索引9)** 执行:* 判断pattern[28]是否等于pattern[9]:* 不同 --> 走else分支:* 将next[starting_index]赋给starting_index** 执行结果:* a b c d 5 6 a b c d c y b e r d a s h a b c d 5 6 a b c e* a b c d 5 6 a b c ...* ^ ^ ... a b c d 5 6 a b c* | | ^* | | |* starting_index |* index* ```*    **else**(起始字符匹配) \n*     index加1(向后移动1位)\n*     starting_index加1(向后移动1位)\n*     更新next数组index索引位置的值为starting_index\n* ```* 当模式串字符pattern[1]失配时, 下一趟必然从pattern[0]开始重新进行匹配,* 因此可确定next[1] = 0* 令next[0] = X; next[1] = next[0] + 1 => 得next[0] = X = -1* 此处逻辑可以和上面的pattern[index] == pattern[starting_index]分支逻辑做代码合并* ```*/
status_t KMPNext(const char* pattern, int pattern_len, int** next)
{// ----- 1 初始化index/starting_index/next[0] -----int index = 0;int first_char_next_index = -1;int starting_index = first_char_next_index;(*next)[0] = starting_index;// ----- 2 递归构造next数组 -----while (index < pattern_len) // 遍历模式串{if (starting_index != first_char_next_index) // 非起始字符匹配过程{if (pattern[index] == pattern[starting_index]) // 此时需要进行两侧区域扩展{// 示例:// pattern[index]和pattern[starting_index], 左右两侧的相同字符串区域扩展//// a b c d 5 6 a b c d 7// a b// ^ a b// | ^// | |// starting_index |// index//// 此时:// index == 8 (右侧区域遍历至索引8)// starting_index == 2 (左侧区域遍历至索引2)//// 执行:// 判断pattern[8]是否等于pattern[2]:// 相同(都为'c') --> 走if( == )分支:// index++ -> 9,// starting_index++ -> 3// 更新next[index] => next[9] = 3 (如果在模式串位置9失配, 下一次匹配点直接从3开始)//// 执行结果:// a b c d 5 6 a b c d 7// a b c// ^ a b c// | ^// | |// starting_index |// indexindex++;starting_index++;(*next)[index] = starting_index;}else{// 示例:// pattern[index]和pattern[starting_index], 左右两侧的相同字符串区域扩展//// a b c d 5 6 a b c d c y b e r d a s h a b c d 5 6 a b c e// a b c d 5 6 a b c// ^ a b c d 5 6 a b c// | ^// | |// starting_index |// index//// 此时:// index == 28 (右侧区域遍历至索引28)// starting_index == 9 (左侧区域遍历至索引9)//// 执行:// 判断pattern[28]是否等于pattern[9]:// 不同 --> 走else分支:// 将next[starting_index]赋给starting_index//// 执行结果:// a b c d 5 6 a b c d c y b e r d a s h a b c d 5 6 a b c e// a b c d 5 6 a b c// ^ ^ a b c d 5 6 a b c// | | ^// | | |// starting_index |// indexstarting_index = (*next)[starting_index];}}else // 起始字符匹配{index++;starting_index++;(*next)[index] = starting_index;}}return OK;
}/*!* @brief **字符串KMP匹配*** @param str 目标串* @param pattern 模式串* @param offset 目标串偏移量* @return 目标串匹配索引* @note* 字符串KMP匹配* ------------* ------------** <span style="color:#FFC921">* Knuth-Morris-Pratt字符串查找算法(简称为KMP算法),** 由高德纳和沃恩·普拉特(英语:Vaughan Pratt)在1974年构思,** 同年詹姆斯·H·莫里斯(英语:James H. Morris)也独立地设计出该算法,** 最终三人于1977年联合发表* </span>** ------------* ###1 分配next数组内存###*   **if** 分配内存失败 :\n*    返回NON_ALLOCATED\n*   memset置0\n* ###2 求模式串next数组###*   调用KMPNext函数求next数组\n*   **if** 调用失败 :\n*    返回错误码\n* ###3 使用next数组找模式串的匹配位置(的索引)###*   **while** 目标串和模式串中, 某个串未遍历完 :\n*    **if** 模式串索引字符 == 目标串索引的字符\n*     模式串索引and目标串索引, 则向后移1位\n*    **else**(模式串索引字符 != 目标串索引的字符): \n*     **if** 模式串索引0字符失配 :\n*      目标串索引向后移1位\n*     **else**(模式串索引非0字符失配) :\n*      从模式串的next[pattern_index]开始执行下一趟匹配\n* ###4 求目标串匹配索引###*   **if** 模式串匹配索引 < 模式串长度 :\n*    目标串匹配索引为-1(没有匹配点)\n*   **else**\n*    目标串匹配索引为str_index - pattern_len\n*/
int StringKMPSearch(string_t* str, string_t* pattern, int offset)
{// ----- 1 分配next数组内存 -----int* next = (int*)malloc((pattern->length + 1) * sizeof(int));if (next == NULL) // if 分配内存失败{return NON_ALLOCATED; // 返回NON_ALLOCATED}memset(next, 0, sizeof(int) * (pattern->length + 1)); // memset置0// ----- 2 求模式串next数组 -----// 调用KMPNext函数求next数组status_t status = KMPNext(pattern->buffer, pattern->length, &next);if (status != OK){return status;}// ----- 3 使用next数组找模式串的匹配位置(的索引) -----int pattern_index = 0; // 模式串索引int str_index = offset; // 目标串索引while (pattern_index < pattern->length && str_index < str->length) // while 目标串和模式串中, 某个串未遍历完{if (pattern->buffer[pattern_index] == str->buffer[str_index]) // if 模式串索引字符 == 目标串索引的字符{pattern_index++; // 模式串索引向后移1位str_index++; // 目标串索引向后移1位}else // else(模式串索引字符 != 目标串索引的字符){if (pattern_index == 0) // if 模式串索引0字符失配{str_index++; // 目标串索引向后移1位}else // else(模式串索引非0字符失配){pattern_index = next[pattern_index]; // 从模式串的next[pattern_index]开始执行下一趟匹配}}}free(next);// ----- 4 求目标串匹配索引 -----int match_pos;if (pattern_index < pattern->length) //if 模式串匹配索引 < 模式串长度{match_pos = -1; // 目标串匹配索引为-1(不匹配)}else{match_pos = str_index - pattern->length; // 目标串匹配索引为str_index - pattern_len}return match_pos;
}
- main.c
#include <stdio.h>
#include <stdlib.h>#include "guistar_string.h"/*!* @brief **字符串打印*** @param str 字符串* @note* 字符串打印* ---------* ---------** ---------* ###1 空字符串处理###*   直接返回* ### 2 调用printf ###*/
static void inline StringPrint(string_t* str)
{// ----- 1 空字符串处理 -----if (str == NULL || str->length <= 0){return; // 直接返回}// ----- 2 调用printf -----printf("%.*s\n", str->length, str->buffer);
}/*!* @brief **测试字符串复制*** @note* 测试字符串复制* ------------* ------------** ------------* ###1 被复制串和复制串初始化###*   被复制串"Hello cyberdash!"* ###2 执行复制###*/
void TestStringCopy()
{printf("\n");printf("|------------------------ CyberDash ------------------------|\n");printf("| Test StringCopy |\n");printf("| 测试字符串复制 |\n");// ----- 1 被复制串和复制串初始化 -----string_t dest_str = { .buffer = NULL, .length = 0};string_t src_str = { .buffer = NULL, .length = 0};// 被复制串"Hello cyberdash!"char chars[50] = "Hello cyberdash!";StringAssign(&src_str, chars, (int)strlen(chars));// ----- 2 执行复制 -----StringCopy(&dest_str, &src_str);StringPrint(&dest_str);printf("|-----------------------------------------------------------|\n\n");
}/*!* @brief **测试字符串比较*** @note* 测试字符串比较* ------------* ------------** ------------* ###1 初始化4个字符串###* ###2 做比较并打印结果###*/
void TestStringCompare()
{printf("\n");printf("|------------------------ CyberDash ------------------------|\n");printf("| Test StringCompare |\n");printf("| 测试字符串比较 |\n");// ----- 1 初始化4个字符串 -----string_t str1 = { .buffer = NULL, .length = 0};string_t str2 = { .buffer = NULL, .length = 0};string_t str3 = { .buffer = NULL, .length = 0};string_t str4 = { .buffer = NULL, .length = 0};char chars1[50] = "Hello cyberdash!";char chars2[50] = "Hello cyberdash!";char chars3[50] = "Hello cyberdash and hello Mr. Yuan";char chars4[50] = "Hi cyberdash";StringAssign(&str1, chars1, (int)strlen(chars1));StringAssign(&str2, chars2, (int)strlen(chars2));StringAssign(&str3, chars3, (int)strlen(chars3));StringAssign(&str4, chars4, (int)strlen(chars4));// ----- 2 做比较并打印结果 -----printf("str1 compare to str2: %d\n", StringCompare(&str1, &str2));printf("str1 compare to str3: %d\n", StringCompare(&str1, &str3));printf("str2 compare to str3: %d\n", StringCompare(&str2, &str3));printf("str1 compare to str4: %d\n", StringCompare(&str1, &str4));printf("|-----------------------------------------------------------|\n\n");
}/*!* @brief **测试字符串拼接*** @note* 测试字符串拼接* ------------* ------------** ------------* ###1 初始化2个字符串###* ###2 执行拼接###*/
void TestStringConcat()
{printf("\n");printf("|------------------------ CyberDash ------------------------|\n");printf("| Test StringConcat |\n");printf("| 测试字符串拼接 |\n");// ----- 1 初始化2个字符串 -----string_t str1;string_t str2;string_t resulting_str;memset(&str1, 0, sizeof(string_t));memset(&str2, 0, sizeof(string_t));memset(&resulting_str, 0, sizeof(string_t));char chars1[50] = "hello cyberdash,";char chars2[50] = "hello Mr. Yuan.";StringAssign(&str1, chars1, (int)strlen(chars1));StringAssign(&str2, chars2, (int)strlen(chars2));// ----- 2 执行拼接 -----StringConcat(&resulting_str, &str1, &str2);StringPrint(&resulting_str);printf("|-----------------------------------------------------------|\n\n");
}/*!* @brief **测试字符串子串*** @note* 测试字符串子串* ------------* ------------** ------------* ###1 初始化字符串###*   "hello cyberdash,"* ###2 求子串###*   原始字符串偏移量6, 子串长度9*/
void TestStringSubStr()
{printf("\n");printf("|------------------------ CyberDash ------------------------|\n");printf("| Test StringSubStr |\n");printf("| 测试字符串子串 |\n");string_t sub_str;string_t str;memset(&str, 0, sizeof(string_t));memset(&sub_str, 0, sizeof(string_t));// ----- 1 初始化字符串 -----// "hello cyberdash,"char chars[50] = "hello cyberdash,";StringAssign(&str, chars, (int)strlen(chars));int offset = 6;int sub_str_len = 9;// ----- 2 求子串 -----// 原始字符串偏移量6, 子串长度9StringSubStr(&str, &sub_str, offset, sub_str_len);StringPrint(&sub_str);printf("|-----------------------------------------------------------|\n\n");
}/*!* @brief **测试字符串插入*** @note* 测试字符串插入* ------------* ------------** ------------* ###1 初始化字符串&待插入字符串 ###* ###2 调用StringInsert执行插入###*/
void TestStringInsert()
{printf("\n");printf("|------------------------ CyberDash ------------------------|\n");printf("| Test StringInsert |\n");printf("| 测试字符串插入 |\n");// ----- 1 初始化字符串&待插入字符串 -----string_t str;string_t insert_str;memset(&str, 0, sizeof(string_t));memset(&insert_str, 0, sizeof(string_t));char chars[50] = "Hello Dash";char insert_chars[50] = "Cyber";printf("插入\"%s\"到\"%s\"中间:\n\n", insert_chars, chars);StringAssign(&str, chars, (int)strlen(chars));StringAssign(&insert_str, insert_chars, (int)strlen(insert_chars));// ----- 2 调用StringInsert执行插入 -----StringInsert(&str, 6, &insert_str);StringPrint(&str);printf("|-----------------------------------------------------------|\n\n");
}/*!* @brief **测试字符串匹配(BF算法 & KMP算法)*** @note* 测试字符串匹配(BF算法 & KMP算法)* -----------------------------* -----------------------------** -----------------------------* ###1 初始化目标串和模式串###*   目标串: "123 cyberdash cyber 456"\n*   模式串: "cyberdash cyber"\n* ###2 使用BF和KMP进行匹配###* - BF匹配, 目标串偏移量2\n* - KMP匹配, 目标串偏移量2\n*/
void TestStringSearch()
{printf("\n");printf("|------------------------ CyberDash ------------------------|\n");printf("| Test StringSearch BF & StringKMPSearch |\n");printf("| 测试字符串搜索BF & KMP算法 |\n");string_t str;string_t pattern;memset(&str, 0, sizeof(string_t));memset(&pattern, 0, sizeof(string_t));// ----- 1 初始化目标串和模式串 -----char str_chars[50] = "123 cyberdash cyber 456"; // 目标串: "123 cyberdash cyber 456"char pattern_chars[50] = "cyberdash cyber"; // 模式串: "cyberdash cyber"StringAssign(&str, str_chars, (int)strlen(str_chars));StringAssign(&pattern, pattern_chars, (int)strlen(pattern_chars));printf("目标串: ");StringPrint(&str);printf("模式串: ");StringPrint(&pattern);// ----- 2 使用BF和KMP进行匹配 -----// BF匹配, 目标串偏移量2printf("BF算法查找匹配索引: %d\n", StringBruteForceSearch(&str, &pattern, 2));// KMP匹配, 目标串偏移量2printf("KMP算法查找匹配索引: %d\n", StringKMPSearch(&str, &pattern, 2));printf("|-----------------------------------------------------------|\n\n");
}int main()
{printf("串!\n");/// - 测试字符串复制TestStringCopy();/// - 测试字符串比较TestStringCompare();/// - 测试字符串拼接TestStringConcat();/// - 测试字符串子串TestStringSubStr();/// - 测试字符串插入TestStringInsert();/// - 测试字符串匹配(BF和KMP)TestStringSearch();return 0;
}
运行结果
串!|------------------------ CyberDash ------------------------|
| Test StringCopy |
| 测试字符串复制 |
Hello cyberdash!
|-----------------------------------------------------------||------------------------ CyberDash ------------------------|
| Test StringCompare |
| 测试字符串比较 |
str1 compare to str2: 0
str1 compare to str3: 1
str2 compare to str3: 1
str1 compare to str4: -4
|-----------------------------------------------------------||------------------------ CyberDash ------------------------|
| Test StringConcat |
| 测试字符串拼接 |
hello cyberdash,hello Mr. Yuan.
|-----------------------------------------------------------||------------------------ CyberDash ------------------------|
| Test StringSubStr |
| 测试字符串子串 |
cyberdash
|-----------------------------------------------------------||------------------------ CyberDash ------------------------|
| Test StringInsert |
| 测试字符串插入 |
插入"Cyber"到"Hello Dash"中间:Hello CyberDash
|-----------------------------------------------------------||------------------------ CyberDash ------------------------|
| Test StringSearch BF & StringKMPSearch |
| 测试字符串搜索BF & KMP算法 |
目标串: 123 cyberdash cyber 456
模式串: cyberdash cyber
BF算法查找匹配索引: 4
KMP算法查找匹配索引: 4
|-----------------------------------------------------------|Process returned 0 (0x0) execution time : 0.090 s
Press any key to continue.