helloworld
//导入系统输入输出头文件 iostream
#include <iostream>
//使用标准命名空间 std
using namespace std;
int main() {
//将 Hello, World! 打印在屏幕上,并且进行换行
cout << "Hello, World!" << endl;
return 0;
}
其中:
-
Include不属于c++函数所以没有;头文件可以参考这篇博客: 头文件不可以定义,只声明函数和变量
-
using namespace可以为命名空间规范确定的名字。防止重复命名的功能模块,可能大型项目里会用到,期待。
其中使用namespace时,.h的头文件是用户自己命名的头文件,与此不同的是标准库文件 使用标准库的时候可以不用namespace。
也可以using具体的命名空间里的东西
多文件编译的时候使用#pragma once可以防止重复调用
.cpp最后变成.exe以及.out
第一部分是把include的东西全部复制进来,叫做编译预处理,生成.c文件
第二部分是把cpp翻译成汇编语言,叫做编译,生成.s
第三部分是把汇编语言翻译成二进制文件,生成.o或者.obj文件
第四部分是将其他第三方编译好的程序链接起来,生成.exe或者.o文件,链接也分动态链接和静态链接
因为本质上C++是C语言加了一些封装的实现,实现了面向对象的特性。
- 不同于python,有且仅有一个
main()函数,程序在运行时会自动调用main()函数。 - 双斜杠
"//"一直表示注释内容一直到行末。
变量和常量
变量背景
- 内存中每个基本存储单元可以存放一个字节的数据
- 一个字节byte存储8个比特bit
- 内存单元地址唯一,16进制数表示
变量使用
- 数据类型 变量名
- 一个变量名唯一对应一个空间
变量命名规则:
- 字母数字和下划线,而且区分大小写,W和w不是一个。
- 数字不可以在首字母。
- 关键字也就是语言特定功能的字母不可以表示变量名,因此需要确定关键字具体,参考资料
- 关键字和函数名最好能够体现功能模块的具体。
- 变量在初始化时应该根据数据类型进行赋值,否则将会发生错误.
python VS C++
与python不同的是需要先定义类型并且赋值
另一个不同是需要每行后面加;
常量和变量之间的关系
每个内存盒子可以存贮数据的地方叫做变量 那么存储的数据就是字面量,表示固定值。
- 整数字面量没有小数点和指数部分。其中十进制和八进制和十六进制。
- 浮点字面量表示小数,可以直接是小数点的数,或者10为底数的幂数。其中
eE都可以表示e或E的左侧必须要有数字e或E的右侧为幂次的数值,必须为整数- 小数可以等价表示为:
6.6E-1 => 0.66,30.0e0 => 30.0,0.01415926E3 => 14.15
- 字符字面量
使用单引号,
'mmm' - 转义符字面量
- 也是使用单引号,
'\n'而且需要是右划线,不同于注释使用/左划线 - 所有字符都采用ASCII编码,共有128个字符。每个字符都对应着一个
0~127之间的整数
- 也是使用单引号,
5. 字符串字面量""
-
使用双引号,里面也可以包含转义字符。
-
字符串除了存储所包含的字符外,还额外包含一个结束标志
'\0''\0':结束符;ASCII编码对应数值为0的字符
一次尝试
c++
#include<iostream>
using namespace std;
int main() {
// TODO 输出三行内容,每行为4个*和一个换行符
cout << "****" << endl;
cout << "****" << endl;
cout << "****" << endl;
//两种方式打印不需要添加额外的引号。
// cout << "****\n";
// cout << "****\n";
return 0;
}
- 常量字符量
const int或者int const都可以,且此时就需要对常量进行初始化了,后来的程序也不会改变此值。- 符号常量命名时参照Google 开源项目风格指南,以 “k” 开头,大小写混合
数据类型:
- 原来基本类型就是整数浮点数这种,复合类型就是数组字符串这种带有数据结构的数据类型。
数值整数类型
- 整数类型分为数值整数类型和字符类型。
-
数值整数用来表示没有小数部分的数字。
-
数值整数可以按照占用内存大小分为
short、int、long以及long long这四种,占用内存越大的类型能表示的数值范围就更大。 -
同时又可以按照是否表示负值分为有符号版本和无符号版本
-
字符类型则专门用来存储计算机中的基本符号:英文字母、数字以及标点等。
-
short-2byte-16bit -
int- 4byte - 32bit -
long-至少4byte>=int,一般是4byte -
long long=long*2 -
一个字节8bit可以表示256个整数。
-
-
- 无符号只能表示正数,有符号为默认版本。也就是使用了一个Bit表示符号也就是表示的数字变小了
- 默认状态下
short等四个整数类型都是符号类型,这使得它们能够表示的最大数值减小了一半左右。 - 在确定变量的数值不会是负数的情况下,我们可以利用
unsigned关键字,加在原有数据类型之前,创建无符号的整数类型。
- 默认状态下
字符整数类型
字符其实就是整数对应ASCII,声明char 后初始化可以赋值字符也可以赋值数字
// 用字符常量初始化一个 char 类型 char size_1 = 'L';
// 用整数常量初始化一个 char 类型,字符L的ASCII编码值为76 char size_2 = 76;
浮点数
- 可以表示小数,也可以表示数值大的可以用幂级数表示的大的数字。
- 表示float/double/long double/精度不同:有效位数和指数范围(幂次大小)。
-
有效位数用来描述浮点数值的刻画精确程度。
例如:3.14的有效位数是3位,3.1415926的有效位数是8位。 3.14与3.140000有效位数一样,其中0表示占位符。
-
float类型通常占用4个字节,有效位数为6位 -
double类型占用的空间是float类型的两倍,即8个字节,有效位数为15位 -
long double类型一般占用16个字节的空间`
-
c++四舍五入使用的是就近一位不是所有位数
输入输出:
c中使用printf()函数和scanf()函数进行格式化的输出输入。C++语言兼容C语言中的基本语句语法。
1. 库文件和命名空间
-
格式化的意义是按指定的格式输入输出值,就是两个函数关键字的最末一个字母
f(format)。 -
标准化输入输出数据库:cstdio,而且使用标准命名空间std。好记的方法就是c-std-io。
-
#include <头文件>,这是编译预处理。预处理指令include意思是找到后面跟随的文件,并且加载文件内容到程序中。在编译预处理之后,源代码文件将和头文件组合起来,在编译的下一阶段使用。 -
命名空间是C++中的一项特性,目的是让大型程序在组合多个厂商的代码时,便于管理重复命名的功能模块。也就是处理陕西苹果和安徽苹果的命名空间。
2. 输出的格式
printf(格式字符串,待打印项)数量要等于格式化字符串中待填充的空的数量,可以是变量或者常量,也可以是表达式。
-
输出也可以加入修饰符具体使用如下:
3. 输入的格式:
-
程序将键盘获取的字符构成的字符串转换成对应整数类型的数值。 将输入的字符串转换成指定的数据类型 与
printf()函数不同,scanf()函数中的地址项是变量对应的内存地址,用来装载对应的输入数据。 -
使用
scanf()函数读取基本变量类型的值,在变量名前加上一个&;使用scanf()函数将字符串读到字符数组中,则不要使用&
c++中输入输出
-
标准函数库
iostream中提供了输入输出(I/O)功能。需要使用预处理指令include加载对应的头文件<iostream>,并且使用标准命名空间stdcin,cout是iostream类的对象cout能够识别C++中所有的基本类型,cin`能够识别C++中的字符型、整型以及浮点型数据类型。 -
cout 输出主要是console output,以字符串的形式输出。 cout 的<<在iostream中重新定义为插入运算符,用来识别类型的。 但是在其他文件中是定义为左位移运算符。 因此,当使用iostream时,含义会变化。
-
多个输出语句的内容之间默认不进行换行,需要借助转义字符'\n'或之前学习的endl执行换行操作。
-
使用
cout进行数据输出时,我们并没有指定相应的输出格式符,系统会自动判断数据的类型并进行转化。 -
单纯的
cout输出并不具备控制输出格式的选项,不同类型数据的输出格式如下:- 对于
char值,如果代表可打印的字符,则将作为一个字符显示在宽度为一个字符的字段中 - 对于整型数值,将以十进制方式显示在一个
刚好容纳该数字以及负号(如果有)的字段中 - 浮点类型被显示为6位,末尾的0不显示,最终显示位数
与精度无关; - 浮点数显示,当指数大于6或者小于等于-5时,将使用
科学记数法显示;字段宽度恰好容纳数字以及负号(如果有); - 字符串被显示在宽度等于该
字符串长度的字段中。
//字符转换为数字 char c; cin >> c; int b = c; // printf("%d", c); cout << b; return 0; - 对于
-
输出的字符串占m列,如果字符串本身大于m,则突破m的限制,将字符串全部输出;若串长小于m,则左补空格。
- cin输入
cin的内存存储单元可以是变量、引用或者之后讲到的类或结构的成员 与cout对应被重定义为抽取运算符,输入功能。
-
抽取运算符
">>"从流中提取数据时,通常会跳过输人流中的空格、制表符、换行符等空白字符。只有在输入完数据再按回车键后,这一行数据才会形成输入流,提取进而被运算符提取。同时支持支持连续的输入,输入之间以回车键分割。如果输入的内容与存储单元定义的类型不同,那么系统返回0。也就是初始化为0。
算术运算符
- Tips:单一的常量,也可以看作是一个简单表达式。
- 赋值的行为都是从右往左进行的
- 左边项必须引用一个存储位置,如一个变量名
/和注释符号一样,如果都是整数那么也返回整数。如果是浮点数,那么结果也是浮点数。%其中必须都是整数,才可以找到整数的余数- 算术运算符的结合律都是从左到右的
- 表达式
juice = cookie = 0;的计算顺序等价于表达式juice = (cookie = 0); - 赋值运算符的结合律是从右到左的
自增自减运算:
- 前缀模式的变量将先于赋值运算符进行递增
- 后缀模式时的变量将后于赋值运算符进行递增
- 自增运算符需要作用在一个确定的变量上,对于由变量构成的表达式应用
++,例如:(coffee + milk)++会使得程序报错,因为计算机无法找到一个明确的位置去存储递增计算之后的结果。
计算且赋值运算符
位运算符与表达式
-
每8位(bit)构成一个字节(byte)
-
按位与运算符
& -
按位或运算符
| -
异或运算符
^ -
按位取反运算符
~取反规则是0变1,1变0。 对二进制码操作以后,会对二进制码取补码,也就是先取反以后+1。 -
左移运算符
<< -
右移运算符
>>左移相当于* 2
按位运算符只能对字符整型以及数值整型数据类型的常量或变量使用,不能对浮点类型数据进行计算。 在输出时,需要加()
分支结构程序设计
- 关系运算符与python一样。运算符的对象可以是字符或数字,但不能是字符串。
返回布尔量:成立为1(true)代表真,不成立为0(false)代表假。
浮点数一般不会用
==或者!=来判断,因为可能产生表示误差。
- 比较两个浮点数是否相等,需要看两个数的差值是否小于一定的精度,比如:
- 对于浮点数
a和b,如果(a - b) < 1e-6如果值为真,就判断两个浮点数相等
- 对于浮点数
- 逻辑表达式:
- C++使用逻辑运算符连接多个关系表达式,从而构建逻辑表达式。
- 运算符顺序:
为了代码的可读性,我们在编写时一般都选择把括号加上**
逻辑表达式最后,运算符先行。
赋值-<逻辑-<关系-<算术
++a || ++b && ++c;为啥不报错
顺序条件结构
if 语句三种语法:
if
if else
if else if
注意点1:如果省略大括号,else默认会匹配到最近的那一个if。嵌套时一般跟上大括号。
cin >> a >> b;先给a
- 如果if(判断条件式子是0),那么该式子的逻辑表达式为0不满足If条件,也就是说if 默认判断()条件是否为真(bool != 0),0为假。
万能头文件:bits/stdc++.h几乎包含所有的可用到的C++库函数。以后写代码就可以直接引用这一个头文件了,不需要在写一大堆vector、string、map、stack……
switch语句根据某个变量不同的值进行不同的操作。
switch (变量名) {
case 变量可能的情况1: 执行语句1; break;
case 变量可能的情况2: 执行语句2; break;
... // 可以有任意数量的 case 语句
default: 执行语句n;
}
-
switch 后面的变量名:整型变量(比如
int或者char),或者值为整型的表达式。 -
可以放bool量和逻辑表达式,因此可以和if一样用
-
!case不可以像赋值语句一样一下赋值很多
-
break用于跳出语句。没有的话就会顺序执行所有语句。如果走到最后一个case,如果没有break,下一个default会执行吗。会继续执行default,所以一定要写break。 代码:
#include <bits/stdc++.h>
using namespace std;
int max(int a, int b){
return a > b ? a : b;
}
int main() {
// 请补全代码,实现题目功能
bool check, right, isosceles, equilateral, normal;
int a, b, c, large;
cin >> a >> b >> c;
check = (a + b >c) && (b+ c > a) && (c+a >b);
large = max(a,max(b,c));
right = (a*a +b*b == large *large) || (b*b + c*c == large*large) || (c*c+ a*a ==large*large);
isosceles = (a==b)|| (b == c)||(c == a);
if (a == b && b == c){
cout << "equilateral";
}else if (check){
if (right){
cout << "right";
}else if (isosceles){
cout << "isosceles";
}else{
cout << "normal";
}
}else {
cout << "no";
}
return 0;
}
循环结构:
for语法:
for (循环变量赋初始值;循环条件;更新循环变量) { 循环体 }
-
赋初值或者函数里面都需要给变量指定类型,和Python不同。
-
使用
;和python不同。 -
也就是更新变量以后或者赋值以后都会判断是否满足循环条件,不满足直接退出循环。
for ( ; ; ),这表示不用给循环变量赋初始值,也不用在每次执行后更新循环变量,同时循环的条件始终为真,也就是说每次都会选择进入循环体。- 如果循环体只有一句话,可以不用大括号括起来。
- cout字符串输出数字不用"",直接输出。
break和continue:
break跳出整个模块。 continue跳出当前循环,并进入下一个循环。
#include <bits/stdc++.h>
using namespace std;
int check(int year){
return (year %400 == 0) || ((year % 4 == 0) && (year % 100 != 0));
}
int main() {
// 请补全代码,实现题目功能
int inyear;
int sign = 0;
cin >> inyear;
if (inyear < 2001 || inyear > 2100){
cout << "Invalid year!";
}else{
for (int i = 2004; i <= 2100; i=i+4){
if (i > inyear){
break;
}
if (check(i) == 1){
cout << i << endl;
sign = 1;
}
}
if (sign == 0){
cout << "None";
}
}
return 0;
}
while语句:
while (循环成立条件) { 循环体 }直到循环成立条件为假退出循环。
//不需要额外的库
srand((unsigned)time(NULL));
// 随机生成一个1-100的数字
num = rand() % 100 + 1;
do while
do { 循环体 } while (循环成立条件);
至少执行一次。
while和for 都是先判断循环条件。
while(i)i 和0比较而不是大于小于0。
判断素数
#include <bits/stdc++.h>
using namespace std;
int main() {
// 请补全代码,实现题目功能
int num;
cin >> num;
int i = 2;
int sign = 0;
if (num == 1){
cout << "no";
sign = 1;
}
//1不是素数,2是素数。
while(i < num){
if (num % i == 0){
cout << "no";
sign = 1;
break;
}
i += 1;
}
if (sign == 0)
cout << "yes";
return 0;
}
多重循环:
- 在嵌套操作中都需要使用缩进,以增强代码可读性
for嵌for,for嵌while,while嵌for,while嵌while都可以a--先给出a的值,在把a= a -1赋值。
#include <bits/stdc++.h>
using namespace std;
int main() {
// 请补全代码,实现题目功能
//由于不可以使用数组,所以使用for进行cin。
int num;
long int res = 1;
//数据过于长;
cin >> num;
for (int i = 1; i <= num; i++){
int c = 1;
cin >> c;
for (int j = 1; j <= c; j++){
res = res*j;
}
cout << res << endl;
//输出以后再初始化!
res = 1;
}
return 0;
}
break语句只用于循环体内和switch语句中。
#include <bits/stdc++.h>
using namespace std;
int main() {
// 请补全代码,实现题目功能
int one;
cin >> one;
int three;
cin >> three;
int five;
cin >> five;
int ten;
cin >> ten;
int N;
cin >> N;
int res = 0;
for (int o = 0; o <= one; o++){
for (int t =0; t <= three; t++){
for (int f = 0; f <= five; f++){
for (int te = 0; te <= ten; te++){
if (o + t*3 + f*5 + te*10 == N){
res += 1;
break;
}
// continue;
}
}
}
}
if (res != 0){
cout << res;
}else{
cout << "no";
}
return 0;
}
数组:
数组的声明与定义:
- 创建后的数组大小固定
- 同一数组中的元素类型相同
- 是一系列数据顺序集
元素类型 数组名称[数组长度]; - 数组长度代表数组容纳元素的数量,必须是一个固定的整型常量,不能是变量
- 数组名其实表示的就是第一个元素的起始地址。
数组的索引: 从0开始到n-1。
- C++数组越界时,程序一般不会产生运行错误,但是可能会导致其他后果,比如修改了无关变量的值。- 把这个元素的值赋给另一个变量:
int a = sales[0];
初始化-给数组赋值:
- 在声明的同时,使用大括号包含对应数值,直接对整个数组初始化
- 在声明之后,逐个访问数组元素进行一一初始化赋值
- 初始化时数组长度必须确定给出。
const int n =10;int a[n];可行。 - 对数组或者结构体赋值,使用花括号
{}5. 不可以直接copy数组使用=
int main() {
// 请补全代码,实现题目功能
//数组定义时长度固定,因此我们需要计算结果的长度们在输入的时候就确定。
//否则使用删除元素的方法,目前还没找到这样的库函数
int N, M;
cin >> N;
int num[N];
for (int i = 0; i<N; i ++){
int n = 0;
cin >> n;
num[i] = n;
}
cin >> M;
//数字到这里才给出。所以方法一不可行。
int sign = 0;
for (int i = 0;i < N; i++){
if (num[i] != M){
sign += 1;
cout << num[i] <<" ";
}
}
int res[sign];
int j = 0;
for (int i =0; i<N; i++){
if (num[i] != M){
res[j] = num[i];
j += 1;
}
}
for (int j = 0; j< sign; j++){
cout << res[j] << " ";
}
return 0;
}
int sales[6] = {1, 3, 5, 7, 9, 11}
int sales[] = {1, 3, 5, 7, 9, 11}
output &input:
- 在C++中,普通的一维数组只能对单个元素进行输入输出。与python不同。
for (int i = 0; i < 12; i ++) sales[i] = 2*sales[i - 1];
#include <bits/stdc++.h>
using namespace std;
int main() {
// 请补全代码,实现题目功能
long int num;
cin >> num;
long int ru[num + 1] ;
for (long int i =0; i < num; i++){
cin >> ru[i];
}
long int runum;
cin >> runum;
// long int res[num+1];
// int sign = 0;
for (long int j=0;j<num;j++){
// if (sign == 0)
// res[j] = ru[j];
// cout << "ru[j]"<<" ";
if (runum>ru[j-1]&&runum<ru[j]){
// sign = 1;
// res[j] = ru[j];
// continue;
cout << runum<<" ";
}
cout << ru[j]<<" ";
// else{
// res[j+1] =ru[j];
// }
}rn 0; }
//从后向前赋值数组最后留有空位子
二维数组:
int scores[5][3]; 二维数组最后一维必须有值;
访问形式是数组名称[行索引][列索引]
从 0 到 维度长度-1
元素之间使用,隔开{,}多层大括号,或者一个一维直接赋值。
int scores[5][3] = {8, 4, 6, 5, 6, 3, 3, 2, 4, 8, 7, 6, 7, 9, 8};
- 单个元素输入输出,不同于Python。如果给出的元素数量少于本身的数量,那么后面的会被默认初始化为0。 与python不同的是,python是库函数读取,c++是按照cin读取。 翻转行列-先按照行列读取的顺序给数组赋值,然后找到方法读取数组。
int hang;
int lie;
cin >> hang >> lie;
int string[lie][hang];
for (int i = 0; i< hang; i++){
for (int j = 0; j < lie; j++){
cin >> string[j][i];
//数组存储的就是改变过的数组
}
}
// int chstring[lie][hang];
for (int j = 0; j < lie; j++){
for(int i = 0;i < hang; i++){
cout << string[j][i] <<" ";
}
cout << endl;
}
字符串数组
char username[11] = {,}
使用数组还存储单个字符char;
-
""双括号和'\0'作为结束符,所以地址储存空间长度+1。前面8个元素分别是:-'L','a','o','W','a','n','g','\0'。。空字符串就是一个字节存贮了'\0',用""表示。 -
字符的声明长度需要+1存贮结束符
-
字符和字符串不同,cout是字符串形式。
'a'和"a"是不一样的,前者是一个字符常量,在内存中占 11 字节,后者是一个字符串,占 22 字节的空间,第 11 个字节储存了字母a的内码值,第二个字节储存了'\0'。
字符数组的初始化
- 初始化可以使用
''单个字符赋值,也可以""字符串格式赋值。- char userName[11] = {"LaoWang"}; // 大括号可以省略
- char userName[11] = "LaoWang";
- char userName[11] = {'L', 'a', 'o', 'W', 'a', 'n', 'g', '\0'};
- char userName[11] = {'L', 'a', 'o', 'W', 'a', 'n', 'g'}; // 和普通数组一样,元素个数可以省略,c++会自动识别长度为8 char userName[] = {'L', 'a', 'o', 'W', 'a', 'n', 'g', '\0'};
字符数组的cin,cout
cin >> ch;
- 输入的时候,使用
cin语句,会不断的读入字符串,直到遇到一个空白字符(空格、回车或者制表符)就结束读入 - 用
cin向计算机输入一串字符时,输入的字符的数量应该少于已定义的字符数组的长度,否则会出现问题 - 如果输入的字符的数量小于字符数组长度时,剩下的部分会默认补上
'\0'
cout << ch;
-
从字符数组的第一个字符开始输出,直到遇到
'\0'(不会输出'\0') -
如果一个字符数组中包含一个以上
'\0',则遇第一个'\0'时cout输出就结束 -
字符的输入用
scanf("%c", &变量名),而输入一个字符串用scanf("%s", 数组名) -
scanf里,数组前不需要加&,只有变量名字需要加&.printf("%c", &变量名),而输出一个字符串用printf("%s", 数组名)
字符数组的操作:
- 头文件
#include<cstring>- 连接字符串使用
strcat(s1, s2) - strlen()长度,不带
\0 - strcmp()返回字典序,s1小就小于0。
- strcpy。复制字符串数组不可
=。
s1存的是{q, w, e, r, \0},s2存的是{a, s, \0},那么使用strcpy(s1, s2)后,s1前五位应该是{a, s, \0, r, \0}。 - 连接字符串使用
int main() {
// 请补全代码,实现题目功能
char str1[100], str2[100], str3[100];
cin >> str1 >> str2 >> str3;
cout << str3 <<" "<< str2 <<" "<< str1;
return 0;
}
//使用多维数组
int main() {
char words[3][101];
for (int i=0; i<3; i++) scanf("%s", words[i]);
printf("%s %s %s", words[2], words[1], words[0]);
return 0;
}
由于输入比较少可以单个输入,或者可以使用多维数组存储。
string变量类型非数组
数组必须给定长度因此可能越界。 标准模版库(Standard Template Library,STL)。
string 类型是直接把字符串当作一个整体,可以像整型变量、字符变量一样使用。
# include <string>// 声明 string a; // 声明与初始化 string b = "yes";- 输入输出使用cin和cout直接,遇到'\0'就停止。
- string也可以作为数组使用。
# include <iostream>
# include <string>
using namespace std;
int main() {
string words[3];
//string产生一个string数组
for (int i=0; i<3; i++)
cin >> words[i];
cout << words[2] << " " << words[1] << " " << words[0];
return 0;
}
// 我写的
string str1, str2, str3;
cin >> str1>> str2 >>str3;
cout << str3 <<" "<<str2 <<" "<< str1;
string库函数
+- 使用
s1.size()或者s1.length()返回字符串s1的字符数。注意() - 直接关系运算符,==, <,>
- 赋值= 和整形变量啥的一样
- str.replace(3,2,str)也就是replace自己时,他会保存str原本的值,然后replace以后付给str/
函数声明/定义和调用:
必须有一个主要的函数,叫做main()函数,作为执行整个程序的入口。你可以在main()函数中去调用其他函数,同样地,其它函数之间也可以互相调用。
声明:
-
参数是可选的,函数可能不包含参数,也可以包含很多个参数
-
函数实参的个数,是定义该函数时传进函数的参数的个数。
-
不返回参数,参数类型为void int MyMax(int a, int b);
定义:
声明以后定义。 如果我们函数的定义在调用前进行的话,也可以省略函数的声明这一步。
调用执行函数:
传入实际参数:
- 全局变量,所有函数,包括
main()函数都可以访问。 - 局部变量,只有在这个函数里能访问到这个变量
参数传递
在引用传递过程中,被调函数的形式参数虽然也作为局部变量开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。
// 传值传递void swap2(int &x, int &y) {--// 引用传递 void swap2(int &x, int &y)
-
变量相关,所以传递的参数实际上是数组的地址- 在函数中修改数组里的某一个值,会在内存中直接修改这个数组。
-
函数定义时,我们可以给函数的参数设置默认值 因此默认值可以不传递被忽略,但是也可以直接赋值就更改了。
递归函数:
递归关系(return)和递归条件(n??): 函数的函数体中又调用了它自己,这就叫做“递归函数”。
递归函数的写法有两个基本要素:
-
递归关系
- 比如计算某个数字的阶乘,我们知道,递归的关系就是:数字n的阶乘 = 数字n * 数字n-1的阶乘。
-
递归的终止条件
- 只知道递归关系是不够的,我们需要有一个递归终止的条件。在计算阶乘这个例子中,递归终止的条件是计算到数字1的阶乘的时候,函数可以直接返回数字1的阶乘就是1。更严谨的,我们可以在
n小于1的时候,输出错误操作。
- 只知道递归关系是不够的,我们需要有一个递归终止的条件。在计算阶乘这个例子中,递归终止的条件是计算到数字1的阶乘的时候,函数可以直接返回数字1的阶乘就是1。更严谨的,我们可以在
int factorial(int n) {
if (n < 1) {
cout << "错误操作" << endl;
return -1;
}
if (n == 1) return 1;
else return n * factorial(n-1);
}
//汉诺塔递归函数
#include <iostream>
using namespace std;
void hanoi(int N, char source, char relay, char destination) {
if(N == 1)
cout << source << " -> " << destination << endl;
else {
hanoi(N-1, source, destination, relay);
cout << source << " -> " << destination << endl;
hanoi(N-1, relay, source, destination);
}
}
int main() {
int n;
cin >> n;
hanoi(n, 'A' , 'B' , 'C');
return 0;
}
结构体:
使用结构体来将一组不同类型的数据聚合成一个整体
- 使用
struct关键字 - 每个结构体都有自己的名称
- 注意大括号后面需要有分号
; - 因为内存对齐的存在,结构体类型的变量的字节数不等于各成员字节数之和。
c++
struct Student{ int number, birth_year; string name; };
声明:
声明结构体变量的方式和声明普通变量是一样的,在声明结构体变量的时候,系统就会为它们在内存上分配空间了。此时先创建一个类别,然后声明产生该类别的具体对象要给她赋名字,并为其分配空间。
//先定义后声明,可以单个变量也可以数组批量声明对象。
struct Student{ int number, birth_year; string name; }; // 声明三个学生 Student zhang_san, li_si, wang_mazi;Student students[500];
//必须要声明Students
struct Student{ int number, birth_year; string name; } zhang_san, li_si, wang_mazi;
//定义以后不加;直接跟变量。!!
初始化:名字最好统一方便调用处理。
- 初始化列表和数组的初始化类似,会根据给出的元素依次初始化结构体中的每个成员。
- 如果给出的元素小于成员数量,排在后面的就会保持没有被初始化,也无法跳过它给后面的成员初始化。 使用{}花括号。
struct Student{ int number, birth_year; string name; };
// 初始化一个学号为1,2000年出生,名叫 ZhangSan的学生
Student zhang_san = {1, 2000, "ZhangSan"};
构造函数初始化。
- 可以先在结构体内部完成一个构造函数,再调用这个构造函数来初始化结构体变量。
- 可以在创建一个结构体变量而不向其传递某些成员变量的值时,提供默认值 函数使用()圆括号 构造函数好像必须和原结构体名字相同。
构造函数好像属于结构体内的局部变量。
- 可以传值也可以引用传递。传值会占用额外的空间。
外界函数引用结构体变量
- 常量引用传递。如果不想让函数更改任何成员变量值,那么可以将结构体变量作为一个常量引用传递给函数。需要在参数类型前加上
const关键字。 - 也就是引用传递了,但是不改变原来的对象的属性。 函数对该结构体的引用对象可以随意取名字,为局部变量。
#include <iostream>
using namespace std;
struct Student{
int number, birth_year;
string name;
};
// TODO 完成该函数,展示学生的学号、姓名和出生年份
void showStudent(const Student& CYIN) {
cout << "Student Number : " << CYIN.number<< endl;
cout << "Name : " << CYIN.name << endl;
cout << "Birth Year : " << CYIN.birth_year<< endl;
}
int main() {
Student zhang_san = {1, 2000, "ZhangSan"};
// 调用函数
showStudent(zhang_san);
return 0;
}
结构体定义和使用如下:
struct Student{ int number, birth_year; string name;
// 在结构体里定义构造函数
// 在初始化时所有学生的出生年份都被设置为2000
// 可以传入两个参数,分别代表学号和姓名,如果不传入参数,默认学号为0,姓名为""
Student (int num=0, string n="") { number = num; birth_year = 2000; name = n; }
};
// 初始化时只用传递两个参数即可
Student li_si(2, "LiSi");
调用函数:已经确定了一个对象以后,该对象拥有了该结构下的所有属性。直接.
#include <bits/stdc++.h>
using namespace std;
struct Student{
string name;
char sex;
int age;
};
int main() {
// 请补全代码,实现题目功能
int n;
cin >> n;
Student stu[n];
Student temp,res;
// same time;
cin >> temp.name;
cin >>temp.sex;
cin >> temp.age;
// res.name = temp.name;
// res.sex = temp.sex;
// res.age = temp.age;
res = temp;
for (int i = 2; i <= n; i++){
cin >> temp.name;
cin >> temp.sex;
cin >> temp.age;
if (temp.age > res.age){
// res.name = temp.name;
// res.sex = temp.sex;
// res.age = temp.age;
res = temp;
}
}
cout << res.name <<" ";
cout << res.sex << " ";
cout << res.age;
return 0;
}
//use tuple's index to save and output
#include <iostream>
#include <string> using namespace std;
struct Student { string name; char gender; int age; };
int main() {
int num, max_age, max_age_idx;
cin >> num;
string n;
char g;
int a;
Student students[11];
for (int i=0; i<num; i++) {
cin >> n >> g >> a;
students[i] = {n, g, a};
}
max_age = 0;
max_age_idx = 0;
for (int i=0; i<num; i++) {
if (students[i].age > max_age) {
max_age = students[i].age; max_age_idx = i;
}
}
cout << students[max_age_idx].name << " " << students[max_age_idx].gender << " " << students[max_age_idx].age;
return 0;
}