Learning C++ primer plus

Hello everyone!现在由我来带大家进入编程语言C++的学习

第一节 进入C++

相信大家有一点C的基础的,以下是一些对初学者困惑的解答和建议:

  • 为什么要将头文件写到写到程序里边呢? 因为此时涉及到程序和外面世界的通信,将源代码文件和头文件组合成一个复合文件,编译的下一阶段需要该文件

  • 命名空间可以将代码封装到一个单元中,可以通过单元名称去同名代码的不同含义。using编译指令可以使得某个命名空间的所有名称都可以使用,其实这是一种偷懒的做法,在大型项目中会存在潜在的问题。可以通过 using std:: out; 来声明所需要的名称,之后就可以直接使用 out ,而不必加上 std:: 前缀。

  • endl可以去确保程序继续运行前刷新输出,而 \n 不可以保证。也就是说在有些系统中,可能输入信息后才有提示

  • C++代码风格:
    1.每条语句占一行
    2.每个函数段需要俩个大花括号包含,这俩花括号各占一行
    3.函数中语句都相对花括号进行缩进
    4.与函数名称相关的圆括号周围没有空白[1]

  • 为什么必须声明变量?因为不声明会存在潜在问题!如果不声明,错误的拼写了变量名,将在不知情的情况又创建了一个新的变量。

  • 函数如果写在 main 函数下面则需要在主函数体上面声明。C++不允许函数定义嵌套在另一个函数定义中,每个函数的创建是平等的。

    大部分情况下,构建程序的过程本质上是对规范调试的过程。

现在的互联网是浮躁的,导致现在的学生是浮躁的,都想一步登天。我建议是大家把那几个学科大课学好,把C语言学好,然后再去选择其他编程语言。一步一步的来,不要急。

最后给大家几个忠告来结束本小节吧:

1.多交流:不管你的技术多么硬,你都不可能一个人做完所有的事情,你要学会与别人合作,与别人交流。交流过程中,要注意交流技巧。学会尊重别人,但要不亢不卑。
2.多动手:熟能生巧,这是万能之理。我们干的是技术活,最能证明自己能力的就是干!不是扯淡!
3.多思考:不要做编码机器。
4.多总结:相同的问题不可能只出现一次,尤其是在我们这个行业。总结是为了你在以后更快的解决类似的问题,提高工作效率。
5.多分享:分享的更多,你会得到的更多,相信我。
6.多阅读:多聆听:不要仅限于技术,你要了解的不只是技术。同样的问题,听一听别人是怎么想的,怎么思考的,你会得到更多。
7.永远不要做拿来主义:没有人有义务帮你搞定问题,不要张口就要,给你你很幸运,不给你也不是别人的错。


第二节 处理数据

简单变量

首先我们要了解变量的属性:

  • 信息存在哪里
  • 要存储什么值
  • 存储何种信息的类型

变量名

命名规则如下:

1.在名称中只能使用字母字符、数字和下划线
2.名称的第一个字符不能是数字
3.区分大小写字符
4.不能将C++关键字作名称
5.以一个下划线开头的名称被保留给实现[2],用作全局标识符;以俩个下划线或者大写字母打头的名称被保留给实现使用。
6.对名称长度没有限制,名称中所有字符都要有意义

驼峰命名法 vs 下划线命名法
驼峰命名法(Camel Case):
  • 驼峰命名法分为小驼峰命名法和大驼峰命名法。
  • 小驼峰命名法:变量名首字母小写,后续每个单词的首字母大写,不使用下划线。例如:myVariable, totalAmount。
  • 大驼峰命名法:所有单词的首字母都大写,不使用下划线。通常用于类名或类型名。例如:MyClass, TotalAmount。
  • 优点:可读性较好,易于阅读和理解长名称,特别适合在面向对象的编程中表示类和对象。
  • 缺点:名称长度较长,某些情况下可读性可能稍差。
