描述
本次讲的是动态数组构成的字符串的基本操作的实现,线性表离不开增删查改,以下是将要实现的功能。
具体实现的是串的六个功能:
1. 初始化
2. 插入字符串
3. 删除某个子串
4. 取子串
5. 消除字符串
6. 输出字符串
0.需要的头文件和定义的类型和结构体变量的实现
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef char* Char; //定义字符指针方便打代码---个人习惯。。。
typedef struct string {
Char str; //定义字符指针
int length; //当前长度
int maxLength; //最大长度
}string, *String;
1.初始化
String createString(Char s, int maxLength) {
if (strlen(s) >= maxLength) {
printf("最大长度不可以比当前长度短");
return NULL;
}
String newStr = (String)malloc(sizeof(string));
newStr->length = strlen(s);
newStr->maxLength = maxLength;
newStr->str = (Char)malloc(sizeof(char) * maxLength);
for (int i = 0; i < strlen(s); i++) {
newStr->str[i] = s[i];
}
newStr->str[newStr->length] = '\0';
return newStr;
}
2. 插入字符串
int Insert(String Str, int index, string insert_Str) {
int i;
if (index < 0 ) {
printf("Insert 函数的参数错误");
return 0;
}
if (Str->maxLength <= Str->length + insert_Str.length) {
Str->maxLength = Str->length + insert_Str.length +1; //保证最后一位是\0
realloc(Str->str, sizeof(char) * Str->maxLength);
}
for (i = Str->length - 1; i >= index; i--){
Str->str[i + insert_Str.length] = Str->str[i]; //正序操作可能重复替换同一个而把后面的替换了,所以要逆序
} //就和排队倒退一个道理,最后一个人退了前面的才可以继续后退
for (i = 0; i < insert_Str.length; i++) {
Str->str[i + index] = insert_Str.str[i];
}
Str->length += insert_Str.length;
Str->str[Str->length] = '\0';
return 1;
}
3. 删除某个子串
int Delete(String Str ,int index, int len) {
int i;
if (index <0 || len <= 0 || index + len > Str->length) {
printf("Detele 函数的参数错误");
return 0;
}
for (i = index; i < index + len; i++) {
Str->str[i] = Str->str[i + len];
}
Str->length -= len;
Str->str[Str->length] = '\0'; //这步很重要
return 1;
}
4. 取子串
String subString(String Str,int index, int len) {
int i;
String sonStr;
if (index <0 || len <= 0 || index + len > Str->length){
printf("subString 函数的参数有误");
return NULL;
}
Char sonstr = (Char)malloc((len + 1) * sizeof(char));
for (int i = 0; i < len; i++) {
sonstr[i] = Str->str[index + i];
}
sonstr[len] = '\0';
sonStr = createString(sonstr, len + 1);
return sonStr;
}
5. 消除字符串
void freeStr(String Str) {
free(Str->str);
free(Str);
}
6. 输出字符串
void tostring(String Str) {
printf("字符串的最大长度是:%d\n", Str->maxLength);
printf("字符串的当前长度是:%d\n", Str->length);
printf("字符串为 %s\n", Str->str);
}
实现效果
实现效果全部代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef char* Char;
typedef struct string {
Char str;
int length;
int maxLength;
}string, *String;
String createString(Char s, int maxLength) { //初始化函数
if (strlen(s) >= maxLength) {
printf("最大长度不可以比当前长度短");
return NULL;
}
String newStr = (String)malloc(sizeof(string));
newStr->length = strlen(s);
newStr->maxLength = maxLength;
newStr->str = (Char)malloc(sizeof(char) * maxLength);
for (int i = 0; i < strlen(s); i++) {
newStr->str[i] = s[i];
}
newStr->str[newStr->length] = '\0';
return newStr;
}
void tostring(String Str) { //输出函数
printf("字符串的最大长度是:%d\n", Str->maxLength);
printf("字符串的当前长度是:%d\n", Str->length);
printf("字符串为 %s\n", Str->str);
}
int Insert(String Str, int index, string insert_Str) { //插入函数
int i;
if (index < 0) {
printf("Insert 函数的参数错误");
return 0;
}
if (Str->maxLength <= Str->length + insert_Str.length) {
Str->maxLength = Str->length + insert_Str.length +1;
realloc(Str->str, sizeof(char) * Str->maxLength);
}
for (i = Str->length - 1; i >= index; i--){
Str->str[i + insert_Str.length] = Str->str[i]; //正序操作可能重复替换同一个而把后面的替换了,所以要逆序
} //就和排队倒退一个道理,最后一个人退了前面的才可以继续后退
for (i = 0; i < insert_Str.length; i++) {
Str->str[i + index] = insert_Str.str[i];
}
Str->length += insert_Str.length;
Str->str[Str->length] = '\0';
return 1;
}
int Delete(String Str ,int index, int len) { //删除函数
int i;
if (index <0 || len <= 0 || index + len > Str->length) {
printf("Detele 函数的参数错误");
return 0;
}
for (i = index; i < index + len; i++) {
Str->str[i] = Str->str[i + len];
}
Str->length -= len;
Str->str[Str->length] = '\0';
return 1;
}
String subString(String Str,int index, int len) { //取子串函数
int i;
String sonStr;
if (index <0 || len <= 0 || index + len > Str->length){
printf("subString 函数的参数有误");
return NULL;
}
Char sonstr = (Char)malloc((len + 1) * sizeof(char));
for (int i = 0; i < len; i++) {
sonstr[i] = Str->str[index + i];
}
sonstr[len] = '\0';
sonStr = createString(sonstr, len + 1);
return sonStr;
}
void freeStr(String Str) { //消除函数
free(Str->str);
free(Str);
}
void main() {
String sonStr;
String Str = createString("123", 5);
String insertStr = createString("45", 3);
tostring(Str);
printf("\n在下标1处插入字符串 45 :\n");
if (Insert(Str, 1, *insertStr))tostring(Str);
printf("\n在下标1处删除字符串长度为2 :\n");
if (Delete(Str, 1, 2)) tostring(Str);
printf("\n截取从下标1处开始字符串长度为2的子串 :\n");
sonStr = subString(Str, 1, 2);
tostring(sonStr);
printf("消除字符串 :");
freeStr(Str);
freeStr(sonStr);
printf("成功消除");
}
串我以前都以为是用链表实现的,但是因为用链表会造成空间浪费
(指针占用空间)sizeof(unsigned long int) + sizeof(char) = sizeof(char) * 5
会造成80%的空间的浪费,所以用动态数组。这种做法真是开了眼界。
实现主要用的是 realloc 函数。
晚一点会更新模式匹配的两种算法,主讲KMP。可能是明天,也可能是后天,这两天课比较多。
如果这篇文章有什么不足,可以评论,我一定会及时更新。