Base
关于标准IO的补充。cin
使用空白来确定结束位置,这意味着cin
每次只能读取单个单位的字串,并且会把空白符留在输入缓冲区。
#include <iostream> // IO流头文件
#include <string>
using namespace std; // 标准命名空间
int main()
{
/*数据类型*/
int i = 10;
float f = 3.14f;
bool flag = true;
char c = 'A'; // 单引号表字符
char chs[5] = { 'a','b','c' }; // 字符数组,会被看作是无结束符的字串
string s = "abc"; // 双引号表字串,隐含'\0'结束符
int arr[4] = { 0,1,2,3 }; // 数组名作用:统计数组长度,获取数组首地址
cout << sizeof(arr)/sizeof(arr[0]) << endl; // 静态数组的长度
/* 标准IO */
float r = 0; float pi = 3.14;
cout << "enter the r:"; // cout: 标准输出
cin >> r; // cin: 标准输入
cout << pi * r * r << endl; // endl: 插入换行符并刷新缓冲区
/*判断*/
if (1 + 1 == 2)
;
else
;
char tmp = 'b';
switch (tmp)
{
case 'a':
break;
case 'b':
break;
default:
break;
}
/*三目运算符*/
int a = 0; int b = 1;
cout << (a < b ? 'a' : 'b') << endl;
(a < b ? a : b) = 9; // 三目运算符左值时,C++会取地址
cout << a;
/*循环*/
int nums[3] = { 0,1,2 };
for (int i = 0; i < 3; i++)
cout << nums[i] << ' ';
cout << endl;
return 0;
}
其他数据类型
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <unordered_map>
#include <algorithm>
using namespace std;
int main(void)
{
string s1, s2;
s1 = "prefix";
s1.size();
s1[0] = 'A'; // string类支持直接修改
getline(cin, s2);
cout << s1 + s2 << endl; // 拼接
if (s1 < s2); // 基于ASCII的比较
vector<int> v1 = { 0,1,2 };
v1.push_back(3);
int tmp=v1.back(); // 取最后一个元素
v1.pop_back(); // 删除最后一个元素
sort(v1.begin(), v1.end());
for (int i = 0; i < v1.size(); i++)
cout << v1[i] << endl;
set<int> s;
s.insert(1); s.insert(2); s.insert(2);
s.erase(1);
if (s.find(2) != s.end()); // 存在性判断
unordered_map<char, int> m;
m['a'] = 1;
m['z'] = 26;
if (m.find('b') != m.end()); // 存在性判断
return 0;
}
指针与引用
指针指向内存地址,引用相当于别名,有着类似指针的性质。引用必须初始化,且不可更改。实际上引用本质上就是指针常量。
int i = 1;
int* p = &i; // 整形指针p指向整形变量i的地址
int& r_i = i; // 创建i的引用
int* const r = &i; // 引用的本质,指针常量
*p += 1; // p指向的地址的值+1
r_i += 1; // 引用+1,即原始数据+1
cout << i << ' ' << p << endl;
int func(const int& x) {
// 引用的常见使用场景:使用常量引用实现只读参数
return x * x;
}
p += 1; // p值+1,即地址偏移一个单位
cout << i << ' ' << p << endl;
int arr[3] = { 0,1,2 };
int* ap = arr; // 数组名即数组首元素的地址
cout << arr << ' ' << ap << endl;
cout << *(ap + 1) << ' ' << arr[1] << endl;
类型转换与常量
*
用作指针创建时,指针指向的类型永远在其左侧且是完整类型,如int*
表示指针指向int
型;而const
关键字永远限定其右侧的类型或变量名,如const int
表示常量整形;当两者混用时,记住修饰规则即可,如const int*
表示指向常量整形的指针,int* const p
表示指向int
的指针,且指针p
是常量。
int a = 1;
float b = 0.1;
bool t = true;
bool f = false;
a + b == 1.1; // int->float自动提升
b + f == 0.1; // true=1, flase=0
const int m = 0;
const int* p_i = &m; // 指向const int的指针
m += 1; *p_i += 1; // error,常量无法被修改
p_i += 1; // 指针可以修改
int i = 1;
int* const p_c = &i; // 指向int的指针且p_c为常量
p_c += 1; // error,指针常量无法被修改
i += 1; *p_c += 1; // 变量可以修改
const int* const p = &m; // 指向const int的指针且指针p为常量
p += 1; *p += 1; // error,常量无法修改,指针常量也无法修改
结构体
#include <iostream>
using namespace std;
struct MyStruct
{
int i;
float f;
char c;
bool b;
};
int main()
{
MyStruct s = { 1,0.5,'a',true };
MyStruct* p = &s;
/*结构体成员的访问方式*/
cout << p->i << ' ' << p->f << ' ' << p->c << ' ' << p->b << endl;
// 结构体数据类型对齐
cout << sizeof(p->i) << '\t' << sizeof(p->f) << '\t'
<< sizeof(p->c) << '\t' << sizeof(p->b) << '\t' << sizeof(s) << endl;
return 0;
}
函数
#include <iostream>
using namespace std;
bool isEven(const int num)
{
return num % 2 == 0;
}
void plusone(int* p_num)
{
*p_num += 1;
}
/*函数重载,同名函数支持不同的输入*/
void f(int num)
{
cout << "f_int" << endl;
}
void f(double num)
{
cout << "f_double" << endl;
}
/*递归*/
int fact(int num = 1) // C++支持默认参数
{
if (num < 2)
return num;
else
return num * fact(num - 1);
}
int main()
{
int num = 1;
if (isEven(num))
cout << "is" << endl;
else
cout << "not" << endl;
plusone(&num);
cout << num << endl;
f(1); f(1.0);
cout << fact(3) << endl;
return 0;
}
类与对象
访问控制的三种权限:
public
:公有,外部可访问;protected
:保护,外部不可访问,继承可访问;private
:私有,外部不可访问,继承不可访问。
下面示例定义一个自定义类C
。
在C.h
里声明类:
class C
{
const double pi=3.14;
double r;
public:
C(double r); // 构造函数
C(const C& c); // 拷贝构造函数,复制对象
~C(); // 析构函数
void setR(double x);
double getS(void);
C& plus(void); // 半径增加1
};
在C.cpp
里实现类:
#include "C.h"
/*需要用作用域解析符来标识所属的类*/
C::C(double x) {
this->r = x; // this指针指向的是对象自身,相当于Python中的self
}
C::C(const C& c) {
this->r = c.r;
}
C::~C() {}
void C::setR(double x) {
this->r = x;
}
double C::getS(void) {
return this->pi * this->r * this->r;
}
/*类方法可以支持链式调用,需要返回自身的引用*/
C& C::plus(void) {
this->r += 1;
return *this;
}
主程序main.cpp
:
#include<iostream>
#include "C.h"
using namespace std;
int main(void) {
C c0 = C(0);
C c1 = C(c0);
c1.setR(1);
cout << c1.getS() << endl;
c1.plus().plus();
cout << c1.getS() << endl;
return 0;
}
C++中类与结构体是相似类型,唯一区别在于struct默认public权限而class默认private权限。C++中保留结构体的设计仅仅是为了兼容C语言。
继承
#include<iostream>
#include<string>
using namespace std;
class BasePage {
protected:
string header = "HTML Header";
string footer = "HTML Footer";
public:
void show(void) {
cout << this->header << "\t"
<< this->footer << endl;
}
};
class DetailPage :public BasePage {
string info = "Detail Info";
public:
void show(void) { // 子类会重写父类的同名函数
cout << this->header << "\t"
<< this->info << "\t"
<< this->footer << endl;
}
};
int main(void) {
DetailPage p1;
p1.show();
return 0;
}
文件IO
#include<iostream>
#include<fstream>
using namespace std;
int main(void) {
fstream fd_w("tmp.txt", ios::out | ios::binary);
if (fd_w.is_open()) {
char info[] = "hello\n";
fd_w.write(info, sizeof(info));
}
fd_w.close();
fstream fd_r("tmp.txt", ios::in | ios::binary);
char buf[512] = { 0 };
if (fd_r.is_open()) {
while (!fd_r.eof()) {
fd_r.read(buf, 512);
cout << buf;
}
}
fd_r.close();
return 0;
}