C/C++语言
C/C++基础知识
程序
编写程序
C ++ 面向对象 的程序设计
C ++程序可由一个或多个源文件组成
每个源文件包含一些函数、类和外部变量或对象的定义,一个程序中有且仅有一个文件中包含一个main()函数,其余文件中可包含函数的定义
程序运行的步骤:编辑(.cpp / .h)-编译( .obj )-链接(. exe )-运行-输出
编程思想
编程核心是人的思维
先构建 正确的数学模型,并进行 优化,最终将其转化为计算机语言
编程数学基础
数学名词 | 解释 |
---|---|
因数 | 因数是指整数a/整数b(b≠0) 的商为整数,则b是a的因数 |
质数(素数) | 在大于1的整数中,除了1和它本身以外不再有其他因数的整数 |
合数 | 在大于1的整数中除了能被1和本身整除外,还能被其他数整除的数 |
注意 | 0,1既不是质数也不是合数 |
(a和b的最小公倍数) * (a和b的最大公约数)= a * b
将两个整数分解成质因数的乘积
共同部分之积即为最大公约数
不同部分之积乘相同部分之积即为最小公倍数
知识点
符号 | 作用 |
---|---|
EOF | 判断是否到文件尾(结束输入) |
= | 赋值运算符 |
== | 判断是否等于运算符 |
注意区别“=”与“==”
注意点
序号 | 注意点 |
---|---|
1 | 不可使用未初始化的变量(系统将为变量随机赋值或赋值为0) |
2 | 定义变量时取名需有意义 |
3 | 编程时需注意格式,保证程序可读性 |
4 | 在写代码时需考虑算法的优化,优化代码 |
6 | 不可将程序设置为 死循环,否则会导致 运行超时 |
7 | 注意临界值的取舍即是否需要 = |
变量和基本类型
基本内置类型
算术类型
long long int
int型数据除以一个数之后仅保留整数部分,舍去小数部分,不是四舍五入
double类型的输入不能使用%f进行输入,得用%lf才能正常得到a的值,而在输出double类型时却可以用%f,这是因为printf只认识双精度,遇到%f自动将float型的参数转换成double型。
double a;
scanf("%lf",&a);
printf("%f",a)、printf("%lf",a);都可用于输出double 型数据
\t 的意思是 横向跳到下一制表符位置(水平制表符占8列)
%e,%f默认输出时,小数点后保留六位,%e的指数部分最少占4位
%m.n中的m代表将要输出的数的列数,其中也包括小数点,n代表小数点后面输出的位数。m<0则右侧补空格,m>0则左侧补空格;小数点也占一位,若最后数值长度大于m,则按实际数值输出,小数位保留n位。
字符
字符串读写时C语言可用s%,缺点是s%不读空格
大写字母+32=小写字母
字符的读取
cin 不读取空格
scanf 读取空格
字符的值
给字符变量赋值时除了NULL,其他都得加’’,否则会报错
字符型可以作为条件(转化为布尔型),而字符串型却不可以
NULL的ASCII码值为0,将其赋给字符变量时,不加单引号,加单引号则赋给字符变量的值为L,即为NULL最后一个字母
变量
extern 表明该变量在别的地方已经声明过了,在这里要使用那个变量
变量类型 | 生存期 | 内存空间的分批 |
---|---|---|
全局变量 | 静态生存期 | 内存空间从程序开始执行时就进行分配,直到程序结束才收回它们的空间 |
局部变量、函数的参数 | 自动生存期 | 内存空间在程序执行到定义它们的复合语句(包括函数体)时才分配,当定义它们的复合语句执行结束时,它们的空间将被收回 |
动态变量 | 动态生存期 | 内存空间在程序中显式地用new操作或malloc库函数分配、用delete操作或free库函数收回 |
局部变量的默认存储类为auto
局部变量的储存类型声明标识符
存储类型标识符 | 作用 |
---|---|
auto | 使局部变量具有自动生存期 |
static | 使局部变量具有静态生存期,它只在函数第一次调用时进行初始化,以后调用中不再进行初始化,它的值为上一次函数调用结束时的值。 |
register | 使局部变量也具有自动生存期,由编译程序根据CPU寄存器的使用情况来决定是否存放在寄存器中。 |
对变量内存分配有时具有随机性
复合类型
引用
- 引用只是与对象进行绑定,引用并非对象,只是为一个已经存在的对象起的另一个名字
引用没有内存地址
- 对引用的定义:type &p=n;
type 是一种数据类型,必须与n的类型相匹配
对引用定义时不可省略&
引用在定义时必须初始化(因为其绑定对象不可改变)
- 除了绑定常量的引用,其绑定的对象的可以与其类型不匹配之外,其他引用要求与绑定对象类型严格配对
对常量的引用
- 初始化常量时允许用任意表达式作为初始值
- 允许为常量引用绑定非常量的对象,字面值,甚至是一个一般表达式
- 不可通过改变常量引用的值来改变绑定对象的值
注意:
当常量引用绑定的是与其类型不同的表达式时,会将表达式的结果转化为引用的类型,并将转化后的结果存储在临时量中,使引用与临时量绑定,此时原值改变不会再影响引用的值
指针
- 指针用于存储地址,其指向的地址可以改变,其所占内存用于存储地址值
- 对指针的定义或赋值:type *p=&n;p=&m(使得指针与变量关联);
type 一种数据类型,必须与n,m的类型相匹配
对指针定义或赋值时不可省略&(不可把int变量直接赋给指针)
- 除了指向常量的指针,其指向的对象的可以与其类型不匹配之外,其他指针要求与指向的变量类型严格配对
常量指针(
普通指针(与普通指针一样,必须严格遵循类型匹配)):指向非常量的常量指针,其指向的对象的值可以改变,但是其指向的地址不可改变
- 指向数组的指针
*(a+i)=a[i],a=&a[0] (数组首元素下标为0)
#include <iostream>
using namespace std;
int main()
{
int a[3]={0,2,4};
cout << *(a+1) << endl;
//a+1表示a的下一个地址的值
//对指针使用解引用符访问指针指向的对象的值
cout << a << endl;
//a为数组的首指针,存储数组的首地址
return 0;
}
指向常量的指针
- 指向常量的指针,初始化时指向的对象可以是 数据类型相同 的 非常量对象
- 不可通过指向常量的指针改变其指向的对象的值(若指向的对象不是常量则可以通过其他方式改变对象的值)
- 指向常量的指针所指向的地址可以改变
字符串、向量和数组
数组
a表示数组的首地址,*a表示的是数组第一个元素的值,相当于a[0]
定义数组时a[n],n所代表的是数组中元素的个数
但是使用数组中某个元素时数组的下标从0开始
表达式
表达式的值分为1(真)/0(假)
条件运算符
形式: 条件?表达式1:表达式2
使用方法
- 赋值(赋值时使用条件运算符)
#include <iostream>
using namespace std;
int main()
{
int a=1,b=2,c;
c=a>b?a:b;//把a、b中的较大值赋值给c
cout << c << endl;
return 0;
}
运行结果:2
- 执行一定的操作(将条件运算符作为选择执行语句的工具)
#include <iostream>
using namespace std;
int main()
{
int a=1,b=2,c;
a>b? cout << a << endl:cout << b << endl;//输出a、b中的较大者
return 0;
}
运行结果:2
语句
简单语句
scanf("%字符类型",&n);
变量前必须加&取地址符
putchar(变量);输出字符
变量=getchar();输入字符
printf(“此处内容只是作为字符常量输出 ”);
cout<<“此处内容只是作为字符常量输出”;
无其他作用
赋值语句
a = b = c 从右往左进行赋值
#include <iostream>
using namespace std;
int main()
{
int a = 1, b = 2, c = 3;
a = b = c;
cout << "a=" << a << endl
<< "b=" << a << endl
<< "c=" << c << endl;
return 0;
}
不可将值赋给常量
常量的值不可以改变
赋值语句类型转换:将右侧数据类型转换为左侧变量的类型
条件语句
if()语句
用字符作为if语句的条件
#include <iostream>
using namespace std;
int main()
{
char c=' ';
cout << "空格的ASCII码是"<<int(c) << endl;
if(c) cout << "空格的ASCII不是0" << endl;
if(' ')cout << "空格的ASCII不是0" << endl;
cout <<"字符0的ASCII码是"<< int('0') << endl;
if('0')cout << "字符0的ASCII码不是0" << endl;
return 0;
}
程序运行结果:
空格的ASCII码是32
空格的ASCII不是0
空格的ASCII不是0
字符0的ASCII码是48
字符0的ASCII码不是0
当整型/字符作为if()语句的条件时
注意:
整型转布尔型方法:整型非0则布尔值为1,整型为0则布尔值为0
字符型转布尔型方法:先将字符型转化为整型(对应的ASCII码值),然后再转化为布尔型
字符 | if()之后语句可否执行 | ASCII | 布尔值 |
---|---|---|---|
’ '(空格) | 可执行 (不执行else后的语句) | 32 | 1 |
‘0’ | 可执行(不执行else后的语句) | 48 | 1 |
0 | 不可执行(执行else后的语句) | 非字符 | 0 |
NULL | 不可执行 (执行else后的语句) | 0 | 0 |
switch()语句
书写方式一
switch()
{
case a: case b: 语句1;
}
书写方式二
switch()
{
case a:
case b: 语句1;
}
switch执行与case匹配后的所有语句
需要考虑是否要加break语句跳出循环
两种方式效果相同(类似于if()else语句的锯齿模型与一般模型)
switch 语句可嵌套使用
迭代语句
语句 | continue作用 |
---|---|
while{…} 、do{…} while; | 使程序转到循环条件的判断 |
for(表达式1;表达式2;表达式3;) | 使程序转到表达式3 |
for()语句表达式1只执行一次,表达式3在下一次循环前执行
函数
函数基础
函数的调用其实就是代码封装
return语句作用 |
---|
结束程序 |
返回值 (空函数无返回值,直接写return;) |
函数返回值
值传递:不改变实参的值
地址传递或引用传递:改变实参的值
参数类型 | 性质 |
---|---|
实参 | |
形参 |
递归函数
递归函数的变量间互不影响,只是同名的变量,但作用域不同,本质上无任何关联
#include <iostream>
using namespace std;
void F(int n, char x, char y, char z)
{
if (n==1)
printf("1 %c -> %c\n", x, z);
else//只要n!=1就会进行递归操作,直到最终n=1
{
F(n-1, x, z, y);
printf("%d %c -> %c\n", n, x, z);
F(n-1, y, x, z);
}
}
int main()
{
F(3,'A','B','C');
return 0;
}
程序执行结果:
1 A -> C
2 A -> B
1 C -> B
3 A -> C
1 B -> A
2 B -> C
1 A -> C
逐层递归,直至最后不再继续进行递归