字符数组和字符串

字符数组:

char 类型的数组,用来存储多个字符(代表字符串),由于char占的内存比较小(1个字节),所以存储多维数组的时候建议使用,比较省内存。

  • char类型是存储不了中文的
  • 中文占2个字节

字符数组声明:

字符数组声明就是简单的数组声明

char c[100];//一维数组
char c1[10][10];//二维数组
char c2[10][10][10];//三维数组

字符数组初始化:

C/C++标准库中的字符串处理函数(如strcpystrlenprintf等)均依赖\0来判断字符串的结束。若字符串未以\0结尾,这些函数会继续读取内存,直到遇到随机内存中的\0,可能导致程序崩溃或数据错误。

需要注意的字符数组存储数据的时候需要添加 '\0' 代表字符串的结束

  • 由于需要存储'\0' 所以数组能存储的数据个数需要-1,留一个位置
  • 未以\0结尾的字符数组可能被误认为字符串,导致函数越界访问内存。
  • 初始化时如果你没给'\0'系统会自动添加

初始化的三种方式:

  • 使用字符串进行初始化: "内容"
  • 使用大括号+单个字符的方式初始化: {'字符1','字符2','字符3','字符4'.....}
  • 使用大括号+字符串的方式初始化:{“字符串”}
#include<iostream>
using namespace std;
int main()
{
	//字符串的结束标志为'\0',所以数组要多开一个空间存放'\0'
	//存放满数据,三种初始化方式相同 
	char a[10]="123456789";//只能存放9个数,第十个存放'\0' 
	char b[10]={'1','2','3','4','5','6','7','8','9'};
	char c[10]={"123456789"};
    char d[]="12345";//自动添加\0
	//或者末尾手动直接添加\0 
	char d[10]={'1','2','3','4','5','6','7','8','9','\0'};
	return 0; 	
} 

数据不够时使用'\0'填充:

#include<iostream>
using namespace std;
int main()
{
	//未存放满数据,会用'\0'补齐 
	char e[10]="12345";
	for(int i=0;i<10;i++)
	{
		if(e[i]=='\0') cout<<"\\0"<<endl; 
		else cout<<e[i]<<endl;	
	} 
	return 0; 	
} 

memset()初始化:

头文件:#include<cstring>函数:

memset(数组,值,数组大小);

  • 第一个参数:数组名
  • 第二个参数:任何字符
  • 第三个参数:获取数组的内存大小  sizeof(数组名)
  • 初始化是按照字节进行初始化,所以要获取数组内存
  • 如果你只初始化了数组的一部分,其他未初始化的部分为可能为SOH,所以使用的时候尽量进行数据全覆盖(但最好留一个位置存储\0)
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	char c[10];
	memset(c,'A',sizeof(c)-1);//留一个\0的位置
	for(int i=0;i<10;i++)
	{
		if(c[i]=='\0') cout<<"\\0"<<endl; 
		else cout<<c[i]<<endl;	
	} 
	cout<<c[9]<<endl;
	return 0; 	
} 

fill()初始化:

头文件:#include<algorithm>函数:

fill(起点,终点,值);

  • char arr[10];
  • 起点为:arr   终点:arr+9   9为数组长度留一个\0
  • 第一个参数:数组的起始位置   可以使用+num 进行后移
  • 第二个参数:数组的终点位置   也可以移动结束位置
  • 第三个参数:可以为任和的值
  • 如果你只初始化了数组的一部分,其他未初始化的部分为可能为SOH,所以使用的时候尽量进行数据全覆盖(但最好留一个位置存储\0)
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	char c[10];
	fill(c,c+9,'A');//留一个\0的位置 
	for(int i=0;i<10;i++)
	{
		if(c[i]=='\0') cout<<"\\0"<<endl; 
		else cout<<c[i]<<endl;	
	} 
	cout<<c[9]<<endl;
	return 0; 	
} 

字符数组赋值:

  • 使用数组[下标]=进行单个字符赋值
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	char c[10]="123";
	c[0]='A';//赋值 
	c[8]='D';//赋值 
	for(int i=0;i<10;i++)
	{
		if(c[i]=='\0') cout<<"\\0"<<endl; 
		else cout<<c[i]<<endl;	
	} 
	return 0; 	
} 

使用for循环进行赋值

