不讲string 只讲char 数组名[ ] 和 const char * 数组名,以及二维数组
所以这篇,所有变量声明都是char 带一个方括号[ ]类型!但是最近看了B站某个培训班课程,老师将以‘ 0’ 结尾的叫字符串,不以‘ 0 ’ 结尾的叫字符数组!
char strA[]{'s','k','i','r','t'};
char strB[]{'s','k','i','r','t','\0'};
strA是字符数组,strB是字符串!这样可能更专业但是本文中,我不采用这种叫法。。
1. 声明和初始化格式:
char mess[]{'A','B','C'};
cout<<mess<<endl;
char mess2[] {'h','l','e','w'};
cout<<mess2<<endl;
但是,在打印这两个字符数组的时候就开始出现奇怪的现象了。垃圾信息出现!
解决办法1:结尾的‘\0’ 补上,变成标准的C字符数组。
char mess[]{'A','B','C','\0'};
cout<<mess<<endl;
char mess2[] {'h','l','e','w','\0'};
cout<<mess2<<endl;
解决办法2:不写 '\0' 了,正确写好整个数组长度,记得给null字符也占用一个位置。例如下图,有6个字母,一定要写7.千万别写6!
char mess3[7] {'f','o','o','t','b','a'};
cout<<mess3<<endl;
解决办法3:字面量的C字符串。
char mess4[] {"watch"};
cout<<mess4<<endl;
多个单词也行:
char mess5[] {"outside the sky"};
cout <<mess5<<endl;
出错案例展示:来自B站课程5_哔哩哔哩_bilibili 1小时42分
char str[10]={0};
for(size_t i=0;i<10;i++){
scanf("%c",&str[i]);
}//helloworld 一共10个字母
printf("shuchu\n");
printf("%s\n",str);//多了个叹号 !老师的演示是多了一堆乱码
for(size_t i=0;i<10;i++){
printf("%c \n",str[i]);
}
//用for循环一个个打印倒是又没错了
//所以一定要写的比方括号里的数字短一个字符!
2. 二维C++ 字符数组
char words[][10] {
{'f','o','o','t'},
{'w','o','r','s','e'},
{'a','r','o','m','a'}
};
size_t wordslen=sizeof(words)/sizeof(words[0]);
//cout<<wordslen;
//3 这是一个3行 10列的数组 不够10的都自动填充'\0'
//遍历方法 一个一个字母输出 不要直接cout<<words[i]
for(size_t i{0};i<wordslen;i++){
for(size_t j {0};j<10;j++){
cout <<words[i][j]<<" ";
}
cout<<endl;
}
C语言形式的二维字符数组 。遍历方法也略有不同
char members[][10] {
"Samuels",
"David",
"Felly",
"Dolly"
};
size_t memlen=sizeof(members)/sizeof(members[0]);
// cout<<memlen<<endl; //4
for(size_t i{0};i<memlen;i++){
cout<<members[i]<<endl;
}
另外补充代码习惯问题,这样写可以减少变量的数目。
//不良代码写法
char advice1[] {"hello, foreigner"};
char advice2[] {"I've seen a car"};
//也能正常打印
//更好的做法
char advices[][50]{
"hello, foreigner",
"I've seen a car",
"The fox is yellow"
} ;
cout<<advices[2]<<endl;
3.头文件 cctype ,函数isdigit, isnum, isalpha, isblank等等
cout<<"---#include <cctype>---"<<endl;
char ch1 {'A'};
cout<<isalnum(ch1)<<endl;
cout<<isalpha(ch1)<<endl;
//大小写转换
char sentance [] {"There is a white fox"};
size_t word_num=sizeof(sentance )/sizeof(sentance [0]);
char sentan2 [word_num];
for(size_t i=0;i<word_num;i++){
sentan2[i]= toupper(sentance [i]) ;
}
cout<<sentan2<<endl;
cout<<sentance <<endl;
例1:找出句子中一共有多少个空格
//find the blank
char mess1[] {"Hello friend, what is your name"};
int blankcount {};
size_t all=sizeof(mess1)/sizeof(mess1[0]);
for(size_t i=0;i<all;i++){
if(isblank(mess1[i])){
cout<<"Find a Blank"<<endl;
blankcount++;
}
}
cout<<blankcount<<endl;
例2:找出句子中有多少个数字
//find digits
char statements [] {"The aboretum has 128 kinds of plants.15 kinds are very rare"};
for(auto ch : statements ){
if(isdigit(ch)){
cout<<"Find a num "<<ch<<" ";
}
}
4.头文件cstring--strcmp比较,strcat拼接(改变原有), strcpy复制,
4.1 strlen( 字符数组名)
cout<<"---#include <cstring>---"<<endl;
cout<<"---strlen---"<<endl;
cout<<strlen(sentance )<<endl;
4.2 strcmp, strncmp 将两个字符串进行比较,按照字母表排序
cout<<"---strcmp--结果 -1 0 +1-----"<<endl;
//char *book1 {"The heaven bird"}; 警告
const char *book1 {"The blue bird"} ;
const char *book2 {"The hydarte earth"} ;
cout<<strcmp(book1,book2)<<endl;
cout<<"---strncmp--第三个参数表示比较几个字符-----"<<endl;
cout<<strncmp(book1,book2,3)<<endl;
4.3 strchr,strrchr 在字符串中寻找单个字符,并从匹配的地方进行截取。
例:从book1 the blue bird中寻找字符 ' u' ,找到了,那么返回以u为首的剩下的字符串。
cout<<"---strchr--从相同的地方开始-----"<<endl;
cout<<strchr(book1,'u')<<endl; //ue bird
cout<<*strchr(book1,'u')<<endl; //u
//老师的例子
const char *mess5 {"Try to do The sucess is noT far."} ;
const char *result =mess5;
char Target {'T'};
int pos {};
while((result=strchr(result,Target))!=nullptr){
cout<<"找到了 "<<Target<<" "<<result<<endl;
result++;
pos++;
}
cout<<pos<<endl;
cout<<"---strrchr--从末尾开始往前找-----"<<endl;
//Juti具体应用:截断文件的扩展名
char input[]{"D:/devC++ Progect/myt.txt"};
char *res=strrchr(input,'.');
if(res!=nullptr){
cout<<res+1<<endl;//把找到的点跳过去
}
else{
cout<<"没找到了"<<endl;
}
4.4 strcat, strncat 将两个字符串拼接
cout<<"---strcat-----"<<endl;
char dest[40]="hello ";
char behind[40]="world";
strcat(dest,behind);
cout<<dest<<endl;
cout<<"---strncat-----"<<endl;
char ff[40]="Meeting you ";
char bb[40]="are nice very much";
strncat(ff,bb,8);
cout<<ff<<endl;
cout<<"---strcat注意事项-----"<<endl;
char *str1=new char [10] {'A','B','C','D','\0'};
cout<<strlen(str1)<<endl;
char *str2=new char [10] {'!','W','Q',' ','F','r','\0'};
cout<<strlen(str2)<<endl;
strcat(str1,str2);
cout<<"合并后长度"<<strlen(str1)<<endl;
4.5 strcpy( 前者,后者) ,将后者拷贝到前者中。 strncpy
cout<<"---strcpy(dest,source) 记住前者被后者覆盖了-----"<<endl;
char source[10]="Meeting Y";
char *dest3=new char [11];
strcpy(dest3,source);
cout<<dest3<<endl;
cout<<"---strncpy(dest,source,n) -----"<<endl;
const char *sour2="Cookbiscuit";
char dest4[] {'H','E','L','L','P','\0'};
strncpy(dest4,sour2,4);//dest4的前4个字符被 资源库的4个字符覆盖
cout<<dest4<<endl;//CookP
4.6补充,C语言 strstr (strA, tarstrB)
头文件<string.h>
在字符串strA中,寻找目标子串tarstrB,如果找不到,返回NULL,如果找到了,返回匹配子串为首的剩余字符串。
//字符串查找 找到的次数 利用已有的strstr <string.h>
int ser_time(char *sear,char*tar){
int k=strlen(tar);
int count=0;
char *r=strstr(sear,tar);
while(r!=nullptr){
printf("%s\n",r);
r+=k;
count++;
r=strstr(r,tar);//再新的 掐去了头的 字符串里寻找
}
return count;
}
4.7 补充,C语言 strtok(strA, line) <string.h>
按照既定的分隔符line ,来拆分字符串strA。语法
char* strtok( char* str, const char* delim)
返回值:拆分后的首地址。
char strG[]="www.baidu.com.cn";
char *ret3=strtok(strG,".");
printf("%s\n",ret3);
原来的strG变成了www\0 baidu.com,www成为了一个独立的串。所以返回www的首地址。
但是strtok只能拆分一次。如果想持续拆分的话:
char strG[]="www.baidu.com.cn";
char *ret3=strtok(strG,".");
while(ret3!=NULL){
ret3=strtok(NULL,".");
printf("%s\n",ret3);
}
//结果分别是
//www baidu com cn (null)
注意事项:strtok的第一个参数必须可读可写,因为这个函数是在原来字符串上进行操作。以下这2种格式都是常量,不能当参数1.
char* str2="www.sina.com"
const char* str3="www.qq.com.cn"
4.8 C语言 <string.h> strstr( 搜索字符串,目标字符串)
待补充
5.利用指针,记得加上const,不然编译器有警告,禁止将string变成char *
const char* car{"volve"};
char* car2 {"bwm"};//我用的red panda Dev C++就会警告
6.利用指针,二维字符数组可以写成const char* 数组名[ ],这样就不需要限定长度,变得更加灵活
const char* benediction []{
"We will have a happy weekend",
"to enjoy today",
"to be honest and brave",
"to wear your beautiful apparus"
};
//遍历
for(size_t i{0};i<size(benediction);i++){
cout<<benediction[i]<<endl;
}
基于范围的for循环,也可以换一种遍历方式:
for(const char* dic :benediction){
cout<<dic<<endl;
}
7.加了const还能修改吗?一定无法修改了吗?
const char* stuA{"Tom Cruse"};
//stuA[0]='D'; 报错了,stuA的名字是一个常量
但是修改指针指向就能改了,因为这是常量指针,不是指针常量
const char* stuA{"Tom Cruse"};
const char *stuB {"Wang wu"};
stuA=stuB;//改变指针指向
cout<<stuA<<endl;//王五,不是汤姆克鲁斯
二维指针数组类似
const char* students[]{
"Tom Cruse",
"Wang wu",
"Zhang San",
"Lily Ford"
};
//*students[0]='D'; 报错,不能修改为Dom Cruse
改变指针指向,就把第一个汤姆克鲁斯变成韩明明了
const char* stuE {"Han mingming"};
students[0]=stuE;
for(const char* stu:students){
cout<<stu<<endl;
}
注意!!如果指针常量,上文就报错了,因为指针常量的指向也是固定的,不能修改指向其他变量
const char* const students[]{ //多了一个const在星号后面
"Tom Cruse",
"Wang wu",
"Zhang San",
"Lily Ford"
};
8.补充,atol, atoi, atof
将字符串转化成长整型;long
将字符串转化成整型;int
将字符串转化成浮点型;float