C++ char * 和char[]的区别以及怎样与string类型进行转换

一、char与string的区别

char也就是字符型数据定义,string也就是字符串类型数据定义,乍一看他们很想,一个是字符一个是字符串,字符串不就是字符串起来得到的吗?但是事实上,字符串即是“字符”串起来也不是“字符”串起来,听起来是不是很奇怪,这里面的两个字符的意义其实是不一样的,第一个“字符”的意思是指一个单位的字形、类字形单位或符号的基本信息,而第二个“字符”的意思是字符类型。可能大家听得还是很糊涂,我帮大家捋一捋,我们现在要先弄清楚一点,char是字符类型,属于一个类,属于编程语言中的一个数据类型,而他和字符有区别,字符是什么?字符指的是一个基本信息单位,也就是说字符是一个数据,它可以是数字也可以是字母。

所以,char是一个可以用来存储字符数据的变量类型,而string就是一个存储一串字符数据的变量类型,他们的共同点就是他们都是变量类型,都是用来存储字符的。

我想这样说大家应该明白了,既然他们俩如此相像,也就免不了他们要常常互动了,不过在讲他们的交互之前,我要和大家再提一个概念,不过希望大家能先理清刚刚讲的再看,不然会越看越乱的。

下面我要说的就是字符数组,char[],他是一组char类变量组成的,也可以用来存储一串字符数据,和string的作用很是相像,但是本质是不一样的,他们应该是数组变量,一个是类变量,char[]很好理解,他就是一个数组,每个单元里面放一个字符数据最后以字符’\0’,作为分隔标识;string则是一个整体,而且他还有很多类函数可以调用使用。

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;
void main()
{
	string Lyu;
	Lyu = "I love C++";
	cout << "字符串为:" + Lyu << endl;
	cout << "字符串的长度为:" << Lyu.length() << endl;
	cout << "是否为空:" << Lyu.empty() << endl << endl;		//若返回值为0,则指字符串不为空
	Lyu.append("!");			//字符串后追加一个!
	cout << "追加修改后的字符串为:" << Lyu << endl << endl;
	string Lyu_2;
	Lyu_2 = "I love too";
	Lyu.swap(Lyu_2);			//字符串数据交换
	cout << "交换修改后的字符串为:" << Lyu << endl << endl;
	int site;
	site = Lyu.find('l', 0);	//从0开始寻找出现l的位置并返回位置
	cout << "字符串中出现l的位置为:" << site << endl;
	site = Lyu.find("oo", 0);	//从0开始寻找出现oo的位置并返回位置
	cout << "字符串中出现oo的位置为:" << site << endl << endl;
	site = 0;				//遍历搜索所有o的位置
	do
	{
		site = Lyu.find('o', site);
		if (site == -1)
			cout << "搜索完毕,无其他项" << endl;
		else
			cout << "字符串中出现o的位置为:" << site << endl;
		site++;
	} while (site != 0);
	getchar();
}

在这里插入图片描述
在string中b.length()和 b.size()没什么区别,就是指去掉’\0’后的字符串的长度

原文链接:https://blog.csdn.net/yu1543376365/article/details/79176606

博客如下:http://blog.csdn.net/liruxing1715/article/details/6715503

http://blog.csdn.net/yahohi/article/details/7427724

二、char*、char[]及string的区别

数据在内存中的存储区域

1、栈:就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
2、堆:就是那些由new或malloc分配的内存块,在不适用时,要手动用delete或free来释放内存区域。
3、 全局/静态存储区:全局变量和静态变量被分配到同一块内存中,他们共同占用同一块内存区。
4、 常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)

#include <iostream>
using namespace std;
int main()
{
    char *a = "abc";
    char b[3] = { 'a','b' };
    b[0] = 'b';
    a[0] = 'b';
    cout << a << " " << b ;
    getchar();
 }

以上代码在运行时时会在第8行处( a[0] = ‘b’)出错,因为char*和char[]的内存分区是不同的。

上面代码中的char*a = ”abc“的”abc“是常量所以被分配在常量存储区,a为字符指针类型是存放在栈区可以被更改,而常量存储区是不能更改的,是只读区域,所以当你试图去写入数据的时候,会报错。

而char b[3] = {‘a’,‘b’}的字符a和b是存放在栈区的所以可以进行写操作。

三、string跟char*类型转换

1、string转换成char*类型

string s = ”abc“;
const char *k = s1.c_str();
const char *t = s1.data();

这两个函数返回值只能是const的类型

因为c_str()函数返回的是const char*类型,所以必须要重新定义一个const char* 的字符串来接受c_str的返回值。然后再通过memcpy将const char类型的字符串复制到char类型的字符串。

2、char*转换成string类型

char* p = ”abc“;//字符串常量的本质是它的第一个字符的地址。
string s = p;

这个操作就是可以直接赋值即可

四、char、char* 、char[]输出

首先当使用char*或者char[]来表示字符串时,加上string.h头文件来调用库函数。

1、char

char只表示一个字符,若重复赋值,则或者会覆盖前者:
char ch=‘qwqewqe’;
cout<<ch<<endl;
输出:e
因为char只有一个字符,后者会覆盖前者。