#include<iostream>
using namespace std;
int main()
{
	char c[10]="123";
	int i=0;
	for(char c1='0';c1<'9';c1++,i++){//循环进行赋值
		c[i]=c1;
	}
	for(int i=0;i<10;i++)
	{
		if(c[i]=='\0') cout<<"\\0"<<endl; 
		else cout<<c[i]<<endl;	
	} 
	return 0; 	
} 

不能使用=进行数组和数组间的赋值,因为数组名是一个地址

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	char c[10];
	char d[10]="456";
	c=d;//报错,不能用=进行赋值
	c="123456";//报错,也不能用字符串去进行赋值  
	return 0; 	
} 

获取长度

字符数组长度:

由于char类型只占一个字节,直接使用sizeof(数组名)就是数组长度。

#include<iostream>
using namespace std;
int main()
{
	char c[10]="123";
	cout<<"字符数组长度:"<<sizeof(c);
	return 0; 	
} 

字符串长度:

由于\0代表结束,使用循环直接读到\0停止即可获取字符串长度

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	char c[10]="123";
	int num=0;
	for(;c[num]!='\0';num++){}//读取字符长度
	cout<<num;
	return 0; 	
} 

使用系统函数获取字符串长度

  • 头文件#include<ctsring>
  • strlen(字符数组名)
  • 可以获取到第一个'\0'前的元素个数
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	char c[10]="123";
	cout<<strlen(c)<<endl;//获取字符串长度 
	return 0; 	
} 

字符数组的输入和输出:

字符数组输入:

使用方法说明
cin>>字符数组名不能读取空格(空格和回车代表结束)
cin.getline(字符数组名,字符个数)   读取一行数据可以读取空格
cin.get()读取一个字符
scanf("%s",字符数组名)C语言方法头文件#include<cstdio>不能读取空格
fgets(字符数组名,字符个数,stdin)C语言方法头文件#include<cstdio>可以读取空格

字符数组的输出:

使用方法说明
cout<<字符数组名直接输出字符串
printf("%s",字符数组名)C语言方法头文件#include<cstdio>直接输出字符串
puts(字符数组名)C语言方法头文件#include<cstdio>直接输出字符串
#include<iostream>
#include<cstdio>
using namespace std;

int main()
{ 
	char a[10];
	
	//C语言方式的读取和输出(不能读取空格)
	scanf("%s",a);//输入 
	printf("%s\n",a); //输出 
	
	//C语言方式读取一行(可以读取空格)
	char b[10]; 
	fgets(b,9,stdin);//输入
	puts(b);//输出 
	
	//C++输入和输出(不能读取空格)
	cin>>b;
	cout<<b<<endl;
	
	//C++读取一行(可以读取空格)
	cin.getline(b,9);//读取一行
	cout<<b<<endl; 
	return 0; 	
} 

字符数组常用函数:

头文件:#include<cstring>

函数名函数的功能
strlen(S1)获取字符串长度,获取第一个''\0'之前的数据长度
strcpy(S1,S2)把S2复制到S1中
strcat(S1,S2)把S2连接到S1
strcmp(S1,S2)比较两者的大小 相同返回0
strchr(S1,ch)返回一个指针,指向S1中字符出现的位置
strstr(S1,S2)返回一个指针,指向字符串S1中S2第一次出现的位置
memcpy(A,B,size)把数组B中的Size个字符复制给A

strcpy(s1,s2)复制:

  • 将s2复制给s1,需要确保s1的容量大于等于s2的容量
  • 不能正确处理重叠的字符串。如果源字符串和目标字符串重叠,strcpy()的行为是未定义的。
  • 它不检查目标缓冲区的大小,如果源字符串比目标缓冲区长,可能会覆盖缓冲区并导致缓冲区溢出。这可能导致安全漏洞和其他问题。
  • 它不能正确处理源字符串中的空字符。如果源字符串包含空字符,strcpy()会在该点停止复制,即使源字符串中还有其他字符。

当S1容量小于S2时,编译器会对S1进行扩容(Dev-C++-5.11)(但不建议这样使用)

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	//strlen 获取'\0'之前的数据长度 
	char a[10]="123456";
	char b[5]={};//b的容量小于a
	strcpy(b,a);//但还是复制成功了
	for(auto p:b)//遍历数组
	{
		cout<<p<<endl;
	}
	cout<<"b字符串的长度"<<strlen(b)<<endl; 
	cout<<b[6]<<endl;
	return 0; 	
} 

实现一个strcpy()

