c语言中字符串处理的库函数还是比较全的,c++里的string类就更不用说了。有些处理函数虽然已封装为库函数,直接调用即可,但是正在学习数据结构,还是想敲些代码,以便总结+巩固。
首先,总结一下常用的c语言中字符串处理标准库函数: (仅仅是我想复习一下。。。)
// #include<string.h>
char* srtcpy(char* dst,const char* src); //从src地址开始且含有'\0'结束符的字符串(c风格字符串)复制到以dst开始的地址空间. 并返回char型指针,与dst指向同 一内容.
char* strcat(char* str1,char* str2); // 把str2所指字符串添加到str1结尾处(覆盖str1结尾处的'\0')并添加'\0'.
int strcmp(char* str1,char* str2); //比较字符串大小,str1>str2,返回正数,str1<str2,返回负数,str1==str2,返回0.
unsigned int strlen(char* str); // 返回字符串长度(以第一个字符串结束符'\0'为终止).
char* strchr(const char* str,char c); // 查找字符串中首次出现字符c的位置,成功则返回要查找字符第一次出现的位置,失败返回NULL.
char* strrchr(const char* str,char c);// 查找字符c在字符串str中末次出现的位置,返回从字符串中的这个位置起,一直到字符串结束的所有字符. 如果未能找到指定字符,那么返回NULL.
char* strdup(char* str); // 将串拷贝到新建的位置处,在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏.
int stricmp(char* str1,char* str2); // 比较字符串大小,对大小写不敏感.
int strnicmp(char* str1,char* str2,unsigned int n); // 比较字符串str1与str2的前n个字符,不区分大小写.
char* strnset(char* str,char c,unsigned int n); // 将一个字符串中的前n个字符都设为指定字符c.
char* strtok(char* str,const char* delim); // 分解字符串为一组字符串,s为要分解的字符串,delim为分隔符字符串.str为要分解的字符串,delim为分隔符字符串.首次调用时s指向要分解的字符串,之后再次调用要把s设成NULL.
char* strrev(char* str); // 串倒转.
char* strstr(char* str1,const char* str2); // 确定str2在str1的第一次出现的位置,返回子串在str1首位置的地址.如果str2不是str1的子串,返回NULL
char* strpbrk(const char* str1,const char* str2); // 依次检验字符串str1中的字符,当被检验字符在字符串str2也包含时,则停止检验.并返回该字符位置,空字符null不包括在内.
size_t strcspn(const char* str1,const char* str2); // 顺序在字符串str1中搜寻与str2中第一个的相同字符,包括结束符NULL,返回这个字符在str1中第一次出现的位置,(返回在字符串str1中的下标值,即在str1中出现而str2中没有出现的子串的长度)
串模式匹配: 实现函数: unsigned int Index(const char* S,const char* T,unsigned int pos);
主函数在此:
void main()
{
char* S="BBC ABCDAB ABCDABCDABDE";
char* T="ABCDABD";
printf("串T在串S中首次出现的位置是:%d\n",Index(S,T,1)); //位置值从1开始,pos>=1 && pos<=strlen(S)
}
一、依赖比较、求串长、求子串函数的实现:
char* SubString(const char* str,unsigned int pos,unsigned int len)
{
if(str==NULL)
{
printf("Wrong point!\n");
return 0;
}
if(pos>0 && len>0)
{
unsigned int i=pos,j=0;
char temp[20]={0};
while(i<=pos+len-1)
{
temp[j]=str[i-1];
++i;++j;
}
return temp;
}
return NULL;
}
unsigned int Index(const char* S,const char* T,unsigned int pos)
{
if(S==NULL || T==NULL)
{
printf("Wrong point!\n");
return 0;
}
if(pos>0)
{
unsigned int n=strlen(S);
unsigned int m=strlen(T);
unsigned int i=pos;
while(i<=n-m+1)
{
char* temp=SubString(S,i,m);
if(strcmp(temp,T))
++i;
else
return i;
}
}
return 0;
}
执行结果:
二、不依赖其他串操作的实现:
unsigned int Index(const char* S,const char* T,unsigned int pos)
{
if(S==NULL || T==NULL)
{
printf("Wrong point!\n");
return 0;
}
if(pos>0)
{
unsigned int n=strlen(S);
unsigned int m=strlen(T);
unsigned int i=pos,j=1;
while(i<=n && j<=m)
{
if(S[i-1]==T[j-1])
{
++i;++j;
}
else
{
i=i-(j-1)+1;
j=1;
}
}
if(j>m)
return i-m;
else
return 0;
}
return 0;
}
执行结果同上.
三、采用上篇转载博文中介绍的改进算法:KMP算法
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void Min(string t,vector<int>& key)
{
string temp1; //子串前缀
string temp2; //子串后缀
int i=2,j=1,k,len=t.length();
//vector<int> key;
while(i<len) //长度为i的子串
{
//if(i==1)
//key[j]=0;
k=1;
while(k<i) //长度为i的子串有i-1个前/后缀,同级相比较
{
temp1=t.substr(0,k);
temp2=t.substr(i-k,k);
if(temp1==temp2)
key[j]=temp1.length();
++k;
}
++j;
++i;
}
}
int Index(string s,string t,int pos)
{
int i=pos-1,slen=s.length(),tlen=t.length();
vector<int> key;
for(int a=0;a<tlen;++a)
key.push_back(0);
Min(t,key);
int j=0;
int k=0;
int ppos=0;
while(1)
{
if(s[j]!=t[k])
{
if(k==0)
{
++j;
++ppos;
continue;
}
else
{
ppos+=k-key[k-1];
j=ppos;
k=0;
}
}
else if(s[j]==t[k])
{
if(k==tlen-1)
return ppos+1;
else
{
++k;
++j;
}
}
if(j==slen)
return -1;
}
}
void main()
{
string S("BBC ABCDAB ABCDABCDABDE");
string T("ABCDABD");
int v=Index(S,T,1);
if(v>=0)
cout<<"串T在串S中首次出现的位置是:"<<Index(S,T,1)<<endl;
else
cout<<"串T不是串S的子串."<<endl;
}
执行结果: