学习笔记

4.2字符串

4.2.1 拼接字符串常量

image-20241025155210847

4.2.2 在数组中使用字符串

image-20241025142811711

strlen只计算可见的字符,不会把空字符,也就是字符串结尾也计算在内部.

因此字符数组a[]的长度必需≥strlen(a) + 1.多出来的1就是存放空字符的.

4.2.3字符串输入

小小辨析一下,因为我看到这个教学视频讲到这一小节的时候,有部分弹幕的解释是错误的.为了让大家看教学视频的时候不被误导,我这里给出易混淆辨析.

辨析1:

空格:空格键产生的字符,ascii码十进制:32

空字符:字符串结束标志‘\0’,为被动添加,ascii码十进制:0

字符0:ascii码十进制:48

辨析2:

空格、制表符、换行符(创建新行)、回车符、换页符、垂直制表符称为“空白字符”,因为它们与打印页上的单词和行之间的空格一样都是起到方便阅读的作用。 标记由空白字符和其他标记分隔(划分边界),如运算符和标点。 在分析代码时,C 编译器将忽略空白字符,除非您将它们用作分隔符或者字符常量或字符串文本的组成部分。 使用空白字符可以让程序更易于阅读。 请注意,编译器也将注释视为空白。

C语言的空字符是在字符串结尾系统自动加上的\0,以让系统识别出一个字符内串的结尾。如:字符串“china”。在系统内是以“china\0”储存的。

image-20241025145339983

cin对象的使用

cin这个对象使用空白字符(空格,制表符和换行符)来确定字符串的结束位置.

image-20241025144300480

image-20241025144415992

4.2.4 每次读取一行字符串的输入

1.面向行的输入:getline()

image-20241025145751147

cin是对象,getline()是方法.记忆方式:

第一个参数就放入字符数组a[]的名字a

第二个参数就放入字符数组a[]的初始化时候的ArSize.这里注意ArSize最短也是stelen(a) + 1.

image-20241025150613204

image-20241025151031360

2.面向行的输入:get()

get()有好几种变体,因此要分清楚

image-20241025151747360

image-20241025151918997

image-20241025152208785

事实上,C语言就没有函数重载这个特性.

3.空行和其他问题

image-20241025152808019

马上第五章就遇到这个问题,我就是第五章的时候有点懵了,回看第四章发现自己连笔记都没有,所以才来复习并补第四章的笔记.

4.2.5混合输入字符串和数组

image-20241025153143535

image-20241025153235331

image-20241025153330864

4.3 string类简介

image-20241025153518855

string对象和字符数组之间的一些相同点和不同点

image-20241025154720049

4.3.2 赋值,拼接和附加

注意分清楚

字符数组和字符数组之间的操作

(下面图片都是字符数组和字符数组之间的操作.s1 和 s2都是char s1[] 和 char s2[]

不是string s1 和 string s2

image-20241025160109804

这里有一个总结的非常好的博客,C++ 字符串与字符数组 详解

)

string对象和string对象之间的操作

image-20241025154851010

C++ 中的 String 类
C++ 标准库提供了 string 类类型,支持上述所有的操作(看来上面那个图片的s1和s2也可是用string s1和 string s2定义的,不过我还是分开用,不要转牛角尖.),另外还增加了其他更多的功能。比如:

append() – 在字符串的末尾添加字符(用法应该是s1.append(s2)这样子,因为s1是个string对象嘛)
find() – 在字符串中查找字符串
insert() – 插入字符
length() – 返回字符串的长度
replace() – 替换字符串
substr() – 返回某个子字符串

4.3.3 string类的其他操作

image-20241025161107043

image-20241025161150886

image-20241025161312655

下面图片是重要的区别,使用方法的不同要牢记.

image-20241025161442981

4.3.4 string类I/O

image-20241025161854355

image-20241025162831731

image-20241025163016075

image-20241025163617681

cin.getline(charr, 20)这里的getline是istream类里面的一个成员函数,也就是istream类里面的一个方法

getline(cin, str)这里的getline就是一个单纯的函数,将我们输入流里面的内容存放到str这个字符串里面.

4.4 结构简介

image-20241025164215982

image-20241025165132097

image-20241025165334528

4.4.1 在程序中使用结构

image-20241025165613768

image-20241025165700242

image-20241025165836985

4.4.2和4.4.3直接见图片

image-20241025165948981

4.4.4 其他结构属性