//size为s1数组长度 
void Strcpy(char s1[],char s2[],int size){ 
	if(size-1<strlen(s2)) cout<<"s1容量不够"<<endl;
	else{
		for(int i=0;i<strlen(s2);i++) s1[i]=s2[i];//复制 
		for(int i=strlen(s2);i<size;i++) s1[i]='\0';//其他数据置为'\0' 
	} 
}

memcpy(A,B,size)复制个数

memcpy(A,B,size):把数组B中的Size个字符复制给A

#include<iostream>
#include<cstring>
using namespace std;
int main()
{ 
	char a[10]="123456";
	char b[20]="789459";
	memcpy(b,a,5);//把a中的5个数据复制b中 
	for(auto i:b)
	{
		cout<<i<<endl;
	 } 
	return 0; 	
} 

实现memcpy()

//length s1的数组长度  size为复制的个数
void Memcpy(char s1[],char s2[],int length,int size){
	if(length-1<size) cout<<"s1容量不足"<<endl;
	else if(strlen(s2)<size) cout<<"元素个数大于s2的长度"<<endl; 
	else{
		for(int i=0;i<size);i++) s1[i]=s2[i];//复制 
		for(int i=size;i<length;i++) s1[i]='\0';//其他数据置为'\0' 
	} 
}

strcat(s1,s2)拼接:

strcat(s1,s2):把S2连接到S1

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	//strlen 获取'\0'之前的数据长度 
	char a[10]="123456";
	char b[20]="789456";
	cout<<strcat(b,a)<<endl;
	return 0; 	
} 

实现Strcat()

//size为s1的数组长度 
void Strcat(char s1[],char s2[],int size){
	int length=strlen(s2)+strlen(s1);//获取复制后的总长度 
	if(size-1<length) cout<<"s1容量不够"<<endl;
	else{
		for(int i=strlen(s1);i<length;i++) s1[i]=s2[i];//复制 
		for(int i=length;i<size;i++) s1[i]='\0';//其他数据置为'\0' 
	} 
}

strcmp(s1,s2)比较:

从第一个元素开始根据ASCLL值比较两者的大小 

  • s1==s2 返回0
  • s1>s2返回1
  • s1<s2返回2
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	//strlen 获取'\0'之前的数据长度 
	char a[10]="123456";
	char b[20]="789456";
	cout<<strcmp(a,b)<<endl;//输出-1
	cout<<strcmp(b,a)<<endl;//输出1 
	return 0; 	
} 

实现strcmp()

int Strcmp(char s1[],char s2[]) 
{
	//获取小的数据长度
	int length=min(strlen(s1),strlen(s2));
	//开始比较
	for(int i=0;i<length;i++){
		if(s1[i]>s2[i]) return 1;
		else if(s1[i]<s2[i]) return -1;
	} 
	//当数据都相等时,需要判断长度 
	if(strlen(s1)==strlen(s2)) return 0;
	else if(strlen(s1)>strlen(s2)) return 1;
	else return -1;
}

strcahr(s1,ch)查找字符

strcahr(s1,ch):查找字符,返回一个指针(char*),指向S1中字符第一次出现的位置

  • 找到返回第一次出现的位置
  • 没找到返回 nullptr 
#include<iostream>
#include<cstring>
using namespace std;
int main()
{ 
	char a[10]="ab1cdef";
	char * p;
	p=strchr(a,'1');//返回的是第一次出现的位置
	
	cout<<*p<<endl;//输出的是当前位置的值 
	cout<<p<<endl;//输出的是字符串 

	//获取字符在字符串中的位置,可以通过计算指针与原始字符串指针的差值来得到。
	//输出所处的位置 
	cout<<p-a+1<<endl; 
	//输出之后的数据
	cout<<p+1<<endl; 
	return 0; 	
} 

实现strchr()

char *Strchr(char c[],char c1){
	char * p=c;//指向第一个元素
	while(*p!='\0'){
		if(*p==c1) return p;
        p++;
	}
	return nullptr;
}

strstr(s1,s2)查找字符串:

strstr(S1,S2)返回一个指针,指向字符串S1中S2第一次出现的位置,没找到返回nullptr

#include<iostream>
#include<cstring>
using namespace std;
int main()
{ 
	char a[10]="ab1cdef";
	char b[20]="cdef";
	char * p;
	p=strstr(a,b);//返回的是第一次出现的位置
	//获取字符在字符串中的位置,可以通过计算指针与原始字符串指针的差值来得到。
	//输出所处的位置 
	cout<<p-a+1<<endl; 
	return 0; 	
} 

实现strstr()