下划线命名法(Snake Case):
  • 下划线命名法使用下划线字符作为单词之间的分隔符。
  • 所有字母小写,单词间用下划线连接。例如:my_variable, total_amount。
  • 优点:较短的名称,可读性较好,适合在函数、变量等场景下使用。
  • 缺点:某些情况下可能会显得杂乱,不便于快速阅读长名称。
选择命名风考量:
  • 有时候,项目的编码规范或团队约定可能会明确指定使用一种命名风格。
  • 不同的编程语言可能对命名风格有偏好或规定。
  • 命名的可读性是关键,无论选择驼峰命名法还是下划线命名法,都应确保名称清晰、简洁和易于理解。
  • 在整个代码库中保持一致的命名风格非常重要,以提高可维护性和团队协作效率。

选定一种一致的命名风格并坚持使用。

运算符 sizeof

sizeof (数据类型) / sizeof 变量
都可以指出其占用内存大小

初始化

变量初始化的意义在于表达式的值都是已知的。如果不对其进行初始化,变量的值将是他创建之前相应内存单元存放的值
有俩种初始化方法:

int res = 100;
int res  (100);

还有一种初始化方法是用 "{}"来初始化,可以忽略等号,这个以后讨论。
这俩种初始化方法执行的结果都是一样的

浮点数的优缺点

优点 缺点
浮点数 1.表示整数之间的值 2.有缩放因子,表示的范围比整数更大 1.运算速度比整数慢 2.结果精度降低

const限定符

在数据类型前加const和数据类型后加const是等价的。
const int Month = 12;//在变量定义前加关键字const,修饰该变量为常量,不可修改

const 类型的变量必须在定义时进行初始化,之后不能对const型的变量赋值

也就是将变量当成常量使用,数值不可修改

运算符优先级

这个比较简单可以自行了解 运算符优先级

数据强制转换

我要介绍的是以{}初始化时进行的转换,和普通强转的区别在于前者对转换的要求更加严格,即初始化时不允许缩窄。比如 将 double 类型转换为 int

数据类型auto

auto可以推断变量的类型,是关键字。但是使用场景太过简单可能会让人误入歧途。具体在使用STL库中的类型时,auto 的优势才能显示出来。

复合类型

C-字符串

char dog[8] = {'a','s','d','d','f','g','h','h'} //char 数组
char cat[8] = {'s','t','u','d','e','n','t','\0'} //字符串
char res[ ] = "data structure" //字符串
char name[15] = "Mr.blacksmith" //字符串
在程序cin读取时,不能接受空格,若输入data structure,则在第一次只接收data,同时将structure放入输入队列,作为第二次输入内容。

面向行的输入

  • getline()函数
    • cin.getline(存储输入行数组的名称,读取的字符数)
  • get()函数
    • 参数与上面的getline()函数相同
    • get不在读取并丢弃换行符,而是将其留在输入队列。若俩次连续调用get函数,第一次调用后换行符留在输入队列,第二次调用时看到第一次字符便是换行符,会认为没有人和可读取的内容
    • 若俩次连续调用get函数,则中间可用无参数的get函数即cin.get(),来接受换行符
    • 因为cin.get(name,Arsize)返回的是cin对象,所以cin.get(name1,Arsize1).get()cin.getline(name1,Arsize1).getline(name2,Arsize2)的使用方法是允许的

sizeof和strlen
前者返回char数组大小,后者返回数组中字符的数量

string类

string str1 = "Everything will be fine"
string str2 {Everything will be fine}
二者初始化效果相同

string与C-字符串

  • 字符串长度
    • string————str.size()
    • char 数组————strlen.(数组名)
  • 字符串拼接
    • string
      str3 = str1 + str2;
    • char 数组
      strcpy(str3,str1);//拷贝
      strcat(str3,str2);//追加

结构体、共用体和枚举

结构体

结构体是一种自定义的复合数据类型,可将不同的数据类型组合成为一个整体,关键字struct

共用体

