字符串
字符串定义及常用函数
- 用数组
char str[]="hello"
数组名是const的指针,即常量指针,表明该指针(地址)不能被修改,即不能再指向别处 。但该指针(即数组变量)指向的字符串可以通过该数组修改 - 用指针
char *p="hello"
p作为一个指针,初始化为指向一个字符串常量,该字符串常量放在内存特殊的地方,不能通过该指针p对其指向的字符串进行修改
char *str1="hello";
*str1='B'; //操作错误,不能通过指针对该字符串进行写
char str2[10]="hello";
str2[0]='B'; //√ 数组定义的字符串常量作为本地变量空间,可被修改
- 字符串变量定义及输入输出
char str[N]; //字符串变量定义
gets(str); //输入
scanf("%s",str); //输入
puts(str); //输出
printf("%s",str); //输出
- 字符串操作常用库函数
//字符串长度计算
size_t strlen(const char* str);
//字符串赋值(复制)
//将参数src字符串拷贝至参数dst所指的地址
//返回参数dst的字符串起始地址
strcpy(const char *dst,const *char src);
// 字符串拼接 strcat
//返回dest字符串起始地址
char* strcat(char* dest,const char* src)
//字符串比较
//若参数s1和s2字符串相同则返回0,s1若大于s2则返回大于0的值,s1若小于s2则返回小于0的值
int strcmp (const char* str1,const char* str2)
//检索子串在字符串中首次出现的位置
//返回字符串str中第一次出现子串substr的地址;如果没有检索到子串,则返回NULL
char* strstr(const char* str,const char* substr)
//查找字符串中第一次出现字符c的位置
//返回首次出现c的位置的指针,如果s中不存在c则返回NULL
char* strchr(const char* str,char c)
//用于将字符串转换为双精度浮点数(double)
//助记atof:ascii to floating point numbers
//同理还有函数atoi 将字符串转为整形数字
double atof (const char* str);
//将整型的数字变量转换为字符数组变量
//参数radix为转换进制数
char *itoa (int value, char *str, int radix)
字符串常见操作
查找字符串中的数字
核心思想:遍历字符串,把遇到的数字字符均存起来,直到当前字符不是数字字符但前一个字符是数字字符的时候,开始清算一次将之前存起来的数字字符转为double型数字,再接着遍历之后的字符
- 用库函数
atof
版本
/*
功能:将字符串s中的数字存放到数组a中
参数:字符串s 字符串中的数字的存放数组a
返回值:字符串中数字的个数
*/
int find_val(char *s,float *a)
{
char *p;
char t[10]; //存放一个整数的每位数
int len=strlen(s); //计算字符的长度
int flag=0; //标记当前字符是否为0-9
int i=0;
int num=0; //整数的个数
for(p=s;p<=s+len;p++) //考虑到字符串最后是数字的情况,
//把最后的\0字符也当作非数字字符处理
{
if(*p>='0'&&*p<='9'||*p=='.') //若统计的是整数,则不用 ||*p=='.'
{
flag=1;
t[i++]=*p; //将数字字符统计起来
}
else if(flag==1) //如果当前字符非数字字符,且前一个字符为数字字符时,开始记录整数
{
flag=0; //flag清零,再开始找下一个数
t[i]='\0'; //方便用atof
i=0;
a[num]=atof(t);
num++; //算完一个数后,num++好让数组存下一个数
}
}
return num;
}
- 不用库函数
atof
版本,用for循环计算,只适合转整数
/*
功能:同上
参数:同上
返回值:同上
*/
int find_val(char *s,int *a)
{
char *p;
int t[255]; //存放一个整数的每位数
int len=strlen(s); //计算字符的长度
int flag=0; //标记当前字符是否为0-9
int i=0,j;
int num=0; //整数的个数
for(p=s;p<=s+len;p++) //把最后的\0字符也当作非数字字符处理
{
if(*p>='0'&&*p<='9')
{
flag=1;
t[i++]=*p-'0'; //归一化 把字符'0'~'9'装换为数字0~9
}
else if(flag==1) //如果当前字符非数字字符,且前一个字符为数字字符时,开始记录整数
{
a[num]=0;
for(j=0;j<i;j++)
a[num]=a[num]+t[j]*pow(10,i-1-j);
num++;
flag=0;
i=0;
}
}
return num;
}
字符串中对子串的操作(删除、替换、统计次数)
- 字符串中字串出现的次数统计
用了库函数strstr
较简单
/*
功能:统计字符串中某子串的出现次数
参数:字符串str1 子串str2
返回值:子串出现的次数
*/
int fun_check(char *str1,char *str2)
{
char *p=NULL;
int num=0;
int len2=strlen(str2); //子串的长度
p=strstr(str1,str2); //找完一次后p指向str1的str2的位置
while(p!=NULL)
{
num++;
p=strstr(p+len2,str2); //加len2 10101000101中出现101两次
// 加1 10101000101中出现101三次
}
return num;
}
不用库函数 较复杂 不推荐
int fun_check(int lena,int lenb,char a[],char b[])
{
int i,k,j,m=0; //m统计次数
char c[100];//中间字符串
for(i=0;a[i];i++)
{
//将a分成很多个长度为lenb的小串 放到c里面
k=i;
for(j=0;j<lenb;j++,k++)
c[j]=a[k];
c[j]='\0';
//判断a的子串c是否和b相同,若相同,则把m++
if(strcmp(b,c)==0)
m++;
}
return m;
}
- 字符串中子串的替换
void fun(char *str,char*substr1,char *substr2,int length1)
{
char *p=NULL;
p=strstr(str,substr1); //p指向str中sunstr1的位置,是指向,并不是新的字符串
while(p) //这儿的循环保证将str的所有子串均替换
{
char temp[N]; //中间变量
strcpy(temp,p+length1);//把子串1后面的东西拷贝到temp中
strcpy(p,substr2);
strcat(str,temp);
p=strstr(str,substr1); //再开始查找一次
}
}
- 字符串中子串的删除
没有用库函数,不推荐
void fun_delate(int lena,int lenb,char a[],char b[])
{
int i,k,j,m=0;
char c[100];//中间字符串
for(i=0;a[i];i++)
{
//将a分成很多个长度为lenb的小串 放到c里面
k=i;
for(j=0;j<lenb;j++,k++)
c[j]=a[k];
c[j]='\0';
//判断a的子串c是否和b相同,若相同,则把该串覆盖掉
//此时i还要减回去,因为新的a要从头开始
if(strcmp(b,c)==0)
{
strcpy(a+i,a+k);
i--;
}
}
}
- 小结
对子串的操作,本质上这几个函数基本相同,
函数框架都是如下,只有中间执行具体操作部分和判断不一样 子串替换 相对复杂一点
p=strstr(str1,str2); //找完一次后p指向str1的str2的位置
while(p!=NULL)
{
{
} //在此处执行相应的操作,删除或统计num++或替换
p=strstr(p+len2,str2); //判断也不完全一样
}
统计字符串中某类字符(如数字or小写字母)的数目,并排序
统计:遍历字符串,用数组元素++的形式保存下来,所以数组下标即对应了字符,用’字符‘-'a’归一化处理更方便。统计的思想比较重要,还可用与计算俩字符串的交集并集这种。
排序:考虑到还要保存数组对应的下标,故新定义一个数组存放原数组下标,数组成员为0,1,2,3,4…只要新数组和要排序的数组一起变换位置即相当于保留了原数组的下标(实际上该方法用了结构体数组的思想。故用结构体数组亦可,具体结构体数组的排序算法将在结构体部分实现学生成绩管理系统给出)
- 统计字符串中各小写字母的个数,并排序
int main()
{
int i,j;
int cnt[26]= {0}; //用来统计个数 初始化都为0 下标为对应字母
int text[26]; //用来存放排序后的字母 ,即下标初始化为0,1,2,3...
for(i=0;i<26;i++)
text[i]=i;
//输入及遍历统计
char str[200]; //存储字符串。
gets(str); //输入字符串。
for(i=0; str[i]!='\0'; i++) //遍历字符串。
if((str[i]>='a')&&(str[i]<='z')) //若是小写字母
cnt[str[i]-'a']++; //统计个数。 归一化后的字母 即a对应0
//排序及输出
sort(cnt,26,text);
for(j=0; j<26; j++) //遍历输出统计到的值
{
if(cnt[j]!=0)//如果出现过则打印值及出现次数
printf("%c:%d\n", text[j]+'a', cnt[j]);//输出结果。
}
return 0;
}
//排序算法
void sort(int* a, int length, int* b)
{
int i,j, t1, t;
//冒泡排序算法
for(j=0; j<length; j++)
for(i=0; i<length-1-j; i++)
if(a[i]<a[i+1]) { //让数组内元素和下标一起移动
t=a[i];
a[i]=a[i+1];
a[i+1]=t;
t1=b[i];
b[i]=b[i+1];
b[i+1]=t1;
}
}
- 统计字符串中各数字字符的个数,并排序
int main()
{
int i,j;
char str[N];
puts("输入一串数字");
gets(str);
int temp_num,temp_sort;
int num[10]={0};
int sort[10]={0,1,2,3,4,5,6,7,8,9};//顺序对应好
for(i=0;str[i]!='0';i++)
{
if(str[i]>='0'&&str[i]<='9')
num[str[i]-'0']++;//将数字字符归一化后,存在num数组中,下标为数字字符,对应成员为出现的次数
}
//冒泡排序 用俩数组保存好对应下标成员
for(i=0;i<N-1;i++)
for(j=0;j<N-i-1;j++)
if(num[j]>num[j+1])
{
temp_num=num[j+1];
num[j+1]=num[j];
num[j]=temp_num;
temp_sort=sort[j+1];
sort[j+1]=sort[j];
sort[j]=temp_sort;
}//排序后num【i】存的是数字sort【i】出现的频率,
puts("出现数字的频率为\n");
for(i=0;i<10;i++)
{
if(num[i]>0)
printf("数字%d出现了%d次\n",sort[i],num[i]);
}
}
删除字符串中指定字符
新建个字符数组temp[]
,将不删除的保存下来,再用strcpy
函数赋值给原字符串即完成删除
void clean_char(char *str,char dst)
{
int i,j=0;
char temp[N];
for(i=0;str[i]!='\0';i++)
{
if(str[i]!=dst)
{
temp[j++]=str[i];
}
}
temp[j]='\0';
strcpy(str,temp);
}
小结
确定一个字符串只需要指向该字符串的头指针即可,因为字符串末尾固定均为'0'
。对字符串的操作可以用指针也可以用数组方式,均一样。*(str+i)
与 str[i]
本质是相同的。