6. 基本句法 1.基本结构
顺序语句
分支语句
循环语句
1. if, switch 语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <iostream> using namespace std;bool isLeapYear (unsigned int year) { if ((year % 4 == 0 && year % 100 !=0 ) || (year % 400 == 0 )){ return true ; } else { return false ; } } typedef enum _COLOR { RED, GREEN, BLUE, UNKNOWN }color; int main () { cout << isLeapYear (2000 ) << endl; cout << isLeapYear (2001 ) << endl; cout << isLeapYear (2020 ) << endl; color color0; color0 = BLUE; if (color0==RED){cout << "red" << endl;} else if (color0==GREEN){cout << "green" << endl;} else if (color0==BLUE){cout << "blue" << endl;} else {cout << "unknown" << endl;} color color1; color1 = GREEN; switch (color1) { case RED: cout << "red" << endl; break ; case GREEN: cout << "green" << endl; break ; case BLUE: cout << "blue" << endl; break ; default : cout << "unknown" << endl; break ; } }
if 和switch 比较 :
使用场景
switch 只支持常量值固定相等的分支判断
if还可用于区间判断
用switch能做的,用if都能做,反过来则不行
性能比较
分支较少是,差别不是很多;分支多是,switch性能较高
if开始处几个分支效率很高,之后递减
switch所有case的速度几乎一样
2. 自定义结构——枚举enum
使用#define
和 const
创建符号常量,使用enum
不仅能够创建符号常量,还能定义新的数据类型。
1 2 3 4 5 6 7 8 9 10 int main () { enum wT {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}; wT weekday; weekday = Monday; weekday = Wednesday; cout << weekday << endl; return 0 ; }
使用细节:
枚举值不可以做左值
非枚举变量不可以赋值给枚举变量
枚举变量可以赋值给非枚举变量
3. 自定义结构——结构体与联合体 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #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; cout << sizeof (Student) << endl; }
结构体数据对齐问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 struct s1 { char x; int z; short y; }; struct s2 { char x; short y; int z; }; struct s3 { char x; short y; double z; }; cout << sizeof (s1) << endl; cout << sizeof (s2) << endl; cout << sizeof (s3) << endl;
对于32位CPU:
char
: 任何地址
short
:偶数地址
int
: 4的整数倍地址
double
: 8的整数倍地址
1 2 3 4 5 6 7 Student stu; memcpy (stu.name, "lili" , 6 );stu.age = 16 ; stu.s.ds = 95.5 ; stu.s.level = 'A' ; cout << stu.name << endl;
4. 循环语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> using namespace std;int main () { int sum = 0 , index = 1 ; while (index <= 100 ){ sum += index; index ++; } cout << sum << endl; sum = 0 ; for (int index = 1 ; index <= 100 ; ++index){ sum += index; } cout << sum << endl; sum = 0 , index = 1 ; do { sum += index; index += 1 ; }while (index <= 100 ); cout << sum << endl; return 0 ; }
Q:输出所有形如aabb的四位完全平方数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <iostream> #include <math.h> using namespace std;int main () { int num; double m; for (int a = 0 ; a < 10 ; ++a) { for (int b = 0 ; b < 10 ; ++b) { num = a * 1100 + b * 11 ; m = sqrt (num); if ((m - int (m)) < 0.000001 ){ cout << num << endl; cout << m << endl; } } } return 0 ; } int main () { int n = 0 ; int high, low; for (int index = 0 ;; ++index) { n = index * index; if (n < 1000 ){ continue ; } if (n > 9999 ){ break ; } high = n / 100 ; low = n % 100 ; if ((high / 10 == high % 10 ) && (low / 10 == low % 10 )){ cout << n << endl; cout << index << endl; } } return 0 ; } ___________________________ 7744 88
5. 函数 一个C++程序是由若干个源程序文件构成,而一个源程序是由若干个函数构成,函数将一段逻辑封装起来,便于复用
从用户角度看,可以分为:
库函数: 标准函数, 由c++系统提供
用户自定义函数:需要用户定义后使用
从组成角度看:
返回类型: 一个函数可以返回一个值
函数名称:函数名和参数列表一起构成了函数签名
参数: 参数列表包括函数参数的类型、顺序、数量。参数是可选的,函数可以不包含参数。
1. overload 函数重载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int test (int a) { return a; } int test (double b) { return int (b); } int test (int a, double b) { return a + b; } int main () { int (*p)(int ); p = test; int result = (*p)(1 ); cout << result << endl; result = test (2.0 ); cout << result << endl; result = test (1 , 2.0 ); cout << result << endl; return 0 ; }
2. 指数函数的指针与返回指针的函数 每一个函数都占用一段内存单元,它们有一个起始地址,指向函数入口地址的指针称为函数指针。
一般形式: 数据类型 (*指针变量名)(参数表);
int (*p)(int)
区别:
int (*p)(int);
是指针,指向一个函数入口地址
int* p(int);
是函数,返回值是一个指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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; }
3. 命名空间
命名空间,可以作为附加信息来区分不同库中名称的函数、类、变量等,命名空间即定义了上下文。本质上,命名空间就是定义了一个范围。
关键字:using 和namespace。 std::name
4. 函数体 函数主体包含一组定义函数执行任务的语句。
5.内联函数 inline function
如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方
引入内联函数的目的是为了解决程序中函数调用的效率问题
注意:内联函数内部不能有太复杂的逻辑,编译器有时会有自己的优化策略,所以内联不一定起作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <iostream> inline int Fib (int n) { if ( n == 0 ){ return 0 ; } else if ( n == 1 ) { return 1 ; } else { return Fib (n-1 ) + Fib (n-2 ); } } int main () { int n = 10 ; std::cout << Fib (n) << std::endl; return 0 ; }
6. 数学归纳法 递归的四个基本法则:
基准情形:无须递归就能解出;
不断推进:每一次递归调用都必须是求解状况朝接近基准情形的方向推进
设计法则:假设所有递归调用都能运行
合成效益法则——compound interest rule:求解一个问题的同一个实例是,切勿在不同的递归调用中做重复性的工作。
递归recursion的缺陷:
递归是一种重要的编程思想:
很多重要的算法都包含递归的思想
递归最大的缺陷:
空间删需要开辟大量的栈空间1
时间上可能需要有大量重复运算
递归的优化
尾递归: 所有递归形式的调用都出现在函数的末尾
使用循环替代
使用动态规划:时间换空间
分别使用递归,循环,尾递归、动态规划来实现斐波那契数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #include <iostream> #include <assert.h> int g_a[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 Fibloop (int n) { if (n < 2 ){ return n; } int n0=0 , n1=1 ; int tmp; for (int i = 2 ; i<=n; i++){ tmp = n0; n0 = n1; n1 = n0 + tmp; } return n1; } int Fiblast (int n, int ret0, int ret1) { if (n==0 ) {return 0 ;} else if (n == 1 ) { return ret1; } return Fiblast (n-1 , ret1, ret0 + ret1); } int Fibd (int n) { 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 () { int n = 10 ; std::cout << Fib (n) << std::endl; std::cout << Fibloop (n) << std::endl; std::cout << Fiblast (n, 0 , 1 ) << std::endl; std::cout << Fibd (n) << std::endl; assert (Fib (10 )==55 ); return 0 ; }