共用体也叫联合体,使几个不同类型的变量共占一段内存(相互覆盖),其所占内存是至少能够容纳最大的成员变量所需的空间,关键字union

枚举

枚举是一种创建符号常量的方式,可以代替const,还允许定义新类型,默认初始值为1~n.若将中间一个元素初始化时赋值为value,前面元素的值不变,后面的元素值++。对于枚举,只定义了赋值运算,算数运算是不允许的,比如

band = blue;  //valid
band = 2000;  //invalid,2000 not an enumerator
band = orange + red;  //not valid,but a little tricky

指针

警告

一定要在指针解引用之前,将指针初始化为一个确定的、适当的地址

(p++)、++p、++p和(p)++的区别

知道你们懒得看代码和推导过程,给你们推荐这个 指针优先级


结构体变量用.去访问成员变量,结构体指针用 ->来访问成员变量


new

分配内存通用格式

typeName * pointer_name = new typeName ;//new返回的是分配好内存后内存的首地址

int* pt = new int ;

int higgens;
int* pn = &higgens;

第一种只能通过该指针访问,第二种还可以通过名称higgens来访问该int。

new创建数组

  • 静态创建
const int N = 1000;
int* res = new int [N];
  • 动态创建
int size;
cin >> size;
int* res = new int [size];

delete

释放内存

int* p = new int;
···
delete p;

释放数组

int* p = new int [10];
···
delete [] p;

用delete删除new创建的指针内存,不要删除自主设置的指针内存。

数组的替代品

vector

变长数组
创建语法:
vector<typeName> res;
由此设置vector的类型和大小
二维vector

// 初始化一个 二维的matrix, 行M,列N,且值为0
vector<vector<int>> matrix(M,vector<int>(N))

array

静态分配的数组,效率和数组一样且更安全
创建语法:
array<typeName,n_elem>
这里与vector不同的是,n_elem不能是变量。
可以对vector和array使用成员函数at()

vector<int> res;
res[3] = 100;
res.at(3) = 100;

使用成员函数at()的好处是可以捕获非法索引,降低意外越界的概率,代价是运行时间更长。

循环与逻辑运算符

基于范围的for循环

对于数组或者容器类(vector、array)的每个元素执行相同的操作

for(auto x : a)  //将a中每个元素单独取出来赋值给x
std::cout << x << endl;

文件尾条件

  • while (cin >>a) + 输入ctrl+z
  • while((scanf"%d,%d",&m,&n)!=EOF)
  • while(~cin.fail())

switch

switch通用格式

switch (integer-expression)
{
	case label1 : statement (s)
	case label2 : statement (s)
	···
	default : statement (s)
}

break 和 continue

break直接跳出循环;满足一定条件后continue后的语句在当次循环中不会被执行

逻辑运算符

image

区别一下|、||、&、&&

  • | 和 || 都表示'或',但是后者在运算时若满足第一个条件,第二个条件将不再计算,直接返回true
  • &和&&都表示'与',但是后者在运算时若不满足第一个条件,第二个条件将不再计算,直接返回false

简单文件I/O

  • 包含头文件fstream。
  • 创建一个fstream对象。
  • 将该fstream对象和某个文件关联起来
  • 像使用cin / cout那样使用该对象

以下是一些文件的打开方式和解释

打开方式 解释
ios::in 打开文件进行读操作,这种方式可避免删除现存文件的内容
ios::out 打开文件进行写操作,这是默认模式
ios::ate 打开一个已有的输入或输出文件并查找到文件尾开始
ios::app 在文件尾追加方式写文件
ios::binary 指定文件以二进制方式打开,默认为文本方式
ios::trunc 如文件存在,将其长度截断为零并清除原有内容,如果文件存在先删除,再创建

  1. 空格、回车和制表符统称为空白。 ↩︎

  2. 编译器及其使用的资源 ↩︎

posted @ 2023-07-19 17:16  blacksmith贾  阅读(78)  评论(0)    收藏  举报