char* Strstr(char c[],char c1[]){
	char *p=c;
	if(strlen(c1)>strlen(c)) return nullptr;
	for(int i=0;i<=strlen(c)-strlen(c1);i++){
		bool b=true;//表示是否匹配成功 
		for(int j=i,k=0;j<i+strlen(c1)&&k<strlen(c1);j++,k++){
			if(c[j]!=c1[k]) {
				b=false;
				break;
			}
		}
		if(b) return p+i;
	}
	return nullptr; 
} 

string字符串:

C++ 标准库提供了 string 类类型,string是一个类,固定占用28个字节,string没有'\0'

  • 头文件:#include<string>
  • 关键词:string
  • 内部也是由char数组实现的
  • 但可以自动扩容

string声明:

把string 当作正常的数据类型使用即可

  • 格式   string 变量名
string str;//正常创建即可

string初始化:

直接使用 " "对字符串进行初始化

string str="ssssssssss";//初始化

string赋值:

字符串和字符串之间可以用 = 进行赋值

string s1="abcdefghijklmnopq";
string s2=s1;//可以使用=进行赋值

string数据访问:

使用数组的方式进行访问:  字符串名[下标]  进行字符的修改和访问

string s1="ABCDEFGHIJKL";
cout<<s1[0];//输出第一个字符
s1[0]='K';//修改你一个字符

string字符串拼接:

使用 + 进行拼接

  • 可以拼接字符
  • 也可以拼接字符串
	string s1="ABCDE";
	s1+='C'; //拼接字符
	string s2="KKKKKKKK";
	s1+=s2;//拼接字符串
	s1+="PPPPPPP"; 
	cout<<s1<<endl; 

string中的函数:

函数名描述
size() length()返回字符串长度cout<<str.size()/length();
empty()判断是否为空cout<<str.empty();
operator[]使用[ ]访问字符串中指定位置的字符。cout<<str[1];
find()查找子字符串在字符串中的位置。 string::nops 代表查找失败cout<<str.find("abc");
rfind()从后往前查找子字符串在字符串中的位置cout<<str.rfind("abc");
at()访问字符串中指定位置的字符(带边界检查)std::cout << str.at(0);
substr()返回从指定位置开始的子字符串。string sub = str.substr(0, 5);
append()在字符串末尾添加内容。str.append(" more");
insert()在指定位置插入内容。str.insert(pos, "inserted");
erase()删除指定位置的字符或子字符串。str.erase(pos, length);
clear()清空字符串。str.clear();
compare()比较两个字符串。(按照ASCLL比较,从头开始比较,直到那个数比较大即可退出)int result = str.compare("other");
c_str()返回 C 风格的字符串(以 null 结尾)const char* cstr = str.c_str();

string数据类型转换:

string和int:

说明使用方法
string 转 int std::stoi()函数
int 转 stringto_string() 函数

#include<iostream>
#include<string>
using namespace std;
int main()
{
    //string 转 int
	string a="123456";
	int b=stoi(a);
	cout<<b<<endl;
    //int 转 string
    int num = 123;
    string str = to_string(num);
    cout << str;
	return 0; 	
} 

函数的实现:

//string 转 int 
int string_int(string s){ //字符串转数字 小于2e9 
	int num=0;
	//拆解累加 
	for(int i=0;i<s.size();i++) num=num*10+(s[i]-'0');
	return num;
} 
//int 转 string 
string int_string(int n){
	//拆解逆转
	string str;
	while(n!=0){
		str+='0'+n%10;
		n/=10;
	} 
	string s1;
	for(int i=str.size()-1;i>=0;i--)s1+=str[i];//逆转拼接 
	return s1 ;
}

char数组和int:

说明使用方法
char数组 转 int使用#include <cstdlib>下的 std::atoi()函数
int 转 char数组

使用 #include<cstdlib>下的

std::char itoa(int value, char* string, int radix); radix为进制数


#include <iostream>
#include <cstdlib>
using namespace std;
int main() {

    //char数组 转 int 类型
    char str[] = "456";
    int num = std::atoi(str);
    std::cout << "num = " << num;

    ////int类型 转 char数组
    int a=123456789;
	char c[20];
	itoa(a,c,10);
	cout<<c<<endl;

    return 0;
}

函数的实现:

//char 转 int
int  char_int(char c[]){//结果在int范围内 
	int num=0;
	//拆解累加 
	for(int i=0;i<strlen(c);i++) num=num*10+(c[i]-'0');
	return num;
} 