image-20241025170340932

image-20241025170458999

image-20241025170701133

4.4.5 结构数组

以后这种多个专有名词组合起来会更加的容易混淆,注意的是哪个名词是用作修饰的形容词,哪个名词是用作中心语的.

结构数组的结构就是形容词,数组就是中心语.

image-20241025171758516

4.4.6 结构中的位字段

image-20241025172246622

4.5 共用体(联合体)

具体内容自己看原书pdf

C++ Primer Plus(第6版)_中文版_带书签_超清.pdf

,这里不做重点学习

image-20241025172524272

4.6 枚举

重点就一个,就是定义符号常量

image-20241025172925541

4.7 指针和自由存储空间

image-20241025194434398

image-20241025194613719

image-20241025194837371

image-20241025194927916

下面这个比喻很好,可以记住.

事实上,你也可以直接记忆成 别名

image-20241025195134238

4.7.1 声明和初始化指针

image-20241025195401522

image-20241025195455639

image-20241025195608202

记住,int* 是一种复合类型,是指向int 的指针

image-20241025195813586

image-20241025195854220

image-20241025195955540

4.7.2 指针的危险

注意空指针和野指针的解引用问题,会造成难以排查的严重错误.

image-20241025200300954

4.7.3 指针和数字

image-20241025200415097

4.7.4 使用new来分配内存

指针真正的用武之地在于,在运行阶段分配未命名的内存以存储值.

image-20241026083456310

image-20241026083537534

image-20241026083827509

image-20241026084449479

参考记录在这里

image-20241026084506190

image-20241026084702039

4.7.5 使用delete释放内存

image-20241026084912272

image-20241026090745374

image

delete释放ps指向的内存,但不会删除指针ps本身.

不能用delete释放声明变量所获得的内存,要配对使用delete和new,要delete你new出来的内存.

4.7.6 使用new来创建动态数组

个人感觉做了这么多,很多内容都可以不截图发上来,直接在原书的pdf里面编辑就好了,这样笔记又完整,自己也节省了时间,效果也好.

前面的内容就不管了,从这一节开始直接在原书的pdf里面编辑.

经过我笔记的原书的pdf的链接在这片博客下

https://hsuwindow.vip/cshsuwindowDIY/C/grammar/C++PrimerPlusNotesHsuwindowPdf/

后面的标题就不显示了,因为笔记都在原书的pdf里面

4.12复习题

char actor[30]

short betsie[100]

float chuck[13]

long double dipsea[64]

1
2
3
4
5
6
7
8
9
#include<array>

array<char, 30>actor

array<short, 100>betsie

array<float, 13>chuck

array<long double , 64>dipsea

int arr[5] = {1,3,5,7,9};

int arr[5] = {1,3,5,7,9};

int even = arr[0] + arr[4];

float ideas[30];

cout << ideas[1] << endl;

char str[] = “cheeseburger”;

string str = “Waldorf Salad”;

struct fish{

​ //string kinds;

​ char kind[30];

​ int weight;

​ double length;

};

struct fish{

​ //string kinds;

​ char kind[30];

​ int weight;

​ double length;

};

fish f = {“luyu”, 99, 50.2};

enum Response {No, Yes, Maybe};

double ted = 1.8;

double* pted = &ted;

cout << “ted = “ << *pted << endl;

float treacle[10] = {0};

float* p = treacle;或者float * p = &treacle[0];

cout << *p << endl;或者cout << p[0] << endl;

cout << *(p + 9) << endl;或者cout << p[9] << endl;

yong new

int n;

cout << “Please enter a integer: “;

cin >> n;

int *p = new int[n];

yong vector

incldue

int n;

cout << “Please enter a integer: “;

cin >> n;

vector arr[n];//这里写错了,这里很容易写成方括号

vector arr(n);//正确写法

image-20241027145657547

有效,打印字符串第一个字符’H’的地址,而不会打印字符串”Home of the jolly bytes”

struct fish{

​ //string kinds;

​ char kind[30];

​ int weight;

​ double length;

};

fish *pointff = new fish;

pointff->kind = “luyu”;

pointff->weight = 99;

pointff->length = 50.2;

cout << pointff->kind <<”,” << pointff->weight <<”,”<< pointff->length << endl;

cin.getline(address, 80);读取一行的输入,以回车符号作为判断的结束.

