c语言实现字符串
来源:互联网 发布:怎么卸载mac自带系统 编辑:程序博客网 时间:2024/05/01 16:33
串的基本概念
串 ( 字符串 ) :是零个或多个字符组成的有限序列。 记作: S=”
串值:双引号括起来的字符序列是串值。
串长:串中所包含的字符个数称为该串的长度。
空串 ( 空的字符串 ) :长度为零的串称为空串,它不 包含任何字符。
空格串 ( 空白串 ) :构成串的所有字符都是空格的串 称为空白串。
子串 (substring) :串中任意个连续字符组成的子序 列称为该串的子串,包含子串的串相应地称为主串。
子串的序号:将子串在主串中首次出现时的该子串 的首字符对应在主串中的序号,称为子串在主串中的序
号(或位置)。
串相等:如果两个串的串值相等 ( 相同 ) ,称这两 个串相等。换言之,只有当两个串的长度相等,且各 个对应位置的字符都相同时才相等。
串的基本操作
1.串赋值
2.串拷贝
3.串比较
4.串长度
5.清空串
6.返回第pos个字符起长度为len的字串
7.若存在和T相等的字串,返回其字串第一次出现的位置
8.替换字串
9.在串中的第pos个字符之前插入字串
10.删除第pos个字符起长度为len的字串
11.销毁串
12. 两个串相接
串的表示和实现
◆ 定长顺序存储表示:将串定义成字符数组,利用 串名可以直接访问串值。用这种表示方式,串的存 储空间在编译时确定,其大小不能改变。
特点:
1.操作时间的复杂度基本上基于字符序列的长度
2.如果在操作中出现串值序列的长度超过上界MAXSTRLEN时,约定用截尾法处理.
定长顺序存储结构定义为:
#define MAX_STRLEN 256typedef struct{ char str[MAX_STRLEN] ; int length;} StringType ;
◆ 堆分配存储方式:仍然用一组地址连续的存储单 元来依次存储串中的字符序列,但串的存储空间是 在程序运行时根据串的实际长度动态分配的。
实现方法:系统提供一个空间足够大且地址连续的存储空间 ( 称为“堆” ) 供串使用。可使用 C 语言的动态存储分配函数 malloc() 和 free() 来管理。
串的堆式存储结构的类型定义
typedef struct{ char *ch; /* 若非空,按长度分配,否则为 NULL */ int length;} HString ;
◆ 块链存储方式:是一种链式存储结构表示。
串的链式存储结构和线性表的串的链式存储结构类似,采用单链表来存储串,结点的构成是:
data 域:存放字符, data 域可存放的字符个数
称为结点的大小;
next 域:存放指向下一结点的指针。
若每个结点仅存放一个字符,则结点的指针域就非常多,造成系统空间浪费,为节省存储空间,考虑串结构的特殊性,使每个结点存放若干个字符,这种
结构称为块链结构。如图 4-1 是块大小为 3 的串的块链式存储结构示意图。
结点的大小直接影响着串的处理效率.
串的存储密度:
显然,存储密度小时(例如结点大小为1),运算处理非常方便,但是存储占用量大.而存储密度大时,存储占用量相对较小,但如果在串处理过程中需进行过多的内外存交换时,会影响处理的总效率.
堆分配存储方式C语言实现
接口定义头文件
#define true 1#define false 0#define S_g_T 1#define S_e_T 0#define S_s_T -1/* 串的堆分配存储表示 */typedef struct h_string{ char *str; /* 串长度 */ int length;}h_string;/* 生成一个值等于str的字符串常量 * 生成成功返回true * 否则返回false*/int string_assign(h_string *S, char *ch);/* 复制串S并返回 */h_string string_copy(h_string S);/* 判断串S是否为空 * 若为空则返回true * 否则返回false*/int string_empty(h_string S);/* 比较串S和T * 若S>T返回S_g_T * 若S=T返回S_e_T * 若S<T返回S_s_T*/int string_compare(h_string S, h_string T);/* 返回自字符串的长度 */int string_length(h_string S);/* 将S清空 */void string_clear(h_string *S);/* S1和S2连接,并由T返回连接的新串 * 若连接成功,返回true * 否则返回false*/int string_contact(h_string *T, h_string S1, h_string S2);/* 用sub返回串S第pos个字符起长度为len的子串 * 成功返回true * 否则返回false*/int string_substring(h_string S, h_string *sub, int pos, int len);/* 若主串S中存在和串T值相等的字串, * 返回它在主串S中第pos个字符之后第一次出现的位置 * 否则返回-1*/int string_index(h_string S, h_string T, int pos);/* 用V替换主串S中出现所有的与T串值相等的不重叠的字串 */h_string string_replace(h_string *S, h_string V, h_string T);/* 在串S的第pos个字符之前插入串T */h_string string_strinsert(h_string S, h_string T, int pos);/* 从串S中删除第pos个字符起长度为len的字串 */h_string string_strdelete(h_string S, int pos, int len);/* 销毁串S */void string_destroy(h_string *S);/* 遍历打印字符 */void string_traverse(h_string S);
接口实现文件
#include<stdio.h>#include<stdlib.h>#include"string.h"int string_assign(h_string *S, char *ch){ /* 释放S的原有空间 */ if(S -> str) free(S -> str); /* 求串ch的长度 */ int count = 0; char *c; for(count = 0, c = ch; *c; count++, c++); printf("count = %d\n", count); /* 若*ch为空 */ if(!count) { S -> length = 0; S -> str = NULL; return true; } else { /* 申请内存空间 */ if(!(S -> str = (char *)malloc(sizeof(char)*count))) return false; S -> length = count; /* 赋值 */ int i = 0; for(i = 0; i < count; i++) { S -> str[i] = ch[i]; } return true; }}h_string string_copy(h_string S){ /* 创建新串 */ int len = S.length; h_string T; T.str = (char *)malloc(sizeof(char) * len); T.length = len; /* 复制 */ int i = 0; for (i = 0; i < len; i++) { T.str[i] = S.str[i]; } return T;}int string_empty(h_string S){ if(S.length == 0) return false; else return true;}int string_length(h_string S){ return S.length;}int string_compare(h_string S, h_string T){ /* 相同索引号从小到大的字符比较 * 相同则继续比较,直至最后一个字符 * 否则直接返回两字符的差值 */ int i = 0; for (i = 0;i < S.length && i < T.length; i++) { int value = S.str[i] - T.str[i]; if(value > 0) return 1; if(value < 0) return -1; } /* 若两个字符串前面的字符都一致 * 则比较长度 * 长度一样说明相等 * 长度短的字符串小 */ int value = S.length - T.length; if(value == 0) return 0; if(value > 0) return 1; if(value < 0) return -1;}void string_clear(h_string *S){ if(S -> str) { free(S -> str); S -> str = NULL; } S -> length = 0;}int string_contact(h_string *T, h_string S1, h_string S2){ /* 释放旧字符串(可直接调用string_empty()函数) */ if(T -> str) { free(T -> str); T -> str = NULL; } /* 新字符串长度 */ T -> length = S1.length + S2.length; T -> str = (char *)malloc(sizeof(char)*(T -> length)); if(!T -> str) return false; /* 赋值 */ int i = 0; for(i = 0; i < T -> length; i++) { if(i >= S1.length) { T -> str[i] = S2.str[i - S1.length]; } else { T -> str[i] = S1.str[i]; } } return true;}int string_substring(h_string S, h_string *T, int pos, int len){ /* pos,len与S.length间的关系 * 1 <= pos <= S.length; * pos + len - 1 <= S.length * len >= 0 */ /* 判断子串起始索引号和长度是否满足要求 */ if(pos < 1 || pos > S.length || len > S.length + pos - 1 || len < 0) return false; /* 清空旧串 */ if(T -> str) free(T -> str); /* 空子串 */ if (!len) { T -> str = NULL; T -> length = 0; return false; } /* 申请内存空间 */ T -> str = (char *)malloc(sizeof(char) * len); T -> length = len; /* 申请内存空间失败 */ if(!(T -> str)) return false; /* 赋值 */ int i = 0; for (i = 0; i < len; i++) { T -> str[i] = S.str[pos - 1 + i]; } return true;}int string_index(h_string S, h_string T, int pos){ /* 若T为空串 */ if(!(T.length)) return -1; /* 比较 */ /* 串S的起始位置 */ int i = pos -1; /* 串T的起始位置 */ int j = 0; while(i < S.length && j < T.length) { if(S.str[i] == T.str[j]) { i += 1; j += 1; } else { i = i -j + 1; j = 0; } } if (j >= T.length) return (i - T.length); return -1;}h_string string_replace(h_string *S, h_string V, h_string T){ /* 替换之后,下一轮替换的起始位置,初始化为1 */ int pos = 1; while(pos <= S -> length) { int index = string_index(*S, T, pos); /* S中存在与T串值相等的子串 */ if (index >= 0) { /* V.length = T.length */ if (V.length == T.length) { int i = 0; for (i = 0; i < V.length; i++) { S -> str[index + i] = V.str[i]; } pos = index + V.length; continue; } /* V.length > T.length */ if (V.length > T.length) { /* 复制字符串S,保存在临时字符串temp中 */ h_string temp = string_copy(*S); /* 增加申请内存 */ S -> str = (char *)malloc(sizeof(char) * S -> length + V.length - T.length); S -> length = S -> length + V.length - T.length; int i = 0; int j = 0; for (i = 0; i < index; i++) { S -> str[i] = temp.str[i]; } for (i = 0; i < V.length; i++) { S -> str[index + i] = V.str[i]; } for(i = index + V.length, j = index + T.length; j < temp.length; i++, j++) { S -> str[i] = temp.str[j]; printf("temp.length =%d j=%d\n", temp.length, j); } pos = index + V.length; printf("部分\n"); string_traverse(*S); continue; } /* V.length < T.length */ if(V.length < T.length) { /* 复制字符串S,保存在临时字符串temp中 */ h_string temp = string_copy(*S); /* 释放旧字符串 */ free(S -> str); S -> str = NULL; /* 新申请内存 */ int len = temp.length + V.length - T.length; S -> str = (char *)malloc(sizeof(char) * len); S -> length = len; int i = 0; int j = 0; for (i = 0; i < index; i++) { S -> str[i] = temp.str[i]; } for (i = 0; i < V.length; i++) { S -> str[index + i] = V.str[i]; } for(i = index + V.length, j = index + T.length; j < temp.length; i++, j++) { S -> str[i] = temp.str[j]; } pos = index + V.length; continue; } } else return *S; }}h_string string_strinsert(h_string S, h_string T, int pos){ /* 插入字符串为空 */ if(!T.length) return S; /* 存储字符串S的临时字符串 */ h_string temp = S; /* 增加申请内存 */ int len = S.length + T.length; S.length = len; S.str = (char *)malloc(sizeof(char) * len); /* 插入字符串 */ int i = 0; int j = 0; for (i = 0; i < pos - 1; i++) { S.str[i] = temp.str[i]; } for (i = 0; i < T.length; i++) { S.str[pos - 1 + i] = T.str[i]; } for (i = pos -1 + T.length, j = pos - 1; j < temp.length; i++, j++) { S.str[i] = temp.str[j]; printf("S.str[%d]=%c j=%d\n", i, S.str[i], j); } return S;}h_string string_strdelete(h_string S, int pos, int len){ /* pos,len与S.length间的关系 * 1 <= pos <= S.length; * pos + len - 1 <= S.length * len > 0 */ /* 判断子串起始索引号和长度是否满足要求 */ if(pos < 1 || pos > S.length || len > S.length + pos - 1 || len <= 0) return S; /* S删除子串之后的长度 */ int length = S.length - len; if (!length) { free(S.str); S.str = NULL; S.length = 0; return S; } else { h_string temp; temp.str = (char *)malloc(sizeof(char) * length); temp.length = length; int i = 0; int j = 0; for (i = 0; i < pos - 1; i++) { temp.str[i] = S.str[i]; } for (i = pos - 1, j = pos -1 + len; j < S.length; i++, j++) { temp.str[i] = S.str[j]; } return temp; }}void string_destroy(h_string *S){ free(S -> str); S -> str = NULL; S -> length = 0;}void string_traverse(h_string S){ if(!(S.length)) printf("字符串为空\n"); else { int i = 0; for(i = 0; i < S.length; i++) { printf("%c",S.str[i]); } printf("\n"); }}
其中的int string_index()函数的采用的是暴力比较法,该算法最好情况的时间复杂度是O(n+m),最差情况时的时间复杂度为O(n*m),可以采用KMP算法改进,使得其时间复杂度为O(n+m),详细情况见下篇博文.
测试文件
int main(){ char *ch = "jiang"; h_string S; S.length = 7; S.str = (char *)malloc(sizeof(char) * S.length); /* 赋值 */ string_assign(&S, ch); string_traverse(S); /* 复制 */ h_string T = string_copy(S); string_traverse(T); /* 判空 */ int value = string_empty(S); printf("字符串判空=%d\n",value); /* 字符串比较 */ char *str = "linyijiang"; string_assign(&T, str); value = string_compare(S, T); printf("字符串比较=%d\n",value); /* 字符串长度 */ value = string_length(T); printf("字符串长度=%d\n", value); /* 清空字符串 */ //string_clear(&S); //printf("字符串清空:"); //string_traverse(S);\ /* 字符串连接 */ h_string ST ; ST.str = NULL; string_contact(&ST, S, T); string_traverse(ST); /* 字串位置 */ string_traverse(T); string_traverse(S); value = string_index(T, S, 1); printf("index=%d\n", value); /* 返回长度为len的字符串 */ printf("返回长度为len的字符串\n"); string_traverse(T); string_traverse(S); value = string_substring(T, &S, 2, 9); string_traverse(S); /* 替换 */ //string_traverse(T); //h_string V; //V.str = "brother"; //V.length = 7; //S.str = "i"; //S.length = 1; //S = string_replace(&T, V, S); //string_traverse(S); /* 插入字符串 */ //printf("插入字符串\n"); //string_traverse(T); //S = string_strinsert(T, V, 2); //string_traverse(S); /* 删除 */ //printf("删除\n"); //string_traverse(T); //S = string_strdelete(T, 2, 6); //string_traverse(S);}
运行结果
- c语言实现字符串
- 字符串C语言实现
- 字符串倒序c语言实现
- c语言实现字符串逆序
- C语言实现字符串替换
- C语言实现字符串倒序
- c语言实现字符串分割
- c语言实现字符串分割
- C语言实现字符串反转
- C语言实现字符串替换
- C语言实现字符串函数
- 【C语言】截取字符串实现
- C语言实现翻转字符串
- 截取字符串 --C语言实现
- C语言实现字符串切片
- C语言实现字符串中查找字符串
- 【C语言】C语言字符串函数实现(一)
- 【C语言】C语言字符串函数实现(二)
- [Codeforces #368 (Div. 2) Pythagorean Triples] 数学:勾股数
- 说说平衡二叉树
- Thinking in Java__对象入门
- 文件下载,获取流
- LINUX 日志级别(LOGLEVEL)详解
- c语言实现字符串
- JMeter(一) -基础入门
- 服务端给的自定义URL跳转对应控制器
- spring-mvc之ioc容器
- Hello itsCoder!
- PAT Basic
- java小总结
- Python学习笔记(一)
- PAT Basic 1034 有理数四则运算(20)