Skip to main content

学不完的概念

Hello world

// 我是注释
#include <iostream>
int main(void) {
using namespace std;
cout << "Hello world!\n";
return 0;
}
  • 注释:由前缀 // 标识
  • 预处理编译指令: #include
    • 数据的流式输入与输头文件:iostream
  • 函数头:int main()
  • 编译指令:using namespace
    • 名称空间:std
    • 因为使用 iostream 而不是 iostream.h,因此需要使用名称空间编译指令
    • 编译指令可以放在函数的定义之前,也可以放在特定的函数定义中
  • 函数体:用 { } 括起
  • 显示消息的语句:cout
  • 结束函数的返回语句:return
    • 返回值是给操作系统的,操作系统可以使用程序的返回值
    • 通常约定,退出值为0意味着程序运行成功,非0意味着存在问题
  • 在C++中,不能省略分号

按需引入名称

#include <iostream>
int main(void) {
using std::cout;
cout << "Hello world!\n";
return 0;
}

声明变量

#include <iostream>
int main(void) {
using namespace std;
int carrots;
carrots = 25;
carrots = carrots -1;
cout << "Now I have " << carrots << " carrots" << endl;
return 0;
}

监听键盘输入

#include <iostream>
int main(void) {
using namespace std;
int carrots;
cin >> carrots;
carrots = carrots -1;
cout << "Now I have " << carrots << " carrots" << endl;
return 0;
}

使用库函数

#include <iostream>
#include <cmath>
int main(void) {
using namespace std;
double area;
double side;
cin >> area;
side = sqrt(area);
cout << "Now I have " << side << " side" << endl;
return 0;
}

使用自定义函数

#include <iostream>
double simon(double);

int main(void) {
using namespace std;
double area;
double side;
cin >> area;
side = simon(area);
cout << "Now I have " << side << " side" << endl;
return 0;
}
double simon(double n){
using namespace std;
return n/2;
}
  • 第一个 simon 是函数原型,用于声明类型
  • 第二个 simon 是函数体

预处理编译指令define(全局搜索替换)

#include <iostream>
#define Pai 3.14
int main(void) {
using namespace std;
cout << "Pai is " << Pai << endl;
return 0;
}

限定符const(定义常量)

#include <iostream>
int main(void) {
using namespace std;
const int Months = 12;
cout << "Mounths is " << Months << endl;
return 0;
}

运算符sizeof(返回类型或数据对象的长度)

#include <iostream>
int main(void) {
using namespace std;
cout << "int is " << sizeof (int) << " bytes" << endl;
return 0;
}

数组声明

#include <iostream>
int main(void) {
using namespace std;
short yamcosts[3] = {20,30,5};
yamcosts[2] = 31;
cout << "this value is " << yamcosts[2] << endl;
return 0;
}
  • 初始化数组时,可省略等号
  • 不在大括号内包含任何东西,这将把所有元素都设置为零
  • 数组初始化禁止缩窄转换

getline每次读取一行字符串输入

#include <iostream>
int main(void) {
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.getline(name,ArSize);
cout << "Enter your dessert:\n";
cin.getline(dessert,ArSize);
cout << "I have some delicious " << dessert << " for you," << name << ".\n";
return 0;
}

get每次读取一行字符串输入(推荐)

#include <iostream>
int main(void) {
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.get(name,ArSize).get();
cout << "Enter your dessert:\n";
cin.get(dessert,ArSize).get();
cout << "I have some delicious " << dessert << " for you," << name << ".\n";
return 0;
}

结构

#include <iostream>
struct inflatable
{
char name[20];
float volume;
double price;
};
int main(void) {
using namespace std;
inflatable guest =
{
"Glorious Gloria",
3.00,
2.00
};
cout << guest.name << " pay " << guest.volume * guest.price << endl;
return 0;
}
  • 结构初始化禁止缩窄转换

结构数组

#include <iostream>
struct inflatable
{
char name[20];
float volume;
double price;
};
int main(void) {
using namespace std;
inflatable guests[2] =
{
{"Bambi",0.5,21.99},
{"Godzilla",1.00,2.00}
};
cout << guests[0].name << " pay " << guests[0].volume * guests[0].price << endl;
cout << guests[1].name << " pay " << guests[1].volume * guests[1].price << endl;
return 0;
}

枚举

#include <iostream>
int main(void) {
using namespace std;
enum spectrum {red,orange,yellow,grren,blue,violet,indigo,ultraviolet};
cout << red << endl;
return 0;
}
  • 默认情况下,第一个枚举量的值为0,第二个枚举量的值为1,依次类推
  • 可以手动设置枚举量的值

常量变量的地址

#include <iostream>
int main(void) {
using namespace std;
int donuts = 6;
cout << &donuts << endl;
return 0;
}

