C++基础句法
三种基本程序结构
● 顺序、分支和循环
switch和if比较
● 使用场景
1.switch只能支持常量固定值相等的判断
2.if还可以判断区间范围
3.用switch能做的,用if都能做,但是反过来不行。
● 性能比较
1.分支少时候差别不大,分支多时,switch性能高
2.if开始处几个分支高效,之后递减
3.switch所有的case速度几乎一样。
循环语句
● C++提供三种玄幻语句:while do while 和 for
#include <iostream> using namespace std; int main() { // TODO: 1+2+3+4...+100 // while语句 int sum = 0; int index = 1; while (index <= 100) { sum += index; index += 1; } //cout << sum << endl; // for语句 //index = 1; sum = 0; for (index = 1; index <= 100; ++index) { sum += index; } //cout << sum << endl; // do-while语句 sum = 0; index = 1; do { sum += index; index += 1; } while (index <= 100); //cout << sum << endl; return 0; }
自定义结构-枚举
● 使用#define和const创建符号常量,使用enum不仅能够创建符号常量,还能定义新的数据类型:
● 枚举类型enum的声明和使用 如:enum wT{Monday = 5, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
● 使用细节
○ 枚举值不可以做左值
○ 非枚举类型不能赋值给枚举变量
○ 枚举变量可以赋值给非枚举变量
#include <iostream> using namespace std; int main() { enum wT{Monday = 5, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}; // 声明wT类型 wT weekday; weekday = Monday; weekday = Tuesday; //weekday = 1; // 不能直接给int值,只能赋值成wT定义好的类型值 cout << weekday << endl; //Monday = 0; // 类型值不能做左值 int a = Wednesday; cout << a << endl; return 0; }
自定义结构 - 结构体和联合体
● 使用struct定义结构体
● 使用union定义联合体
● 结构体的尺寸:
● 结构体对齐原则:缺省对齐原则
○ 32位CPU:
char : 任何地址
short: 偶数地址
int 4的整数倍地址
double 4的整数倍地址
● 修改默认编译选项
○ msvc #pragma pack(1)
○ g++ __attribute__(aligned(n)) __attribute__(__packed__)
#pragma pack(1) #include <string.h> #include <iostream> using namespace std; int main() { union Score { double ds; char level; }; struct Student { char name[6]; int age; Score s; }; //cout << sizeof(Score) << endl; // 8 Student s1; strcpy_s(s1.name, "lili"); s1.age = 16; s1.s.ds = 95.5; s1.s.level = 'A'; cout << sizeof(Student) << endl; // 24 18 return 0; }
函数
● 一个C++程序是由若干个源程序文件构成,而一个源程序是由若干个函数组成,函数将一段逻辑封装起来以便复用。
● 从用户角度看,函数分成:
○ 库函数 标准函数,由C++提供 比如strcpy_s等
○ 用户自定义函数:需要用户定义后使用。
函数的组成部分:
1.返回类型:一个函数可以返回一个值
2.函数名称:函数的实际名称,函数名和参数列表一起构成了函数签名;
3.参数:参数列表包括函数参数的类型、顺序、数量。参数时可选的,也就是说函数可能不包含命令参数;
函数重载overload与函数签名
int test(int a); int test(double a); int test(int a, double d);
指向函数的指针和返回指针的函数
● 每个函数都占用一段内存单元,它们有一个起始地址,指向函数入口地址的指针称为函数指针
例子: int (*p)(int);
● 注意与返回指针的函数的区别 int *p(int);
#include <iostream> using namespace std; int MaxValue(int x, int y) { return (x > y) ? x : y; } int MinValue(int x, int y) { return (x < y) ? x : y; } int Add(int x, int y) { return x+y; } bool ProcessNum(int x, int y, int(*p)(int a, int b)) { cout << p(x, y) << endl; return true; } int main() { int x = 10, y = 20; cout << ProcessNum(x, y, MaxValue) << endl; cout << ProcessNum(x, y, MinValue) << endl; cout << ProcessNum(x, y, Add) << endl; return 0; }
命名空间
using namespace std;
内联函数
如果一个函数是内联的,那么编译时候,编译器会把函数的代码副本放在每个调用函数的地方。
inline int max(int x, int y) { return x>y?x:y; }
内联函数内部不能处理太复杂的逻辑,编译器有时会有自己的优化策略,所以内联不一定有用。
递归
使用准则:
1.基准情形:无需递归就能解出
2.不断推进:每一次递归必须使求解状况接近基准情况方向推进
3.设计法则:假设所有的递归调用都能运行
4.合成效益法则:求解一个问题的同一个实例时,切勿在不同递归函数中做重复性工作。
递归的缺陷:
● 递归是一种重要的编程思想
1.很多重要的算法都包含递归思想
2.递归最大的缺陷
1.空间上需要大量的栈空间
2.时间上可能需要大量的重复运算
● 递归的优化:
1.尾递归:所有的递归形式的调用都出现在函数的末尾
2.使用循环代替
3.使用动态规划,空间换时间
#include <assert.h> #include <iostream> int g_a[1000]; // 全局的数组,记录斐波那契数列的前1000个值 // 斐波那契数列的实现 // 方法一:递归 int Fib(int n) { if (n == 0) { return 0; } else if (n == 1) { return 1; } else { return Fib(n - 1) + Fib(n - 2); } } // 尾递归 int Fib2(int n, int ret0, int ret1) { if (n == 0) { return ret0; } else if (n == 1) { return ret1; } return Fib2(n - 1, ret1, ret0 + ret1); } // 循环 int Fib3(int n) { if (n < 2) { return n; } int n0 = 0, n1 = 1; int temp; for (int i = 2; i <= n; i++) { temp = n0; n0 = n1; n1 = temp + n1; } return n1; } // 动态规划 int Fib4(int n) { //assert(n >= 0); g_a[0] = 0; g_a[1] = 1; for (int i = 2; i <= n; i++) { if (g_a[i] == 0) { g_a[i] = g_a[i - 1] + g_a[i - 2]; } } return g_a[n]; } int main() { //Fib(10); //std::cout << Fib2(10, 0, 1); //std::cout << Fib(20) << std::endl; //std::cout << Fib2(20, 0, 1) << std::endl; //std::cout << Fib3(20) << std::endl; //std::cout << Fib4(20) << std::endl; assert(Fib(10) == 55); assert(Fib2(10, 0, 1) == 55); assert(Fib3(10) == 55); assert(Fib4(10) == 55); return 0; }