zoukankan      html  css  js  c++  java
  • 【数据结构】之串(C语言描述)

      串(字符串)是编程中最常用的结构,但 C语言 中没有“字符串”这种变量,只能通过字符数组的形式表示字符串。

      C语言 为我们提供了一个 string.h 的头文件,通过这个头文件,我们可以实现对字符串的各种操作,如拷贝、比较等,具体用法请参考【C语言库函数】

      当然,我们对字符串的操作可能不仅仅局限于 string.h 这个头文件给我们提供的这些方法,因此,我们可以自己实现一个字符串的数据结构,通过在这里面编写一些实用的方法,实现我们的需求。

      以下是实用 C语言 编写的一个字符串的头文件 String.h,代码如下:

    /**
     * 串(顺序存储方式)
     * 注意:字符串都是以“”符号结尾的
     */
    #include <Constant.h>
    
    // 定义字符串的数据结构体
    typedef struct String {
        char* data;     // 字符串中的数据
        int currLength; // 字符串的当前长度
        int maxLength;  // 字符串的总长度
    } String;
    
    // 0.获取某个字符串的长度
    int getCharArrayLength(char* string) {
        int length = 0;
        while(string[length] != '') {
            length++;
        }
        return length;
    }
    
    // 1.初始化字符串(创建一个新的字符串,其中包含string中的所有字符)
    Status initString(String* S, char* string) {
        int i = 0;
        // 获取字符串的长度
        int length = getCharArrayLength(string);
        // 字符串赋值
        S->data = (char*)malloc(length * sizeof(char));
        if(S->data == NULL) {
            printf("initString => 空间分配失败,初始化字符串失败!
    ");
            return FAILURE;
        }
        S->currLength = length;
        S->maxLength = length;
        for(i = 0; i < length; i++) {
            S->data[i] = string[i];
        }
        return SUCCESS;
    }
    
    // 2.复制字符串(将字符串string中的所有字符复制到字符串S中)
    Status copyString(String* S, char* string) {
        int i;
        int length = getCharArrayLength(string);
        if(S->data == NULL) {
            printf("copyString => 字符串不存在,复制失败!
    ");
            return FAILURE;
        }
        if(length > S->maxLength) {
            S->data = (char*)realloc(S->data, length * sizeof(char));
            if(S->data == NULL) {
                printf("copyString => 重分配空间失败,复制字符串失败!
    ");
                return FAILURE;
            }
            S->maxLength = length;
        }
        S->currLength = length;
        for(i = 0; i < length; i++) {
            S->data[i] = string[i];
        }
        return SUCCESS;
    }
    
    // 3.判断字符串是否为空
    Status isStringEmpty(String* S) {
        if(S->data == NULL) {
            printf("isStringEmpty => 字符串不存在!
    ");
            exit(1);
        }
        if(S->currLength == 0) {
            return TRUE;
        }
        return FALSE;
    }
    
    // 4.比较两个字符串的大小(返回的是S1与S2比较的结果)
    // 当两个字符串的长度相等,且对应字符都相同时,称这两个字符串相等;否则,看第一个不相等的字符比较结果,字符较大的字符串较大
    Status compareString(String* S1, String* S2) {
        int i = 0;
        // 判空
        if(S1->data == NULL || S2->data == NULL) {
            printf("compareString => 其中一个字符串不存在!
    ");
            exit(1);
        }
        // 某一个字符串为空
        if(S1->currLength == 0) {
            if(S2->currLength == 0) {
                return EQUAL;
            } else {
                return SMALLER;
            }
        }
        if(S2->currLength == 0) {
            if(S1->currLength == 0) {
                return EQUAL;
            } else {
                return BIGGER;
            }
        }
        // 两个字符串都不为空时,逐个字符比较
        for(i = 0; ;i++) {
            if(i == S1->currLength && i == S2->currLength) {
                return EQUAL;
            }
            if(i >= S1->currLength) {
                return SMALLER;
            }
            if(i >= S2->currLength) {
                return BIGGER;
            }
            if(S1->data[i] > S2->data[i]) {
                return BIGGER;
            } else if(S1->data[i] < S2->data[i]) {
                return SMALLER;
            }
        }
    }
    
    // 5.获取字符串的长度
    int getStringLength(String* S) {
        if(S->data == NULL) {
            printf("getStringLength => 字符串不存在!
    ");
            exit(1);
        }
        return S->currLength;
    }
    
    // 6.清空字符串
    Status clearString(String* S) {
        if(S->data == NULL) {
            printf("clearString => 字符串不存在!
    ");
            return FAILURE;
        }
        S->currLength = 0;
        return SUCCESS;
    }
    
    // 7.将字符串S2连接到字符串S1后面并返回
    Status concatString(String* S1, String* S2) {
        if(S1->data == NULL || S2->data == NULL) {
            printf("concatString => 其中一个字符串不存在!
    ");
            return FAILURE;
        }
        int i;
        int len1 = getStringLength(S1);
        int len2 = getStringLength(S2);
        if(S1->maxLength < len1 + len2) {
            S1->data = (char*)realloc(S1->data, (len1 + len2) * sizeof(char));
            if(S1->data == NULL) {
                printf("concatString => 重分配空间失败,字符串拼接失败!
    ");
                return FAILURE;
            }
            S1->maxLength = len1 + len2;
        }
        for(i = 0; i < len2; i++) {
            S1->data[len1 + i] = S2->data[i];
        }
        S1->currLength = len1 + len2;
        return SUCCESS;
    }
    
    // 8.返回字符串S中从pos位置开始,长度为len的子串
    char* getSubString(String* S, int pos, int len) {
        char* result;
        int i;
        if(S->data == NULL) {
            printf("getSubString => 字符串不存在!
    ");
            exit(1);
        }
        if(pos < 0 || pos >= S->currLength) {
            printf("getSubString => pos参数超出范围!
    ");
            exit(1);
        }
        if(len > S->currLength - pos) {
            printf("getSubString => 子串长度超出范围!
    ");
            exit(1);
        }
        for(i = 0; i < len; i++) {
            *(result + i) = S->data[pos + i];
        }
        *(result + i) = '';
        return result;
    }
    
    // 9.返回字符串S中从pos位置开始的与子串string相等的第一个子串的位置
    int locateSubString(String* S, char* string, int pos) {
        int i, j;
        int length = getCharArrayLength(string);
        if(S->data == NULL) {
            printf("locateSubString => 字符串不存在!
    ");
            exit(1);
        }
        if(pos < 0 || pos >= S->currLength) {
            printf("locateSubString => pos参数超出范围!");
            exit(1);
        }
        if(length + pos > S->currLength) {
            printf("locateSubString => 子串长度超出范围!
    ");
            exit(1);
        }
        for(i = pos; i <= S->currLength - length; i++) {
            for(j = 0; j < length; j++) {
                if(S->data[i + j] != string[j]) {
                    break;
                }
            }
            if(j == length) {
                return i;
            }
        }
        return -1;
    }
    
    // 10.在字符串S的pos位置插入字符串string
    Status stringInsert(String* S, int pos, char* string) {
        int i;
        int length = getCharArrayLength(string);
        if(S->data == NULL) {
            printf("stringInsert => 字符串不存在,插入字符失败!
    ");
            return FAILURE;
        }
        if(pos < 0 || pos > S->currLength) {
            printf("stringInsert => pos参数超出范围,插入字符失败!
    ");
            return FAILURE;
        }
        if(S->currLength + length > S->maxLength) {
            S->data = (char*)realloc(S->data, (S->currLength + length) * sizeof(char));
            if(S->data == NULL) {
                printf("stringInsert => 重分配空间失败,插入字符失败!
    ");
                return FAILURE;
            }
            S->maxLength = S->currLength + length;
        }
        for(i = S->currLength - 1; i >= pos; i--) {
            S->data[i + length] = S->data[i];
        }
        for(i = 0; i < length; i++) {
            S->data[pos + i] = string[i];
        }
        S->currLength += length;
        return SUCCESS;
    }
    
    // 11.删除字符串S中从pos位置开始的len个字符
    Status stringDelete(String* S, int pos, int len) {
        int i;
        if(S->data == NULL) {
            printf("stringDelete => 字符串不存在,删除字符失败!
    ");
            return FAILURE;
        }
        if(pos < 0 || pos >= S->currLength) {
            printf("stringDelete => pos参数超出范围,删除字符失败!
    ");
            return FAILURE;
        }
        if(pos + len > S->currLength) {
            printf("stringDelete => 子串长度超出范围,删除字符失败!
    ");
            return FAILURE;
        }
        for(i = pos + len; i < S->currLength; i++) {
            S->data[i - len] = S->data[i];
        }
        S->currLength -= len;
        return SUCCESS;
    }
    
    // 12.用字符串newStr替换字符串S中出现的所有与子串oldStr相同的不重叠的子串
    Status replaceString(String* S, char* oldStr, char* newStr) {
        int index;
        int oldLen = getCharArrayLength(oldStr);
        int newLen = getCharArrayLength(newStr);
        if(S->data == NULL) {
            printf("replaceString => 字符串不存在,替换失败!
    ");
            return FAILURE;
        }
        index = locateSubString(S, oldStr, 0);
        while(index >= 0 && index + oldLen <= S->currLength) {
            stringDelete(S, index, oldLen);
            stringInsert(S, index, newStr);
            if(oldLen + index + newLen >= S->currLength) {
                break;
            }
            index = locateSubString(S, oldStr, index + newLen);
        }
        return SUCCESS;
    }
    
    // 13.遍历字符串
    void traverseString(String* S) {
        int i;
        if(S->data == NULL) {
            printf("traverseString => 字符串不存在,遍历失败!
    ");
            exit(1);
        }
        printf("遍历字符串:");
        for(i = 0; i < S->currLength; i++) {
            printf("%c", S->data[i]);
        }
        printf("
    ");
    }
    
    // 14.销毁字符串
    Status destroyString(String* S) {
        if(S->data == NULL) {
            printf("destroyString => 字符串不存在,不需要销毁!
    ");
            return FAILURE;
        }
        free(S->data);
        S->data = NULL;
        S->currLength = 0;
        S->maxLength = 0;
        return SUCCESS;
    }
    
    // 测试函数
    int testString() {
        // 声明变量
        String str1, str2;
        // 初始化字符串
        if(initString(&str1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]") == SUCCESS) {
            printf("初始化字符串S1成功!
    ");
            traverseString(&str1); // 遍历
        }
        if(initString(&str2, "abc") == SUCCESS) {
            printf("初始化字符串S2成功!
    ");
            traverseString(&str2);
        }
        // 清空字符串
        if(clearString(&str2) == SUCCESS) {
            printf("清空字符串S2成功!
    ");
        }
        // 判断字符串是否为空
        printf("字符串S1是否为空?%s
    ", isStringEmpty(&str1) ? "" : "");
        printf("字符串S2是否为空?%s
    ", isStringEmpty(&str2) ? "" : "");
        // 字符串复制
        if(copyString(&str2, "abcdefg") == SUCCESS) {
            printf("字符串复制成功!
    ");
            traverseString(&str2);
        }
        // 字符串连接
        if(concatString(&str1, &str2) == SUCCESS) {
            printf("将字符串S2连接到S1后面成功!
    ");
            traverseString(&str1);
        }
        // 比较两个字符串的大小
        printf("S1比S2的关系?%d
    ", compareString(&str1, &str2));
        // 字符串的长度
        printf("字符串S1的长度:%d
    ", getStringLength(&str1));
        printf("字符串S2的长度:%d
    ", getStringLength(&str2));
        // 取字符串的子串
        printf("S1从58位置开始7个长度的子串是:%s
    ", getSubString(&str1, 0, 7));
        // 返回子串第一次出现的位置
        printf("字符串S1中从20位置起,ABCDE子串第一次出现的位置是%d
    ", locateSubString(&str1, "ABCD", 20));
        // 插入字符串
        if(stringInsert(&str1, 26, "||||||") == SUCCESS) {
            printf("在S1的26位置插入字符串||||||成功!
    ");
            traverseString(&str1);
        }
        // 删除字符串
        if(stringDelete(&str1, 26, 6) == SUCCESS) {
            printf("从S1的26位置删除6个字符成功!
    ");
            traverseString(&str1);
        }
        // 替换字符串
        if(replaceString(&str1, "abcdefg", "0123456789") == SUCCESS) {
            printf("成功将S1中的所有abcdefg替换为0123456789!
    ");
            traverseString(&str1);
        }
        // 销毁字符串
        if(destroyString(&str1) == SUCCESS) {
            printf("销毁字符串S1成功!
    ");
        }
        if(destroyString(&str2) == SUCCESS) {
            printf("销毁字符串S2成功!
    ");
        }
        return 0;
    }

      常量头文件 Constant.h 中的代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define TRUE 1
    #define FALSE 0
    
    #define SUCCESS 1
    #define FAILURE 0
    
    #define SMALLER -1
    #define EQUAL 0
    #define BIGGER 1
    
    typedef int Status;

      主函数所在的文件 main.c 中的代码如下:

    #include <String.h>
    
    int main() {
        testString();
        return 0;
    }

      运行结果如下:

    初始化字符串S1成功!
    遍历字符串:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]
    初始化字符串S2成功!
    遍历字符串:abc
    清空字符串S2成功!
    字符串S1是否为空?否
    字符串S2是否为空?是
    字符串复制成功!
    遍历字符串:abcdefg
    将字符串S2连接到S1后面成功!
    遍历字符串:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]abcdefg
    S1比S2的关系?1
    字符串S1的长度:65
    字符串S2的长度:7
    S1从58位置开始7个长度的子串是:abcdefg
    字符串S1中从20位置起,ABCDE子串第一次出现的位置是26
    在S1的26位置插入字符串||||||成功!
    遍历字符串:abcdefghijklmnopqrstuvwxyz||||||ABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]abcdefg
    从S1的26位置删除6个字符成功!
    遍历字符串:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]abcdefg
    成功将S1中的所有abcdefg替换为0123456789!
    遍历字符串:0123456789hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]0123456789
    销毁字符串S1成功!
    销毁字符串S2成功!
    
    Process returned 0 (0x0)   execution time : 1.783 s
    Press any key to continue.
  • 相关阅读:
    cmd中编译java
    java出错
    去掉开始菜单中新装程序的红色标记【Windows】
    Windows安装java
    看视频缓冲好还一卡一卡【解决】
    python图像卷积
    电脑硬盘、内存
    python 查询Neo4j多节点的多层关系
    python 快速排序实现
    python 二分法实现
  • 原文地址:https://www.cnblogs.com/itgungnir/p/6690133.html
Copyright © 2011-2022 走看看