1、 C语言字符串的实现以及基本功能
输入数据的时候按我这样输入:不然的话会把换行读进去
#include<stdio.h>
#include <mm_malloc.h>
#include <conio.h>
#define MAXSIZE 50
typedef struct String {
char elem[MAXSIZE];
int length;
} String, *LinearString;
int main() {
int getArrayLength(char array[]);
LinearString InitLinearString();
int StrInsert(LinearString s, int pos, LinearString t);
void InsertData(LinearString s);
void InsertData(LinearString s);
void display(LinearString s);
int StrDelete(LinearString s, int pos, int length);
int StrCompare(LinearString s, LinearString t);
int StrIndex(LinearString s, int pos, LinearString t);
int StrIndexKMP(LinearString s, LinearString t);
LinearString s = InitLinearString();
printf("给s点数据:");
InsertData(s);
display(s);
printf("\n");
printf("长度%d\n", s->length);
printf("给t点数据:\n");
LinearString t = InitLinearString();
InsertData(t);
display(t);
printf("\n");
printf("长度%d\n", t->length);
printf("判断t在s中的位置在哪里:%d",StrIndex(s,0,t));
printf("判断t在s中的位置在哪里KMP:%d",StrIndexKMP(s,t));
printf("比较字符串s和字符窜t:%d\n", StrCompare(s, t));
StrInsert(s, 4, t);
display(s);
printf("长度%d\n", s->length);
StrDelete(s, 3, 3);
display(s);
}
//初始化字符串
LinearString InitLinearString() {
LinearString s = (String *) malloc(sizeof(String));
s->length = 0;
return s;
}
//插入数据
void InsertData(LinearString s) {
int flag = 1, i = 0;
char ch;
while (flag) {
ch = getch();
if (ch != '$') {
s->elem[i] = ch;
s->length++;
i++;
} else {
flag = 0;
}
}
}
//遍历数据
void display(LinearString s) {
for (int i = 0; i < s->length; ++i) {
printf("%c", s->elem[i]);
}
printf("\n");
}
//得到数组长度
int getArrayLength(char array[]) {
int i = -1;
int length;
do {
i++;
} while (array[i] != '\0');
return length = i;
}
//字符串插入函数 以数组的下标为基准
/**
* 插入的时候会将字符串分为三部分: LA LB(LA和LB是 字符串S被拆开成了两部分) LC(LC是插入的那个字符串)
* 有三种情况:
* 1、如果s.length+t.length <= MAXSIZE, 那么意味着s中的数组容量够大,那么这个时候只需要将LB部分往后面挪,LC插入进来就可以啦
* 2、如何s.length+t.length <= MAXSIZE不成立,并且pos +t.length <= MAXSIZE,那么这意味着,LB会失去一部分
* 3、如何s.length+t.length <= MAXSIZE不成立,并且pos +t.length > MAXSIZE,那么这意味着,LB会全部失去,而且LC也会失去一些
*
*/
int StrInsert(LinearString s, int pos, LinearString t) {
if (pos < 0 || pos > s->length) {
printf("插入的位置不对!");
return -1;
}
if (s->length + t->length <= MAXSIZE) {
for (int i = s->length + t->length - 1; i >= pos + t->length; i--) {
s->elem[i] = s->elem[i - t->length]; // 这一步其实就是将第三部分往后面挪
}
for (int i = 0; i < t->length; i++) {
s->elem[pos + i] = t->elem[i];
}
s->length = s->length + t->length;
} else if ((pos + t->length) <= MAXSIZE) {
for (int i = MAXSIZE - 1; i > t->length + pos - 1; i--) {
s->elem[i] = s->elem[i - t->length];
}
for (int i = 0; i < t->length; i++) {
s->elem[pos + i] = t->elem[i];
}
s->length = MAXSIZE;
} else {
for (int i = 0; i < MAXSIZE - pos; i++) {
s->elem[pos + i] = t->elem[i];
}
s->length = MAXSIZE;
}
return 1;
}
//删除字符串
int StrDelete(LinearString s, int pos, int length) {
if (pos < 0 || pos > s->length - length) {
printf("删除不合理!");
return -1;
}
for (int i = pos + length; i < s->length; ++i) {
s->elem[i - length] = s->elem[i];
}
s->length = s->length - length;
return 1;
}
//串的比较 比较的原理很简单就是一个字符一个字符比较,如果相等就返回0,同时也意味着他们一样长,如果不相等就返回第一次不同的字符之间的差值
int StrCompare(LinearString s, LinearString t) {
for (int i = 0; i < s->length && i < t->length; ++i) {
if (s->elem[i] != t->elem[i]) {
return s->elem[i] - t->elem[i];
}
}
return (s->length - t->length);
}
//串的简单匹配模式 暴力破解法 pos的作用可以使匹配模式更加灵活,可以找主串中任意位置后面模式串第一次出现的位置,不必一定要从第一个位置开始啦;
int StrIndex(LinearString s, int pos, LinearString t) {
int i, j = 0, start;
start = pos;
i = start;
if (t->length == 0) return (0); // 模式串为空串的时候,是任意串的匹配串
while (i < s->length && j < t->length) {
if (s->elem[i] == t->elem[j]) {
i++;
j++;
} else {
// 用start记录i应该回到的位置
start++;
i = start;
j = 0;
}
}
if (j >= t->length){
return start;
}else{
return -1;// 这一步意味着start已经到主串的末尾了,说明没有匹配成功
}
}
//KMP算法解决串的匹配;
int StrIndexKMP(LinearString s,LinearString t){
void getNext(LinearString t,int next[]);
int next[t->length];
int i = 0,j = 0;
getNext(t,next);
while (i < s->length && j < t->length){
if ( j == -1 || s->elem[i] == t->elem[j]){
i++;
j++;
}else{
j = next[j];
}
}
if ( j >= t->length){
return i - t->length;
}else{
return -1;
}
}
void getNext(LinearString t,int next[]){
int j,k; // j始终指向t中的元素,并且从头一直移动到尾,不发生重返的过程,k代表着最大公共前缀的长度
//我们约定第一个元素的最长公共前缀长度为-1,其实没有公共前缀的元素约定为0;
next[0] = -1;
j = 0;
k = -1;
/**
* 实现next的原理就是通过递推的方法,知道next[j],从而起的next[j+1]
* 并且如果 Pk = Pj,那么有next[j+1] = k+1;
* 如果k = -1,那就意味着next[j] = 1;就是没有公共前缀
*/
while( j < t->length-1){
// k如果等于 -1那么就代表着已经回溯到了next[0],那就意味着,next[j+1]的最长公共前缀一定是0的;
// 如果是t->elem[k] == t->elem[j],那么及时满足这个条件Pk = Pj,那么有next[j+1] = k+1;
if ( k == -1 || t->elem[k] == t->elem[j]){
j++;
k++;
next[j] = k;
}else{
k = next[k];
}
}
}