指针

#include <iostream>
int main(void) {
using namespace std;
int updates = 6;
int *p_updates;
p_updates = &updates;
*p_updates = *p_updates + 1;
cout << p_updates << endl;
cout << *p_updates << endl;
return 0;
}
  • p_updates是指针(地址)
  • *p_updates是 int 类型
  • 对每个指针变量名,都需要使用一个*

自定义指针地址

#include <iostream>
int main(void) {
using namespace std;
int *pt;
pt = (int *) 0xB8000000;
cout << pt << endl;
return 0;
}

new分配指针内存

#include <iostream>
int main(void) {
using namespace std;
int *pt = new int;
*pt = 1001;
cout << pt << endl;
return 0;
}
  • 区别:变量的值存储在栈(stack)中,而new从堆(heap)或自由存储区(free store)中分配内存

delete释放指针内存

#include <iostream>
int main(void) {
using namespace std;
int *pt = new int;
short *ps = new short [500];
delete pt;
delete [] ps;
return 0;
}
  • 不要使用delete来释放不是new分配的内存
  • 不要使用delete释放同一个内存块两次
  • 对空指针使用delete是安全的

使用模板类数组

#include <iostream>
#include <array>
int main(void) {
using namespace std;
array<int, 5> ai;
array<double, 2> ad = {1.2, 2.1};
return 0;
}

打印字符串地址

#include <iostream>
int main(void) {
using namespace std;
cout << (int *) "Hello world" << endl;
return 0;
}

监听输入赋值给结构

#include <iostream>
struct fish
{
char kind[20];
int weight;
float length;
};
int main(void) {
using namespace std;
fish *pole = new fish;
cout << "Enter kind of fish:";
cin >> pole->kind;
cout << (*pole).kind << endl;
return 0;
}

for循环

#include <iostream>
int main(void) {
using namespace std;
int i;
for(i=0;i<5;i++){
cout << i << endl;
}
return 0;
}

for循环字母

#include <iostream>
int main(void) {
using namespace std;
char ch;
for(ch='a';ch<='z';ch++){
cout << ch << endl;
}
return 0;
}

while循环

#include <iostream>
int main(void) {
using namespace std;
char name[20] = "michael";
int i = 0;
while(name[i]!='\0'){
cout << name[i] << endl;
i++;
}
return 0;
}

do while循环

#include <iostream>
int main(void) {
using namespace std;
char name[20] = "michael";
int i = 0;
do{
cout << name[i] << endl;
i++;
}while(name[i]!='\0');
return 0;
}
  • for、while是输入条件循环,
  • do while是退出条件循环,至少执行一次

基于范围的循环

#include <iostream>
int main(void) {
using namespace std;
double prices[3] = {1.22,3.44,5.66};
for(double x:prices){
cout << x << endl;
};
return 0;
}

循环文本输入

#include <iostream>
int main(void) {
using namespace std;
char ch;
int count = 0;
cout << "Enter characters:\n";
cin >> ch;
while(ch!='#'){
++count;
cin >> ch;
}
cout << count << " characters read" << endl;
return 0;
}
  • cin >> ch 会忽略空格、换行符、制表符,而 cin.get(ch) 不会

  • cin >> ch 只读取一个字符,而 cin.get(ch) 可以读取一个或多个字符

  • cin >> ch 读取一个字符后,将剩余的字符留在输入缓冲区中,下一次读取时将从缓冲区中读取;而 cin.get(ch) 读取一个字符后,将把换行符和其他字符都从输入缓冲区中读取走

  • 如果需要读取一个单词或一个数字,可以使用 cin

  • 如果需要读取一个包含空格的字符串或一整行的文本,可以使用 cin.get()

EOF(Ctrl+Z)结束循环文本输入

#include <iostream>
int main(void) {
using namespace std;
char ch;
int count = 0;
cout << "Enter characters:\n";
cin.get(ch);
while(!cin.fail()){
++count;
cin.get(ch);
}
cout << count << " characters read" << endl;
return 0;
}

初始化二维数组

#include <iostream>
int main(void) {
using namespace std;
int maxtemp4[4][3] = {
{96,100,88},
{96,100,88},
{96,100,88},
{96,100,88},
};
return 0;
}

文件写入

#include <iostream>
#include <fstream>
int main(void) {
using namespace std;
ofstream outFile;
outFile.open("carinfo.txt");
if (outFile.is_open()) {
outFile << "文件写入";
outFile.close();
} else {
cout << "Unable to open file" << endl;
}
return 0;
}

文件读取

