C++字符串常量总结(包含表达式必须是可修改的左值问题)
引用参考,感谢各位大佬,另外还有阅读了书籍《C++程序设计》谭浩强编著。
https://blog.csdn.net/JQ_AK47/article/details/53169799
https://www.runoob.com/w3cnote/cpp-string-array-pointer.html
https://blog.csdn.net/weixin_41498246/article/details/103322225
字符串常量与双引号
在 C 语言中,将字符串作为字符数组来处理,而C++中不是。
C++中,用双引号括起来的字符就是字符串常量,如“abc”,“hello”,“a+b”都是字符串常量。
双引号做了3件事:
1.申请了空间(在常量区),存放了字符串
2. 在字符串尾加上了’/0’
3.返回地址
例:
这里的字符串常量“Wang_li”看起来是7个字符,但是在内存中占8个字节,字符串最后自动加上了一个‘\0’作为字符串结束标志。在为字符串设置内存空间时一定要注意这一点。
字符串常量返回的是地址,而不是Wang_li\0,因此它可以赋值给指针而无法在已经定义好字符串变量后再赋值给字符串变量,后面细写。
它是常量,因此是const char[],而不是char[],
字符串常量的保存与使用
字符数组(必须是可修改的左值原因)
1、用字符串常量来初始化字符数组
char name1[] = { "Wang_li" };
char name2[] = "Wang_li" ;
char name3[10] = "Wang_li";
char name4[10]= { 'W','a','n','g','_','l','i'}; //补充
C++允许用这种方式初始化字符数组,虽然字符串变量返回的是地址。
但需要注意的是,字符数组的赋值只能对字符数组的各元素逐个赋值,不能用赋值语句对整个数组一次赋值。
char name[10];
name[0] = 'W'; name[1] = 'a'; name[2] = 'n'; name[3] = 'g'; //正确
char name[10];
name = { 'W','a','n','g','_','l','i'}; //错误
char name[10];
name = "Wang_li"; //错误,表达式必须是可赋值的左值
定义的char Name[10] ,是一个字符数组,在定义完成之后,系统会分配一段内存,这段内存的地址赋值给name,给name的这个内存地址是一个常量。
而name = "Wang_li"不行,"Wang_li"赋值的值是一个地址,而name虽然也是地址,但是这与指针是不一样的,指针的值是地址,而数组的值虽然也是地址,但是却是一个常量,所以不能给常量赋值。
但C++支持用字符串常量初始化,初始化相当于一个一个元素赋值。
运算符的左边应该是一个“左值”。所谓“左值”就是指在程序中占用内存空间、可以被修改的量,比如各种变量。
解决办法见指针小节。
在字符串实际长度和数组长度不等的时候,系统对字符数组最后的元素自动填补空字符‘\0’,注意,不是空格字符。在程序中往往依靠检测‘\0’的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。
2、首先定义字符数组(必须确定字符数组的长度),用cin从键盘向计算机输入一个字符串。
char str[10];
cin>>str;
字符串指针(表达式必须是可修改的左值解决办法1)
字符串常量已经在常量区存放了,返回地址,因此定义一个字符串常量指针变量指向这个字符串常量就可以使用了。例
const char *name ;
name = "Wang_li";
const char *name2= "Wang_li";
可以直接初始化,也可以先定义指针变量再赋予字符串常量的地址,这种先定义再赋值的方法很适合在C++的类定义里使用。
必须是可修改的左值解决办法:
char name3[10];
name3 = "Wang_li";//错误,表达式必须是可修改的左值
const char *name ;
name = "Wang_li";//正确
class Student
{
public:
Student(int n,char nam)
{
num = n;
name = nam;//错误,表达式必须是可修改的左值
}
private:
int num;
char name[10];
};
class Student
{
public:
Student(int n,const char* nam)
{
num = n;
name = nam;//正确
}
private:
int num;
const char* name;
};
Student stud1(10010, "Wang_li");
总结:将字符串常量的返回值理解为地址,使用指针变量指向字符串常量就可以了。注意字符串常量是存储在常量区的,是const char类型,因此指针是constant char *类型的。(VS2017需要这么写,不过书上可以用char *指向字符串常量,大概是低版本支持,到高版本不支持了。)
字符串变量(string,表达式必须是可修改的左值解决办法2)
C++提供了一种新的数据类型——字符串类型(string类型),string并不是C++的基本类型(像char,int,float都是基本类型),它是C++标准库中声明的一个字符串类,每一个字符串变量都是string类的一个对象。
在使用string类定义变量时,必须在文件开头将string头文件包含进来
#include <string> //注意头文件名不是string.h
定义字符串变量和赋值。注意,定义字符串变量时不需指定长度,它的长度随其中的字符串长度而改变,如果指定长度反而可能出现“表达式必须是可修改的左值”问题。
string string1; //定义字符串变量时不需指定长度
string string2="China";
string1="China"; //可以先定义后赋值
同样针对之前举例的定义类时的表达式必须是可修改的左值问题:
#include <string> //用string类必须包含这个头文件
class Student
{
public:
Student(int n,string nam)
{
num = n;
name = nam;
}
private:
int num;
string name;
};
Student stud1(10010, "Wang_li");
如果仍然又表达式必须是可修改的左值问题,可以观察一下其他细节,比如[n]的有无,string不加[n]的,但const char* name[10]在定义类时就需要。
补充
如果在一个字符串中最后一个字符为“\”,则表示它是续行符,下一行的字符是该字符串的一部分,且在两行字符串间无空格。如
cout << "You are so\
oooo cute";
输出的是You are sooooo cute