cin >>address;初始的时候忽略连续的空白字符,直到遇到非空白字符后读取,接着直到 再遇到空白字符(空格,回车,制表符)就会结束.事实上,会将最后遇到的空白字符留在输入序列里面

注释:

一开始我看到题干说混合输入数字和字符串的时候,我脑袋一时间懵了,不记得有讲过这个,那我就顺便复习一下.

image-20241027155042624

image-20241027151102547

image-20241027151210169

这本书的翻译没有那么好,感觉他这句混入输入数字和字符串的意思是说

前面输入的数字如果你按照习惯用cin >> year来读取的话,会留一个回车在输入缓冲区,接着你就算能注意到读取一行字符串用cin.getline(address, 80)也会有问题,就是留着的那个空格问题.

所以我们要在cin>>year后面还加一条语句, 那就是cin.get()或者cin.get(ch)

那里想不起来了就翻一下,记录一下,没时间大把大把的回看,只能遇到了或者发现自己忘记了再来看,然后重新几一边.

1
2
3
4
5
6
7
8
9
10
#include<iostream>
#include<vector>
#include<array>
#include<string>
const int size = 10;
int main(void){
std::vector<std::string> arr1(size);
std::array<std::string, size > arr2;
return 0;
}

4.13编程练习

作业如下

4.13编程练习

备注:

看到第二道题目的题干的时候我的大脑有懵了,我会看到程序清单4.4的时候感觉,第二个cin.getline(dessert, ArSize)会遇到第一个cin.getline(name, Arsize)留下来的回车符号,然后第二个就只能读取空字符串了.后来查看,发现是自己记错 了.

image-20241027154329402

cin.getline()以换行符作为输入的结尾,同时他会丢弃换行符.

cin.get()以换行符作为输入的结尾,同时他不会丢弃换行符,而是让换行符保留在输入序列中.

然后是从上面可得的cin的信息:

cin >>address;初始的时候忽略连续的空白字符,直到遇到非空白字符后读取连续的非空白字符,接着直到 再遇到空白字符(空格,回车,制表符)就会结束.事实上,会将最后遇到的空白字符留在输入序列里面

image-20241027154259890

就这样慢慢总结,挺好的.

备注2:

记忆什么时候用#Include

什么时候用#Include

的窍门.

你把#Include看成C风格的字符串,因此strcpy(),strcat()等等就在这个头文件里面

你把#Include看成C++风格的String类对象,因此string s;等等就在这个头文件里面.

备注3:

这个视频教程讲的练习题的第八题讲错了.他忽略了第八题最想考察你的内容.就是用cin.get()把输入序列里面的回车符拿出来.

我这里贴上两种结果.

1.没用cin.get()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>
#include <vector>
#include <array>
using namespace std;
struct Pizza
{
string corporation;
double diameter;
double weight;
};
int main(void)
{
Pizza *p = new Pizza;

cout << "Please enter pizza`s diameter: ";
cin >> p->diameter;
// cin.get(); // 为了把换行符给从输入序列里面拿出去
// 不然下面的getline()就读入空字符串了.
cout << "Please enter pizza`s corporation name: ";
getline(cin, p->corporation);
cout << "Please enter pizza`s weight: ";
cin >> p->weight;

cout << p->corporation << endl;
cout << p->diameter << endl;
cout << p->weight << endl;

return 0;
}

运行结果

image-20241027164342633

2.用了cin.get()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>
#include <vector>
#include <array>
using namespace std;
struct Pizza
{
string corporation;
double diameter;
double weight;
};
int main(void)
{
Pizza *p = new Pizza;

cout << "Please enter pizza`s diameter: ";
cin >> p->diameter;
cin.get(); // 为了把换行符给从输入序列里面拿出去
// 不然下面的getline()就读入空字符串了.
cout << "Please enter pizza`s corporation name: ";
getline(cin, p->corporation);
cout << "Please enter pizza`s weight: ";
cin >> p->weight;

cout << p->corporation << endl;
cout << p->diameter << endl;
cout << p->weight << endl;

return 0;
}

运行结果

image-20241027164442008

同样,你看到new的第一反应应该是有配套的delete,我上面的两个程序都没有delete,是大错误

备注4:

我好像理解为什么这个老师讲课的时候老师重复的输入一些操作了,因为这本书的编排顺序是循环和选择结构都在第四章后面,这个老师实在是严谨.

💡 有关C++PrimerPlus上的问题,欢迎您在底部评论区留言,一起交流~