目录
想说的话:打算学好C++,计划从C++ Primer Plus开始。在学习过程中遇到我不了解的或者感兴趣的,会花大篇幅来做笔记;对于很熟悉的内容在书上过一遍后,不会记录在本文中。这也算是对本科所学的一次系统的复习。
Stay hungry ,stay foolish.
第一章 预备知识
泛型编程:generic programming
第二章 开始学习C++
C语言的传统是头文件使用扩展名.h,C++则没有扩展名。
1、名称空间
以厂商为例,名称空间指代不同的厂商,这样将多个厂商的代码组合时不会互相混淆。
Micro::func(1);
Macro::func(1);
也可以用using编译指令,using namespace Micro,使得Micro名称空间中的所有名称可用。名称空间管理技术以后再表。
2、定义变量
C++的做法是尽可能在首次使用变量前声明它。(为什么要声明变量?防止拼写错误而使用了错误的变量。。)
3、赋值语句
- 等号表达式的值为左值,从右往左计算:b=a=1;即可以连续赋值。
- 逗号表达式的值为右值,从左往右计算:int i = 0; int n = (i += 2, i++); n结果为2。
第三章 处理数据
1、变量名
以两个下划线或下划线和大写字母开头的名称被保留给编译器,以一个下划线开头的名称也被保留,用作全局标识符。如_time_stop、_Dount虽然可以通过编译但不建议。
2、整形
规定整形长度为:2B <= short <= 4B <= int <= long <= 8B <=long long
对于有符号整数,假设长为n位(bit),则其表示范围为 [-2^(n-1),2^(n-1)-1]。指数减一是因为留一位给符号位,结果减一是因为最高位为n-2。如signed short 范围为-2^15到2^15-1(-32768~32767) 。无符号数的表示范围扩大一倍即可。
如何判断溢出?逆向运算再比较:
int tadd_ok(int x,int y){ int sum=x+y; return (sum-x==y)&&(sum-y==x); }
cout<<hex cout<<oct分别输出16进制、8进制整数。
3、浮点数
浮点数表示带小数的数字,一部分表示值,另一部分用于对值进行放大和缩小。
float的存储方式如下图所示:
double的存储方式为:
第四章 复合类型
1、字符串
a) 概念
在C++中,单引号表示字符常量,如 ‘S’;双引号表示字符串常量,如 “S”。
字符常量:‘S’ 只是83的另一种写法,本质是ASCII码
字符串常量:“S” 其实是由字符S和字符\0 组成的字符串。实际上,“S”表示的是字符串所在的内存地址。、
b) 字符串输入
cin使用空白(空格、制表符和换行符)来确定字符串结束的位置,所以用cin输入“aaa bbb”时,第一个字符串接收aaa,第二个接收bbb。要解决这个问题可以用getline() 和 get() 。cin.get() 经常用来接收输入流中未被接收的换行符。
int main(){
//每次读取一行带空格的字符串
using namespace std;
const int size = 20;
char name[size];
char dessert1[size];
char dessert2[size];
cout << "enter name\n";
cin.getline(name, size);//通过换行符来确定行尾,存储时用空字符替换换行符
cout << "enter dessert1\n";
cin.get(dessert1, size).get();//通过换行符确定行尾,保留换行符,所以要再调用get()取出换行符
cout << "enter dessert2\n";
cin.get(dessert2, size).get();
cout << "end";
return 0;
}
2、String类简介
a)相关函数
参见 C语言字符串函数探幽
b)原始字符串
将原始字符串(Raw)输出,不用转义符。如下:
cout<<R"(Jim "King" Tutt use "\n" instead of endl.) " << ' \n' ;
cout<<R"+* ("(Who wouldn‘ t?)" , she whispered.) +*" <<endl;
3、指针
一个指针的一生:
int main() {
/*1、声明指针。指针值均为0xcccccccc。造了三个仓库管理员,他们管理哪个仓库未知*/
int *point_c,*point_cpp,*p,val;
/*2、定义|初始化指针。指针都有值了,但是他们指向的int变量均默认为-842150451。
仓库管理员知道自己管理哪个仓库了*/
point_c = (int *)malloc(sizeof(int *));
point_cpp = new int;
/*3、使用指针。指针指向的变量有一个明确的值了。管理员们开始搬货进去*/
*point_c = 10;
*point_cpp = 11;
/*4、释放内存。
指针指向的变量被清空,C指针指向的值为-572662307,C++指针也存在,但指向的值无法读取
他们变成野指针了(迷途指针):告诉管理员,你不再管理任何仓库了*/
free(point_c);
delete(point_cpp);
/*5、清空指针,指针值变为0
把管理员删除掉了。人没了。*/
point_c = NULL;
point_cpp = NULL;
return 0;
}
- delete 只能释放new得来的地址,free同理。
- 不能释放同一个内存块两次,但可以释放空指针。
- 不释放将导致内存泄漏。
4、C++数据存储
a)自动存储
自动变量(局部变量)是在函数内部定义的常规变量,其作用域为包含它的代码块。执行到这个函数时,相关变量入栈,函数结束时,变量出栈,编译器自动释放这些变量。
b)静态存储
第九章将详解。要么在函数外定义它,要么用static。
c)动态存储
有一个称为堆的内存空间给程序员使用。可以在一个函数内分配内存,也可以在另一个函数里释放它。
5、内存空间
第五章 循环和关系表达式
1、延时循环
#include <ctime>
void my_delay(float secs) {
clock_t delay = secs * CLOCKS_PER_SEC;//乘以系统时间得到秒数
std::cout << "\a";//振铃
clock_t start = clock();
while (clock() - start < delay)//流逝的时间小于指定时间,就循环消耗cpu
;
std::cout << "\a";//时间到
}
2、基于范围的for循环
double prices[5] = {1.1, 1.2, 1.3, 1.4, 1.5};
for (double &x : prices)
x *= 0.8;
3、cin读取之文件尾EOF
int main() {
char ch;
int count=0;
cin.get(ch);
while (cin.fail()==false)//检测到EOF后,cin把eofbit和failbit都设置为1,cin.fail()为true
{
cout << ch;
count++;
cin.get(ch);//调试发现,键盘键入字符后回车,cin就从输入流读取,读完了就需要再次键入
}
while (cin.get(ch)) { ; }//这样也行
//注意在Unix使用Ctrl+D模拟EOF 而在Windows使用Ctrl+Z或回车
return 0;
}
第六章 分支语句和逻辑控制符
1、字符函数库cctype
函数名称 |
返回值 |
isalnum() |
如果参数是字母数字,即字母或者数字,函数返回true |
isalpha() |
如果参数是字母,函数返回true |
isblank() |
如果参数是水平制表符或空格,函数返回true |
iscntrl() |
如果参数是控制字符,函数返回true |
isdigit() |
如果参数是数字(0-9),函数返回true |
isgraph() |
如果参数是除空格之外的打印字符,函数返回true |
islower() |
如果参数是小写字母,函数返回true |
isprint() |
如果参数是打印字符(包括空格),函数返回true |
ispunct() |
如果参数是标点符号,函数返回true |
isspace() |
如果参数是标准空白字符,如空格、换行符、水平或垂直制表符,函数返回true |
isupper() |
如果参数是大写字母,函数返回true |
isxdigit() |
如果参数是十六进制数字,即0-9、a-f、A-F,函数返回true |
tolower() |
如果参数是大写字符,返回其小写,否则返回该参数 |
toupper() |
如果参数是小写字符,返回其大写,否则返回该参数 |
2、简单文件的输入输出
一切皆文件。
#include <iostream>
#include <cstdlib>
#include <fstream>
const int SIZE = 60;
int main() {
using namespace std;
ifstream in_file;
ofstream out_file;
out_file.open(R"(C:\Users\Trafalgar\Desktop\a.txt)");//文件不存在则新建,存在则截断(丢弃原内容)
double value = 3.2;
int cnt = 10;
while (cnt--)
{
out_file << value++<<" ";
}
out_file << "\nthis is a test\n";
out_file.close();
in_file.open(R"(C:\Users\Trafalgar\Desktop\a.txt)");
if (!in_file.is_open()) {
cout << "could not open file\n";
exit(EXIT_FAILURE);
}
double sum = 0.0;
in_file >> value;//读
while (in_file.good()) {
sum += value;
in_file >> value;
}
if (in_file.eof()) {
cout << "EOF\n";
}
else if (in_file.fail()) {
cout << "由于数据不匹配无法读取\n";
}
else cout << "未知错误\n";
cout << "sum=" << sum;
in_file.close();
return 0;
}
总结下:
- 引入头文件fstream;
- 创建ifstream对象/ofstream对象,假设是object;
- object.open();
- object >>或者<<(读写文件):就像cin一样来操作;
- object.close()。