2、char* src表示字符串

字符串的本质即是指向首个字符的指针(地址)

#include <iostream>
using namespace std;
int main() {
    char *src = "Lijiwen";
    cout << &src <<endl;//0x61ff0c首个字符L的地址
    cout<<src <<endl;//Lijiwen
    cout << &(*src)<<endl; //Lijiwen
    cout<<*(&src)<<endl;//Lijiwen

    cout<<src+2<<endl;//jiwen
    cout<<&src[2]<<endl;//jiwen

    cout<<src[0]<<endl;//L
    cout<<*src<<endl;//L

    cout<<*(src+2)<<endl;//j
    cout<<src[2]<<endl;//j


    cout<<&"Lijiwen"<<endl;//0x405065首个字符L的地址
    cout<<"Lijiwen" <<endl;//Lijiwen
    cout << &(*"Lijiwen")<<endl; //Lijiwen
    cout<<*(&"Lijiwen")<<endl;//Lijiwen
    
    cout<<"Lijiwen"+2<<endl;//jiwen
    cout<<&"Lijiwen"[2]<<endl;//jiwen
    
    cout<<"Lijiwen"[0]<<endl;//L
    cout<<*"Lijiwen"<<endl;//L
    
    cout<<*("Lijiwen"+2)<<endl;//j
    cout<<"Lijiwen"[2]<<endl;//j
}
#include <iostream>
using namespace std;
int main() {
    int b = 2789;
    int *src = &b;
    cout << &src <<endl;//0x61ff08,指针的地址
    cout<<src <<endl;//0x61ff0c ,b的地址
    cout << &(*src)<<endl; //0x61ff0c
    cout<<*(&src)<<endl;//0x61ff0c

    cout<<src+2<<endl;//0x61ff14
    cout<<&src[2]<<endl;//0x61ff14

    cout<<src[0]<<endl;//2789
    cout<<*src<<endl;//2789
    
    cout<<src[1]<<endl;//4201424
    cout<<*(src+1)<<endl;//4201424
    cout<<src[2]<<endl;//6422320
    cout<<*(src+2)<<endl;//6422320
   
}

可以对比得出,字符串与指针src完全等价,字符串的本质即是指向首个字符的指针。

  • C语言没有字符串类型,所有的字符串其实都是字符指针,而且是一个指向其首字符的指针。比如"abc"就是一个指向字符’a’的指针。
    char *p = “abc”;
    此处,就是将’a’的地址赋值给了指针p,因此我们一般说“p指向了字符串"abc"其实只是一种简便的习惯说法,严格地说法应该是“p指向了字符串"abc"的首字符’a’”。
    根据这个小知识点,和指针运算规则,我们就会得出一些匪夷所思但却正确的表达式:
    “abc”[1] 其实就是 ‘b’,你可以打印出来试试:printf("%c\n", “abc”[1]);
    1[“abc”] 其实也是’b’
    https://blog.csdn.net/vincent040/article/details/50614421?utm_source=blogxgwz3

这里的src为指针,指向的就是该字符串的首地址开始表示的内容 。
可以使用src[i]获取第i的字符;也可以使用src+i代表第i个字符开始后面的字符串

可以使用src获取整个串;

可以使用&src获取存放该字符串的首地址:

 char *src="qwertyu";//字符串常量的本质是它的第一个字符的地址,字符串常量在编译器中是把它看做一个地址。

    cout<<src[0]<<" "<<src[1]<<" "<<src[2]<<endl;

    cout<<src<<endl;

    cout<<&src<<endl;

这里如果想使用printf输出,只能使用src,不能加&

因为*src代表src本身就是一个指针,指向src的首地址,使用src就可以输出了,而如果&src则是代表指针自己的储存位置(src地址的地址),因此错误!!

printf("%s\n",src);//正确

printf("%s\n",&src);//错误

3、char src[] 表示字符串

char src[]="qwertyu";

使用src[i]获取第i个字符:
cout<<src[0]<<" “<<src[1]<<” “<<src[2]<<endl;
使用src获取整个字符串:
cout<<src<<endl;
使用&src获取首地址:
cout<<&src<<endl;
在使用printf时,加不加&都是可以的:
printf(”%s\n",src);//正确
printf("%s\n",&src);//正确

#include <iostream>
using namespace std;
int main() {
    char ch='qwqewqe';
    cout<<ch<<endl;
    
    char *src="qwertyu";
    cout<<&src<<src<<endl;

    char str1[]="Love";
    char str2[]={'L','o','v','e'};  //长度未知,见https://blog.csdn.net/weixin_43892514/article/details/107050104 中第30
    char str3[]={'L','o','v','e','\0'};
    cout<<str1<<'\n'<<str2<<'\n'<<str3<<endl;

    int num[] = {1,2,3};
    cout<<num<<'\n'<<num[0]<<endl;

输出:在这里插入图片描述

五 、参考

C语言中,为什么字符串可以赋值给字符指针变量
深入 char * ,char ** ,char a[ ] ,char *a[] 内核
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值