#include <iostream>
#include <fstream>
int main(void) {
using namespace std;
ifstream inFile;
char filename [50];
string value;
cout << "Enter filename:";
cin.getline(filename,50);
inFile.open(filename);
if (!inFile.is_open()) {
cout << "Unable to open file" << endl;
}
while(getline(inFile, value)){
cout << value << endl;
}
inFile.close();
return 0;
}

大小写转换

#include <iostream>
#include <cctype>
int main(void) {
using namespace std;
cout << "Enter some text(end with @):" << endl;
char ch;
while(cin.get(ch) && ch!='@'){
if(isalpha(ch)){
if(isupper(ch)){
ch = tolower(ch);
}
else if(islower(ch)){
ch = toupper(ch);
}
}
cout << ch;
}
cout << endl;
return 0;
}
  • isalpha用来判断一个字符是否为字母

四个菜单选项

#include <iostream>
int main(void) {
using namespace std;
char choice;
bool isValid = false;
while(!isValid){
cout << "Please enter one of the following choice:" << endl;
cout << "A) Option 1" << endl;
cout << "B) Option 2" << endl;
cout << "C) Option 3" << endl;
cout << "D) Option 4" << endl;
cin >> choice;
choice = toupper(choice);
switch(choice){
case 'A':
cout << "You chose Option 1" << endl;
isValid = true;
break;
case 'B':
cout << "You chose Option 2" << endl;
isValid = true;
break;
case 'C':
cout << "You chose Option 3" << endl;
isValid = true;
break;
case 'D':
cout << "You chose Option 4" << endl;
isValid = true;
break;
default:
cout << "Invalid choice" << endl;
break;
}
}
return 0;
}

创建类型别名

#include <iostream>
int main(void) {
using namespace std;
typedef double real;
real num = 0.0001;
cout << num << endl;
return 0;
}

替换字符串中的指定字符

#include <iostream>
int replace(char *str,char c1,char c2);
int replace(char *str,char c1,char c2){
int count = 0;
while(*str){
if(*str == c1){
*str = c2;
count++;
}
str++;
}
return count;
};
int main(void) {
using namespace std;
char str[] = "abcdef";
char c1 = 'a';
char c2 = 'q';
int count = replace(str,c1,c2);
cout << count << endl;
cout << str << endl;
return 0;
}

函数递归

#include <iostream>
int factorial(int n);
// 阶乘函数,使用递归实现
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
int main(void) {
using namespace std;
int n;
cout << "请输入一个整数: ";
cin >> n;
cout << n << " 的阶乘为: " << factorial(n) << endl;
return 0;
}

创建引用变量

#include <iostream>
int main(void) {
using namespace std;
int rats;
int &rodents = rats;
cout << &rodents << endl;
return 0;
}

函数模板

#include <iostream>
template<typename T>
T max2(T x, T y) {
return (x > y) ? x : y;
};
int main(void) {
using namespace std;
int a = 10, b = 20;
int max_int = max2(a, b);
cout << max_int << endl;
return 0;
}

函数接收结构参数

#include <iostream>
struct box{
char maker[40];
float height;
float width;
float length;
float volume;
};
void show_box(const box &n);
void show_box(const box &n){
using namespace std;
cout << n.maker << endl;
cout << n.height << endl;
cout << n.width << endl;
cout << n.length << endl;
cout << n.volume << endl;
};
int main(void) {
using namespace std;
box box1 = {
"box1",
1.00,
2.00,
3.00,
6.00
};
show_box(box1);
return 0;
}

decltype类型推导

#include <iostream>
int main(void) {
using namespace std;
int a = 1;
decltype(a + 1) b = 2; // 推断表达式 a + 1 的类型,并将 b 声明为该类型
cout << b << endl;
return 0;
}

使用多个名称空间

#include <iostream>
namespace ns1 {
void func() {
std::cout << "Hello from ns1\n";
}
};
namespace ns2 {
void func() {
std::cout << "Hello from ns2\n";
}
};
int main(void) {
using ns1::func;
func(); // 调用 ns1::func()
ns2::func(); // 调用 ns2::func()
return 0;
};

类的创建和使用

#include <iostream>
using namespace std;
class Person {
private:
string id;
public:
string name;
int age;
void sayHello() const {
cout << "Hello, my name is " << name << " and I am " << age << " years old." << endl;
}
};
int main(void) {
Person p1;
p1.name = "Alice";
p1.age = 25;
p1.sayHello();

Person p2;
p2.name = "Bob";
p2.age = 30;
p2.sayHello();

return 0;
}
  • const 成员函数可以被视为只读函数
  • 成员函数可以隐式访问调用对象的成员,而无需使用成员运算符

类的构造函数

