串
串类型的定义
区分空串和空格串(空白串):空串字符长度为0,空白串是由一个或多个空格组成的串。
串的基本操作
- 求串的长度strlen()
- 复制串到另一个串中strcpy()
- 将串s1和s2连接成新串strcat()
- 比较两个字符串s1和s2strcmp()
- 在字符串中查找子串的位置strstr()【见上机作业】
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int luo_strlen(char* string);
void luo_strcpy(char* str1, char** str2);
char* luo_strcat(char* str1, char* str2);
int luo_strcmp(char* str1, char* str2);
int main()
{
char* string = "Hello";
char* str2, * str3 = NULL;
char* str4 = "abcde";
char* str5 = "abcdf";
int result = 0;
printf("%d\n", luo_strlen(string));
luo_strcpy(string, &str2);
printf("%s\n", str2);
str3 = luo_strcat(string, str2);
printf("%s\n", str3);
result = luo_strcmp(str4, str5);
printf("%d", result);
free(str2);
free(str3);
return 0;
}
int luo_strlen(char* string)
{
int length=0;
while (string[length] != '\0')
{
length++;
}
return length;
}
void luo_strcpy(char* str1, char** str2)
{
int i = 0;
*str2 = (char*)malloc((luo_strlen(str1) + 1) * sizeof(char));
while (str1[i] != '\0')
{
(*str2)[i] = str1[i];
i++;
}
(*str2)[i] = '\0';
}
char* luo_strcat(char* str1, char* str2)
{
int length = luo_strlen(str1) + luo_strlen(str2) + 1;
char* str3 = (char*)malloc(length * sizeof(char));
int i = 0, j = 0;
while (str1[i] != '\0')
{
str3[i] = str1[i];
i++;
}
while (str2[j] != '\0')
{
str3[i + j] = str2[j];
j++;
}
str3[i+j] = '\0';
return str3;
}
int luo_strcmp(char* str1, char* str2)
{
int i;
int result = 0;
for (i = 0; i < luo_strlen(str1) && i < luo_strlen(str2); i++)
{
if (str1[i] > str2[i])
{
result = 1;
break;
}
if(str1[i] < str2[i])
{
result = -1;
break;
}
}
return result;
}
串的表示
1、串的定长顺序存储表示
类似于线性表的顺序存储结构,用一组地址连续的存储单元存储串值得字符序列。在串的定长顺序存储结构中,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。
2、串的堆分配存储表示
仍然以一组地址连续的存储单元存放串值字符序列。但它们的存储空间是在程序执行过程中动态分配而得,利用malloc()和free()函数
3、串的块链存储表示
#define CHUNKSIZE 10//用户自定义块大小
typedef struct Chunk
{
char ch[CHUNKSIZE];
struct Chunk* next;
}Chunk;
typedef struct
{
Chunk* head, * tail;//串的头指针和尾指针
int curlen;//串当前的长度
}LString;
第六周上机作业
实现基于链表结构的字符串匹配算法
串的模式匹配算法:
1、BF算法(暴力匹配法),时间复杂度
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct _strLink
{
char ch;
struct _strLink* next;
}strLink;
strLink* SaveLink(char* filename);
int BF_match(strLink* head, char subStr[]);
int main()
{
//1、读取文件中的字符,存入串中
char* filename = "D:\\Cfiles\\DSweek6\\strLink.txt";
strLink* head = NULL;
head = SaveLink(filename);
//2、输入要查找的子串
char subStr[10];
printf("please input a subStr:");
scanf("%9s", subStr);
//3、BF算法查询子串,返回子串所在的位置
int position = BF_match(head, subStr);
if (position != 0)
{
printf("%s在第%d个位置\n", subStr, position);
}
else
{
printf("子串没有找到\n");
}
//4、释放链表内存
strLink* current = head;
while (current != NULL)
{
strLink* temp = current;
current = current->next;
free(temp);
}
return 0;
}
strLink* SaveLink(char* filename)
{
FILE* fp = fopen(filename, "r");
if (fp == NULL)
{
printf("打开文件错误");
return NULL;
}
strLink* head = NULL;
strLink* current = NULL;
char ch;
while (fscanf(fp, "%c", &ch) == 1)
{
strLink* link = (strLink*)malloc(sizeof(strLink));
link->ch = ch;
link->next = NULL;
if (head == NULL)
{
head = link;
current = link;
}
else
{
current->next = link;
current=current->next;
}
}
fclose(fp);
return head;
}
int BF_match(strLink* head, char subStr[])
{
int length = strlen(subStr);
int i;
int index = 0;
strLink* current = head;
while (current != NULL)
{
int flag = 1;
strLink* back = current;
for (i = 0; i < length && back!= NULL; i++)
{
if (back->ch == subStr[i])
{
back = back->next;
}
else
{
flag = 0;
break;
}
}
if (flag)
{
return index;
}
current = current->next;
index++;
}
return 0;
}
2、KMP算法,时间复杂度
在BF算法程序的基础上,只需要对KMP_match函数进行修改,其他不变。
思路:
1、求子串的next数组
2、匹配串和子串
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct _strLink
{
char ch;
struct _strLink* next;
}strLink;
strLink* SaveLink(char* filename);
int KMP_match(strLink* head, char subStr[]);
int main()
{
//1、读取文件中的字符,存入串中
char* filename = "D:\\Cfiles\\DSweek6\\strLink.txt";
strLink* head = NULL;
head = SaveLink(filename);
//2、输入要查找的子串
char subStr[10];
printf("please input a subStr:");
scanf("%9s", subStr);
//3、KMP算法查询子串,返回子串所在的位置
int position = KMP_match(head, subStr);
if (position != 0)
{
printf("%s在第%d个位置\n", subStr, position);
}
else
{
printf("子串没有找到\n");
}
//4、释放链表内存
strLink* current = head;
while (current != NULL)
{
strLink* temp = current;
current = current->next;
free(temp);
}
return 0;
}
strLink* SaveLink(char* filename)
{
FILE* fp = fopen(filename, "r");
if (fp == NULL)
{
printf("打开文件错误");
return NULL;
}
strLink* head = NULL;
strLink* current = NULL;
char ch;
while (fscanf(fp, "%c", &ch) == 1)
{
strLink* link = (strLink*)malloc(sizeof(strLink));
link->ch = ch;
link->next = NULL;
if (head == NULL)
{
head = link;
current = link;
}
else
{
current->next = link;
current = current->next;
}
}
fclose(fp);
return head;
}
int KMP_match(strLink* head, char subStr[])
{
//1、求subStr的next数组
int length = strlen(subStr);
int next[10];
next[0] = 0;
for (int j = 1; j < length; j++)
{
int index = next[j - 1];
if (subStr[j] == subStr[index])
{
next[j] = next[j - 1] + 1;
}
else
{
while (index > 0 && subStr[j] != subStr[index])
{
index = next[index - 1];
}
if (subStr[j] == subStr[index])
{
index++;
}
next[j] = index;
}
}
for(int k=0;k<length;k++)
{
printf("%d ",next[k]);
}
//2、与串进行匹配
strLink* current = head;
int index = 0;
int k = 0;
while (current != NULL)
{
if (current->ch == subStr[k])
{
current = current->next;
index++;
k++;
}
else
{
if (k == 0)
{
current = current->next;
index++;
}
else
{
k = next[k - 1];
}
}
if (k == length)
{
return index - length;
}
}
return 0;
}