字符串使用
零、创建“字符串”
众所周知,C语言是没有字符串类型的,但还是有字符串常量的概念的。
字符串常量与指针:通过指针找空间
char s;*
声明了一个指向字符的指针变量s,它可以指向一个字符数组,也就是一个字符串。
char *s = "hello World";
他们存的首地址语言,但是他们自身的地址不同;若内容一样,则指向的空间也会是一样的
代更新: 常量字符串
字符数组
char arr[]="hello";
一、移除元素
我们通常在做题的时候,会遇到查看字符串里面是否有重复的字符元素的问题。我们C语言的字符串是利用数组开辟的。使用暴力的解答方式,一个一个的对比形成了O(n^2)的时间复杂度。
那么就不得不提及尺取法(双指针) == 的做法了。
我之前写尺取法(双指针)==的链接在此link
1.1)移除后的字符串
那么我们通过一道例题来实战一下:
题目编号 AT_test001_b
题目来源 AtCoder 【在洛谷做的】
地址:链接: link
题目描述:
给出一个字符串 a与破掉的按键b。请输出a除去b后的新字符串。
#include<stdio.h>
#include<string.h>
int main(){
char ch;
ch=getchar();
char arr[60];
scanf("%s",arr);
int low=0,fast=0;
for(fast=0;fast<strlen(arr);fast++){
if(ch!=arr[fast])
arr[low++]=arr[fast];
}
arr[low]='\0';
printf("%s\n",arr);
}
注意事项:
1)这个主要原因就是,开辟好的空间储存着一定量的元素,而且只有该地址覆盖,删除不得。
2)而且数组是遇见’\0’才算终止。
对比一下:
将13行的那个赋予‘\0’的注释掉的话,我们看到的就是结果是三个S。
取消注释:两个S
1.2)查看是否有重复字符
例题:
题目编号 AT_abc063_b
题目来源 AtCoder 【在洛谷做】
地址:链接: link
题目描述:给定一个字符串S,判断其中字符,如果全部不相同,输出yes,否则输出no。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int emm(const void* a,const void* b){
return (*(char*)a-*(char*)b);
}
int main(){
char arr[100];
int low=0,fast=0;
scanf("%s",arr);
int len=strlen(arr);
qsort(arr,len,sizeof(arr[0]),emm);
for(fast=0;fast<len;fast++){
if(arr[fast+1]!=arr[fast]){
low++;
}
}
if(low==len)printf("yes\n");
else printf("no\n");
}
1.3)特殊:
<1>连续出现的字符
链接: link
题目描述
给定一个字符串,在字符串中寻找第一个连续出现次数不低于 k 次的字符。
输入格式2 行。第 1 行是 k;第 2 行是仅包含大小写字母的字符串。
输出格式
字符串中第一个连续出现次数不低于 k 次的字符。如果没有符合条件的字符,输出 No。
#include<stdio.h>
#include<string.h>
int main(){
char arr[1005];
int k;
scanf("%d",&k);
scanf("%s",arr);
int len=strlen(arr);
int i,count=1;
for(i=1;i<=len;i++){
if(arr[i]==arr[i-1]){count++;
if(count>=k){
printf("%c",arr[i]);return 0;
}}else count=1;
}
printf("No");
}
<2>
链接: link
题目描述
在实际的开发工作中,对字符串的处理是最常见的编程任务。本题目即是要求程序对用户输入的串进行处理。具体规则如下:
把每个单词的首字母变为大写。
把数字与字母之间用下划线字符(_)分开,使得更清晰
把单词中间有多个空格的调整为 1 个空格。
输入描述
用户输入的串中只有小写字母,空格和数字,不含其它的字母或符号。每个单词间由 1 个或多个空格分隔。假设用户输入的串长度不超过 200 个字符。
输出描述
输出处理好的字符串。
输入输出样例示例
输入
you and me what cpp2005programcopy
输出
You And Me What Cpp_2005_program
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
char str[201];
gets(str);//遇到\n结束输入
if(str[0]>='a' && str[0]<='z') {
printf("%c",str[0]-32);//第一个字符是字母则大写
if(str[i+1]>='0' && str[i+1]<='9') printf("_");//后面有数字再输出一个_
}
else printf("%c",str[0]);//否则直接输出第一个字符
for(i = 1;i<strlen(str);i++){
if(str[i]>='a' && str[i]<='z')//判断是不是字母
{
if(str[i-1]>='0' && str[i-1]<='9') printf("_");//如果前面有数字先输出_
if(str[i-1]==' ') printf("%c",str[i]-32);//首字母大写
else printf("%c",str[i]);//否则小写
if(str[i+1]>='0' && str[i+1]<='9') printf("_");//如果后面有数字则再输出一个_
}
else if(str[i]==' ' && str[i-1]==' ')continue;//如果空格前面还是空格,不输出
else printf("%c",str[i]);//如果空格或者数字,直接输出
}
return 0;
}
1.4)注意事项:
本题的数据规模换不算太大,如果超过了10^5字符串长度的时候,就该考虑优化一定的时间复杂度了。这题我采取的是C语言自带的快速排序的库里面的函数。【这极大的区别于那个冒泡排序】
本题不需要像上方再写 arr[low++]=arr[fast]; 空间里面不要管了。
二、反转字符串
这个在熟悉不过了。往往最熟悉的容易刺伤自己 我做了一些题,大多就是反转整个字符串,
还有就是反转字符串中的单词,还有一点就是,按某一位反转再整体反转的那种。
2.1)普通反转字符串
只是输出反转
没有改变实际的空间,当我们直接输出整条字符串的时候,依然会是原来的字符串,原封不动的换回来
char arr[100];
scanf("%s",arr);
for(i=strlen(arr)-1;i>=0;i--){
printf("%c",arr[i]);}
改变空间的反转
这个才是输出整条字符串的时候,输出我们想要的那种。
char arr[100];
scanf("%s",arr);
int left = 0,right = 0;
for(left = 0,right = strlen (arr) ;left < stlrn(arr)/2;i ++,j --){
char temp = arr [left];
arr [left++] = arr[right];
arr [right--] = temp;
2.2)反转字符串中的单词
( 后续马上更新)