#include <iostream>
#include <string>
using namespace std;
class Person {
private:
string name;
public:
Person(); // 构造函数
Person(const char *n); // 构造函数
};
Person::Person() {
name = "default name";
cout << name << endl;
};
Person::Person(const char *n) {
name = n;
cout << name << endl;
};
int main(void) {
Person p1;
Person p2("mike");
return 0;
}
  • 构造函数用于在对象被创建时初始化成员变量、分配内存等
  • 构造函数的名称必须与类名相同
  • 构造函数在对象创建时自动被调用
    • p1调用的是默认构造函数,不需要括号
    • p2提供了构造函数参数,必须使用括号

类的析构函数

#include <iostream>
using namespace std;
class Person {
private:
string name;
public:
Person(); // 构造函数
~Person(); // 析构函数
};
Person::Person() {
name = "default name";
cout << name << endl;
};
Person::~Person() {
cout << "destruct " << name << endl;
}
int main(void) {
Person p1;
return 0;
}
  • 析构函数通常用于释放分配的内存、关闭文件等
    • 一个类中使用了动态分配内存的成员变量,通常需要使用析构函数
  • 当一个对象被删除或离开其作用域时,会自动调用其析构函数
  • 析构函数名与类名相同,但前面加上一个波浪线(~)作为前缀
  • 析构函数没有返回值,没有参数
  • 析构函数不能被重载,一个类只能有一个析构函数
  • 析构函数可以被继承,如果派生类没有自己的析构函数,则会自动调用基类的析构函数

this指针

#include <iostream>
using namespace std;
class Person {
private:
string name;
public:
void setName(const char *n){
this->name = n;
cout << this->name << endl;
}
};
int main(void) {
Person p1;
p1.setName("mike");
return 0;
}
  • this 指针通常用于解决同名成员变量和局部变量之间的歧义
  • 在静态成员函数中,无法使用 this 指针
  • 在非静态成员函数中,编译器会隐式地将当前对象的地址作为 this 指针传递进去
  • this是对象的地址,*this是对象本身

创建类的对象数组

#include <iostream>
using namespace std;
class Person {
private:
string name;
public:
Person(); // 构造函数
};
Person::Person() {
name = "default name";
cout << name << endl;
};
int main(void) {
Person arr[5];
return 0;
}

运算符重载

#include <iostream>
using namespace std;
class Complex {
public:
double real;
Complex operator+(const Complex &c) {
Complex result;
result.real = real * c.real;
return result;
}
};
int main(void) {
Complex c1;
Complex c2;
c1.real = 2;
c2.real = 3;
Complex c3 = c1 + c2;
cout << c3.real << endl;
return 0;
}

友元函数

#include <iostream>
#include <string>
using namespace std;
class Person {
private:
string name;
public:
Person(); // 构造函数
friend void printName(Person p); // 友元函数
};
Person::Person() {
name = "default name";
};
void printName(Person p) {
cout << p.name << endl;
};
int main(void) {
Person p1;
printName(p1);
return 0;
}
  • 友元函数不是类的组成部分,但能访问类的私有成员(仅友元能访问)
  • 过度使用友元函数会降低代码的安全性和可维护性

生成随机数

#include <iostream>
#include <cstdlib>
#include <ctime>
int main(void) {
using namespace std;
srand(time(NULL)); // 以当前系统时间作为起始种子
int random_num = rand() % 6 + 1; // 生成1到6之间的随机数
cout << random_num << endl;;
return 0;
}

类型转换

#include <iostream>
#include <cmath>
using namespace std;
class Vector {
private:
double x, y, z;
public:
Vector(double x_, double y_, double z_){
x = x_;
y = y_;
z = z_;
};
operator double() const {
return sqrt(x * x + y * y + z * z);
}
};
int main() {
Vector v(1.0, 2.0, 3.0);
int length = v;
cout << "The length of vector v is " << length << endl;
return 0;
}

虚函数

#include <iostream>
using namespace std;
class Animal {
public:
virtual void speak() {
cout << "Animal is speaking" << endl;
}
};
class Dog : public Animal {
public:
void speak() override {
cout << "Dog is barking" <<std::endl;
}
};
int main(void) {
Animal* dog = new Dog();
dog->speak(); // 输出 Dog is barking
return 0;
}
  • 通过在基类中声明为虚函数,然后在派生类中重新定义,这样,当指针或引用引用到派生类对象时,调用的是派生类中的函数
  • 虚函数是多态的一种体现

标识不能被派生类覆盖

#include <iostream>
using namespace std;
class Animal final {
public:
virtual void speak() final {
cout << "Animal is speaking" << endl;
}
};
class Dog : public Animal {
public:
void speak() override {
cout << "Dog is barking" <<std::endl;
}
};
int main(void) {
Animal* dog = new Dog();
dog->speak();
return 0;
}
  • 当一个类被声明为 final 时,它不能被其他类继承
  • 当一个虚函数被声明为 final 时,它不能被派生类覆盖