//int 转 char*
//radix的范围为2-10 超过十的就不判断了 
void int_char(int num,char c[],int radix,int length){ 
	//首先先用strig先存储数据,看一下结果的长度
	string s;
	while(num!=0){
		s+='0'+num%radix;
		num/=radix;
	}

	if(s.size()<=length-1){ //数据可以放得下,把数据放入
		int j=0;//c数组下标 
		for(int i=s.size())-1;i>=0;i--,j++) c[j]=s[i];
		for(int i=j;j<length;j++) c[i]='\0';//把剩余位置都设置为\0 
	}
	else{
		cout<<"数组容量不够"<<endl;
	}
}

string输入和输出

字符串输入:

使用方法说明
cin>>字符串名不能读取空格(空格和回车代表结束)
getline(cin,字符串名)   读取一行数据可以读取空格
  • getline (istream& is, string& str, char delim); 读到delim截止

  •  getline (istream& is, string& str);

字符串输出:

使用方法说明
cout<<字符串名直接输出字符串
使用循环进行输出访问每一个数据
#include<iostream>
#include<string>
using namespace std;

int main()
{ 
	string s;
	cin>>s;//读取不带空格的数据
	cout<<s<<endl;
	
	//读取带空格的数据
	getline(cin,s);//读取一行数据
	string s1;
	getline(cin,s1,'p');//读取一行读到p停止
	cout<<s<<endl<<s1<<endl; 

	return 0; 	
} 

C++处理带空格的字符串:

当我们要处理带空格的字符串的时候是有很多种方法解决的

  • 字符数组的读取方法
  • 字符串的读取方法

字符数组的读取方法:

使用方法说明
cin.getline(字符数组名,字符个数)   读取一行数据可以读取空格
cin.get()读取一个字符(可读取空格)
fgets(字符数组名,字符个数,stdin)C语言方法头文件#include<cstdio>可以读取空格

需要注意的是 使用过cin后  \n 没有被cin读取,所以还会残留在输入流中,需要将 \n 读取掉再读取一行

单独读取一行:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
	char a[50];
	fgets(a,sizeof(a),stdin);//需要指定数据长度,更安全
	cout<<a<<endl;
	return 0;
}

连续输入读取:

//连续输入和读取多行
#include<iostream>
#include<cstdio>
#include<cstdlib> //char数组转int 的头文件
using namespace std;
int main()
{
	char n[50];//创建一个字符串
	fgets(n,sizeof(n),stdin);//读取需要输入的字符串个数
	int N=atoi(n);//转换为数字 为数据的行数
	while(N--)
	{
		gets(n);//输入字符串
		cout<<n<<endl; //输出字符串
	}
	
	return 0;
}

处理cin输入问题:

//连续输入和读取多行
#include<iostream>
#include<cstdio>
#include<cstdlib> //char数组转int 的头文件
using namespace std;
int main()
{
	char n[50];//创建一个字符串
	int N=0;
	cin>>N//读取行数 
	cin.get();//读取掉 \n 
	//后面就能正常读取一行数据了 
	while(N--)
	{
		gets(n);//输入字符串
		cout<<n<<endl; //输出字符串
	}
	
	return 0;
}

字符串的读取方式:

使用getline函数读取一行带空格的数据

  • getline (istream& is, string& str, char delim); 读到delim截止

  •  getline (istream& is, string& str);

单独读取一行:

//读取一行数据
#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s;
	getline(cin,s);//读取一行数据
	cout<<s<<endl; 
	return 0;
}

连续输入读取:

//输入和输出多行数据时
#include<iostream>
#include<string>
using namespace std;
int main()
{
	 string s;
	 getline(cin,s);//输入读取的个数
	 int N=stoi(s);//转换为整数
	 while(N--)
	 {
	 	getline(cin,s);
	 	cout<<s<<"--------------"<<endl; 
	 } 
	return 0;
}

处理cin输入问题:

//当使用cin输入数据时,一定cin读取的那行的回车符号先去除掉
#include<iostream>
#include<string>
using namespace std;
int main()
{
	 int N=0;
	 string s;
	 cin>>N;
     //把这行全部读取完 ,不然cin这行的\n 会被留在输入流中的   getline()读取 
	 getline(cin,s);
	 //或者使用cin.get() 读取掉这个回车符
	 while(N--)
	 {
	 	getline(cin,s);
	 	cout<<s<<"--------------"<<endl; 
	 } 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值