xcx:主流语言这么多,为什么acm算法竞赛要用C++呢?
shy:C++在竞赛中实现算法和数据结构时具有更高的执行效率,对于一些需要处理大量数据和复杂算法的竞赛题目来说,C++ 能够提供更快的执行速度和更低的资源消耗,这对于算法竞赛中的性能要求至关重要。
hwjw:除此之外,C++还有什么其他的优点吗?
shy:C++ 提供了丰富的标准库,其中包括对数组、字符串、容器(如 vector、set、map 等)、算法(如排序、搜索等)等常用数据结构和算法的支持。这些标准库功能强大且经过优化,使得在算法竞赛中能够更快速地实现问题的解决方案。
xcx、hwjw:WOW!原来用C++打算法竞赛这么爽啊,那我们要好好学习C++基础语法!ヾ(≧▽≦*)o
文章目录
1. 初识C++
1.1 第一个C++程序——输出"Hello world"
#include<iostream> //标准输入输出流库,可以在程序中使用std::cout、std::cin等对象来进行输入输出操作
using namespace std; //告诉编译器使用std命名空间中的名称,而不需要为它们加上std::前缀。例如,你可以直接写cout而不是std::cout。
int main() //主函数,程序的主入口点。当你运行一个C++程序时,操作系统会调用这个main()函数,从而启动你的程序。
{
cout << "Hello world"; //cout用于输出数据到控制台
return 0; //表示程序成功地执行完毕,并返回给操作系统一个状态码0,表示没有错误。
}
输出结果如下:
Hello world
1.2 注释
作用:在代码中加一些说明和解释,方便自己或其他人阅读代码。编译器在编译代码时,会忽略注释的内容。
种类:
1.单行注释: // 注释信息
2.多行注释:/* 注释信息 */
//这是单行注释
/*
这是多行注释
这是多行注释
这是多行注释
*/
1.3 变量
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名 = 初始值;
#include<iostream>
using namespace std;
int main()
{
int a = 10; //把a赋值为10
cout << "a=" << a << endl;
return 0;
}
输出结果如下:
a=10
变量的值可以修改,可以反复给一个变量赋值:
#include<iostream>
using namespace std;
int main()
{
int a = 10; //把a赋值为10
a = 20; //把a赋值为20
a = 30; //把a赋值为30
cout << "a=" << a << endl;
return 0;
}
输出结果如下:
a=30
1.4 常量
作用:用于记录程序中不可更改的数据
C++定义常量两种方法
1.#define宏常量:#define 常量名 常量值
2.const修饰的变量:const 数据类型 常量名 = 常量值;
(注意分号)
Tips:算法竞赛中一般把较大的数组范围上限定义为N,例如:const long long N = 1e9+10;
(一般都+10防止数组溢出)
示例:
#include<iostream>
#define id 20222245 //1.宏常量
using namespace std;
int main()
{
cout<<"学生的id号为:"<<id<<endl;
//id=20222246; //报错,常量值不可修改
const int age = 20; //2.const修饰的变量
cout<<"学生的年龄为:"<<age<<endl;
//age = 21; //报错,常量值不可修改
return 0;
}
1.5 关键字
作用:关键字是C++中预先保留的单词
在定义变量或常量时,不要使用关键字
1.6 标识符命名
作用:C++中给变量、常量命名时,要遵循以下原则
-
标识符不能是关键字
-
标识符只由数字、字母、下划线组成
-
第一个字符必须是字母或下划线 (不能是数字)
-
标识符中区分大小写
-
不能以中文命名(这里与Python不同)
Tips:命名原则应见名知意,方便自己和他人阅读
2. 数据类型
C++在创建一个变量和常量时,必须要指出相应的数据类型,否则不能给变量分配内存
2.1 整型
作用:整型变量表示的是整数类型的数据
表示整型类型的方式,区别在于内存空间和可表示数的取值范围不同:
数据类型 | 占用空间 | 取值范围 | 精确范围 |
---|---|---|---|
short | 2Byte | -215~215-1 | -32768~32767 |
int | 4Byte | -231~231-1 | -2147483648~2147483647 |
long | Windows:4Byte,Linux:4Byte(32位),8Byte(64位) | -231~231-1 | -2147483648~2147483647 |
long long | 8Byte | -263~263-1 | -9223372036854775808~9223372036854775807 |
Tips:算法竞赛中最常用的是 int 和 long long,int一般只能存下9位数,long long一般只能存下18位数,超长度就需要使用字符串string进行高精度处理
2.2 sizeof关键字
作用:利用sizeof关键字可以统计数据类型所占内存空间大小
语法:sizeof(数据类型 或 变量)
#include<iostream>
using namespace std;
int main()
{
cout<<"short 类型所占内存空间为:"<<sizeof(short)<<endl;
cout<<"int 类型所占内存空间为:"<<sizeof(int)<<endl;
cout<<"long 类型所占内存空间为:"<<sizeof(long)<<endl;
cout<<"long long 类型所占内存空间为:"<<sizeof(long long)<<endl;
return 0;
}
输出结果如下:
short 类型所占内存空间为:2
int 类型所占内存空间为:4
long 类型所占内存空间为:4
long long 类型所占内存空间为:8
或者直接使用sizeof(变量名)
来统计占用的内存空间大小
#include<iostream>
using namespace std;
int main()
{
int a = 10;
cout<<"变量a所占的内存空间大小为:"<<sizeof(a)<<endl;
return 0;
}
输出结果如下:
变量a所占的内存空间大小为:4
2.3 浮点型(实型)
作用:用于表示小数
浮点型变量分为两种:
1.单精度float
2.双精度double
两者的区别在于表示的有效数字范围不同。
数据类型 | 占用空间 | 有效数字范围 |
---|---|---|
float | 4Byte | 7位 |
double | 8Byte | 15~16位 |
Tips:算法竞赛中一般使用double
#include<iostream>
using namespace std;
int main()
{
float f1=3.14f; //float定义的浮点数最后要加f,否则默认为double
double d1=3.14;
cout<<f1<<endl;
cout<<d1<<endl;
cout<<"float sizeof = "<<sizeof(f1)<<endl;
cout<<"double sizeof = "<<sizeof(d1)<<endl;
return 0;
}
输出结果如下:
3.14
3.14
float sizeof = 4
double sizeof = 8
2.4 科学计数法
语法: men
(m,n均为int)表示mn
#include<iostream>
using namespace std;
int main()
{
double d1 = 3e2; //3 * 10 ^ 2 = 300
cout<<"d1 = "<<d1<<endl;
double d2 = 3e-2; //3 * 10 ^ -2 = 0.03
cout<<"d2 = "<<d2<<endl;
return 0;
}
输出结果如下:
d1 = 300
d2 = 0.03
2.5 字符型
作用:字符型变量用于显示单个字符
语法:char ch = 'a';
在显示字符型变量时,用单引号将字符括起来,不要用双引号(双引号表示字符串string)
单引号内只能有一个字符,不可以是字符串
C++中char只占1个字节
字符型变量是将对应的ASCII码放入存储单元
#include<iostream>
using namespace std;
int main()
{
char ch='a';
cout<<ch<<endl; //直接输出字符ch
cout<<sizeof(char)<<endl; //char只占1个字节
cout<<(int)ch<<endl; //把ch强转为ASCII码
ch=97; //给char用ASCII码赋值
cout<<ch<<endl; //输出的是char类型
return 0;
}
输出结果如下:
a
1
97
a
ASCII码表如下:
Tips:算法竞赛中一般只需记住A(65),a(97)即可
2.6 转义字符
作用:表示一些不能显示出来的ASCII字符
Tips:算法竞赛中常用的转义字符有:\n \\ \t
\n:换行符,相当于endl
\t:水平制表符,默认占8位
\\:表示一个反斜杠字符’\’
#include<iostream>
using namespace std;
int main()
{
cout<<"\\"<<endl;
cout<<"\tHello"<<endl;
cout<<"\n"<<endl;
return 0;
}
输出结果如下:
\
Hello
2.7 字符串型
作用:用于表示一串字符
两种风格:
1.C风格:char 变量名[] = "字符串值"
#include<iostream>
using namespace std;
int main()
{
char str[]="hello world";
cout<<str<<endl;
return 0;
}
输出结果如下:
hello world
2.C++风格:string 变量名 = "字符串值"
#include<iostream>
#include<string> //引入字符串的头文件
using namespace std;
int main()
{
string str = "hello world";
cout<< str <<endl;
return 0;
}
输出结果如下:
hello world
Tips:算法竞赛中通常使用C++风格(string),string有很多高端的操作 (੭ˊᵕˋ)੭ଘ
2.8 布尔类型bool
作用:bool类型代表真或假的值
bool类型只有两个值:
true:真——1
false:假——0
bool类型占1个字节
#include<iostream>
using namespace std;
int main()
{
bool flag = true;
cout<<flag<<endl; //1
flag = false;
cout<<false<<endl; //0
cout<<"sizeof bool = "<<sizeof(bool)<<endl; //1
return 0;
}
输出结果如下:
1
0
sizeof bool = 1
2.9 数据的输入
作用:用于从键盘获取数据
关键字:cin
语法:cin>>变量
#include<iostream>
using namespace std;
int main()
{
//整型
int num = 0;
cin>>num;
cout<<num<<endl;
//浮点型
double d = 0;
cin>>d;
cout<<d<<endl;
//字符型
char ch = 0;
cin>>ch;
cout<<ch<<endl;
//字符串型
string str;
cin>>str;
cout<<str<<endl;
//布尔类型
bool flag = true;
cin>>flag;
cout<<flag<<endl;
return 0;
}
3. 运算符
分类:
3.1 算术运算符
作用:用于处理四则运算
运算符 | 名称 |
---|---|
+ | 正号 |
- | 负号 |
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取模 |
++ | 前置递增 |
++ | 后置递增 |
– | 前置递减 |
– | 后置递减 |
加减乘:
#include<iostream>
using namespace std;
int main()
{
int a=10;
int b=3;
cout<<a+b<<endl; //13
cout<<a-b<<endl; //7
cout<<a*b<<endl; //30
return 0;
}
除:
#include<iostream>
using namespace std;
int main()
{
int a1=10,b1=3;
cout<<a1/b1<<endl; //3,两个整数相除依然是整数
int a2=10,b2=20;
cout<<a2/b2<<endl; //0
int a3=10,b3=0;
//cout<<a3/b3<<endl; //error,除数不能为0
double d1=0.5,d2=0.25;
cout<<d1/d2<<endl; //2
return 0;
}
取模:只有整型变量才能取模
#include<iostream>
using namespace std;
int main()
{
cout<<10%3<<endl; //1
cout<<10%20<<endl; //10
//cout<<10%0<<endl; //取模运算,除数不能为0
//cout<<3.14%1.1<<endl; //小数不能取模
return 0;
}
递增递减:
#include<iostream>
using namespace std;
int main()
{
//后置递增
int a=10;
a++; //a=a+1;
cout<<a<<endl; //11
//前置递增
int b=10;
++b; //b=b+1;
cout<<b<<endl; //11
//后置递减
int c=10;
c--; //c=c-1;
cout<<c<<endl; //9
//前置递减
int d=10;
--d; //d=d-1;
cout<<d<<endl; //9
//区别
//前置递增先对变量进行++,再计算表达式
int a1=10;
int b1=++a1*10; //(10+1)*10=110
cout<<b1<<endl;
//后置递增先计算表达式,后对变量进行++
int a2=10;
int b2=a2++*10; //10*10=100
cout<<b2<<endl;
//前置递减先对变量进行--,再计算表达式
int a3=10;
int b3=--a3*10; //(10-1)*10=90
cout<<b3<<endl;
//后置递减先计算表达式,后对变量进行--
int a4=10;
int b4=a4--*10; //10*10=100
cout<<b4<<endl;
}
3.2 赋值运算符
作用:用于将表达式的值赋给变量
运算符 | 名称 |
---|---|
= | 赋值 |
+= | 加等于 |
-= | 减等于 |
*= | 乘等于 |
/= | 除等于 |
%= | 模等于 |
#include<iostream>
using namespace std;
int main()
{
//=
int a=10;
a=100;
cout<<"a="<<a<<endl; //a=100
//+=
a=10;
a+=2; //a=a+2;
cout<<"a="<<a<<endl; //a=12
//-=
a=10;
a-=2; //a=a-2;
cout<<"a="<<a<<endl; //a=8
//*=
a=10;
a*=2; //a=a*2;
cout<<"a="<<a<<endl; //a=20
///=
a=10;
a/=2; //a=a/2;
cout<<"a="<<a<<endl; //a=5
//%=
a=10;
a%=2; //a=a%2;
cout<<"a="<<a<<endl; //a=0
return 0;
}
3.3 比较运算符
作用:用于表达式的比较,并返回一个真值或假值
运算符 | 名称 |
---|---|
== | 相等于 |
!= | 不等于 |
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
#include<iostream>
using namespace std;
int main()
{
int a=20;
int b=20;
cout<<(a==b)<<endl; //0 假
cout<<(a!=b)<<endl; //1 真
cout<<(a>b)<<endl; //0 假
cout<<(a<b)<<endl; //1 真
cout<<(a>=b)<<endl; //0 假
cout<<(a<=b)<<endl; //1 真
return 0;
}
3.4 逻辑运算符
作用:用于根据表达式的值返回真值或假值
运算符 | 名称 | 语法 |
---|---|---|
! | 非 | !a |
&& | 与 | a&&b |
|| | 或 | a||b |
1.非:假变真,真变假
真值表
a | !a |
---|---|
0 | 1 |
1 | 0 |
#include<iostream>
using namespace std;
int main()
{
int a=10;
cout<<!a<<endl; //0
cout<<!!a<<endl; //1
return 0;
}
2.与:同真为真,其余为假
真值表
a | b | a&&b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
#include<iostream>
using namespace std;
int main()
{
int a=10;
int b=10;
cout<<(a&&b)<<endl; //1
a=10;
b=0;
cout<<(a&&b)<<endl; //0
a=0;
b=0;
cout<<(a&&b)<<endl; //0
return 0;
}
3.或:同假为假,其余为真
真值表
a | b | a||b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
#include<iostream>
using namespace std;
int main()
{
int a=10;
int b=10;
cout<<(a||b)<<endl; //1
a=10;
b=0;
cout<<(a||b)<<endl; //1
a=0;
b=0;
cout<<(a||b)<<endl; //0
return 0;
}
4. 程序流程结构
C++基本运行结构:顺序结构、选择结构、循环结构
- 顺序结构:程序顺序执行,不发生跳转
- 选择结构(条件结构):依据条件是否满足,有选择地执行相应代码
- 循环结构:依据条件是否满足,循环多次执行某段代码
4.1 选择结构
4.1.1 if语句
1.单行if语句:if(条件){条件满足执行的语句}
#include<iostream>
using namespace std;
int main()
{
//输入一个分数,如果分数大于等于95分,则视为获得了保研资格
int score=0;
cout<<"请输入学生分数:"<<endl;
cin>>score;
cout<<"学生分数为:"<<score<<endl;
if (score>=95)
{
cout<<"恭喜你获得了保研资格!!!"<<endl;
}
return 0;
}
2.多行if语句:if(条件){条件满足执行的语句} else{条件不满足时执行的语句}
#include<iostream>
using namespace std;
int main()
{
int score=0;
cout<<"请输入学生分数:"<<endl;
cin>>score;
cout<<"学生分数为:"<<score<<endl;
if(score>=95)
{
cout<<"恭喜你获得了保研资格!!!ヾ(≧▽≦*)o"<<endl;
}
else
{
cout<<"很遗憾没有获得保研资格,好好准备考研吧!!!╥﹏╥..."<<endl;
}
return 0;
}
3.多条件if语句:if(条件1){条件1满足执行的语句} else if(条件2){条件2满足执行的语句} else{都不满足执行的语句}
#include<iostream>
using namespace std;
int main()
{
int score=0;
cout<<"请输入学生分数:"<<endl;
cin>>score;
cout<<"学生分数为:"<<score<<endl;
if(score==100)
{
cout<<"学生绩点为5.0";
}
else if(score>=95)
{
cout<<"学生绩点为4.5";
}
else if(score>=90)
{
cout<<"学生绩点为4.0";
}
else if(score>=85)
{
cout<<"学生绩点为3.5";
}
else if(score>=80)
{
cout<<"学生绩点为3.0";
}
else if(score>=75)
{
cout<<"学生绩点为2.5";
}
else if(score>=70)
{
cout<<"学生绩点为2.0";
}
else if(score>=65)
{
cout<<"学生绩点为1.5";
}
else if(score>=60)
{
cout<<"学生绩点为1.0";
}
else
{
cout<<"挂了,准备补考吧!!!";
}
return 0;
}
Tips:在算法竞赛中,{}内执行语句只有一句时,通常可以省略{},例如:
#include<iostream>
using namespace std;
int main()
{
int score=0;
cout<<"请输入学生分数:"<<endl;
cin>>score;
cout<<"学生分数为:"<<score<<endl;
if(score==100)cout<<"学生绩点为5.0";
else if(score>=95)cout<<"学生绩点为4.5";
else if(score>=90)cout<<"学生绩点为4.0";
else if(score>=85)cout<<"学生绩点为3.5";
else if(score>=80)cout<<"学生绩点为3.0";
else if(score>=75)cout<<"学生绩点为2.5";
else if(score>=70)cout<<"学生绩点为2.0";
else if(score>=65)cout<<"学生绩点为1.5";
else if(score>=60)cout<<"学生绩点为1.0";
else cout<<"挂了,准备补考吧!!!";
return 0;
}
if语句的嵌套:在if语句中,可以使用嵌套语句达到更精准的条件判断
例如:
用户输入学生的分数:
如果分数大于等于95分,则认为该学生获得了保研资格。如果分数小于95分,则认为该学生没有获得保研资格。
在保研的分数中,如果等于100分,则绩点为5.0;如果分数95~100分,则绩点为4.5。
在未保研的分数中,如果90~95分,则绩点为4.0;如果85~90分,则绩点为3.5;如果80~85分,则绩点为3.0;如果75~80分,则绩点为2.5;如果70~75分,则绩点为2.0;如果65~70分,则绩点为1.5;如果60~65分,则绩点为1.0;如果小于60分,则挂科。
#include<iostream>
using namespace std;
int main()
{
int score=0;
cout<<"请输入学生分数:"<<endl;
cin>>score;
cout<<"学生分数为:"<<score<<endl;
if(score>=95)
{
cout<<"恭喜你获得了保研资格!!!ヾ(≧▽≦*)o"<<endl;
if(score==100)cout<<"学生绩点为5.0";
else cout<<"学生绩点为4.5";
}
else
{
cout<<"很遗憾没有获得保研资格,好好准备考研吧!!!╥﹏╥..."<<endl;
if(score>=90)cout<<"学生绩点为4.0";
else if(score>=85)cout<<"学生绩点为3.5";
else if(score>=80)cout<<"学生绩点为3.0";
else if(score>=75)cout<<"学生绩点为2.5";
else if(score>=70)cout<<"学生绩点为2.0";
else if(score>=65)cout<<"学生绩点为1.5";
else if(score>=60)cout<<"学生绩点为1.0";
else cout<<"挂了,准备补考吧!!!";
}
return 0;
}
4.1.2 条件运算符(三目运算符)
作用:实现简单的判断
语法:表达式1 ? 表达式2 : 表达式3
说明:如果表达式1为真,执行表达式2,并返回表达式2的结果;如果表达式1为假,执行表达式3,并返回表达式3的记结果
#include<iostream>
using namespace std;
int main()
{
int a=10;
int b=20;
int c=0;
c=a>b?a:b;
cout<<"c="<<c<<endl; //c=20
//三目运算符返回的是变量,可以继续赋值
(a>b?a:b)=100;
cout<<"a="<<a<<endl; //a=10
cout<<"b="<<b<<endl; //b=100
cout<<"c="<<c<<endl; //c=20
return 0;
}
4.1.3 switch语句
作用:执行多条分支语句
语法:
switch(表达式)//------------------------------->此处表达式类型只能是int型或char型
{
case 结果1:执行语句;break;//---------------->如果没有break,程序会一直向下执行下去
case 结果2:执行语句;break;
......
default:执行语句;break;
}
案例:
#include<iostream>
using namespace std;
int main()
{
//根据等级对学生进行评价
//A:优秀
//B:良好
//C:一般
//D:及格
//其他:不及格
char grade=0;
cout<<"请给出学生等级"<<endl;
cin>>grade;
switch(grade)
{
case 'A':
cout<<"优秀"<<endl;
break;
case 'B':
cout<<"良好"<<endl;
break;
case 'C':
cout<<"一般"<<endl;
break;
case 'D':
cout<<"及格"<<endl;
break;
default:
cout<<"不及格"<<endl;
}
return 0;
}
与if语句相比,对于多条件判断时,switch结构清晰,执行效率高,缺点是switch不可以判断区间
4.2 循环结构
4.2.1 while循环
作用:满足循环循环条件,执行循环语句
语法:while(循环条件){循环语句}
解释:循环条件为真,执行循环语句
#include<iostream>
using namespace std;
int main()
{
int n=0;
while(n<10)
{
cout<<n<<" "; //0 1 2 3 4 5 6 7 8 9
n++;
}
return 0;
}
执行循环语句时,程序必须提供跳出循环的出口,否则会出现死循环,例如:
#include<iostream>
using namespace std;
int main()
{
int n=0;
while(1)
{
cout<<n<<" ";
n++;
}
return 0;
}
Tips:算法竞赛中TLE(超出时间限制,Time Limit Exceed)可能是因为程序中有死循环,或者时间复杂度过高。
Tips:算法竞赛中switch语句一般用于多组数据的输入,下面给出三个例子:
e.g.1:
输入包含多组数据,每组数据输入一行,包含两个整数
对于每组数据输出一行包含一个整数表示两个整数的和
Input
1 2 3 4
Output
3 7
#include<iostream>
using namespace std;
int main()
{
int a,b;
while(cin>>a>>b)
{
cout<<a+b<<endl;
}
return 0;
}
e.g.2:
第一行输入一个数据组数n
接下来n行每行输入两个整数
对于每组数据计算a+b的值
Input
2 1 1 2 2
Output
2 4
#include<iostream>
using namespace std;
int main()
{
int n;
int a,b;
cin>>n;
while(n--)
{
cin>>a>>b;
cout<<a+b<<endl;
}
return 0;
}
e.g.3:
多组数据,每组输入两个整数,当两个整数都为0时表示输入结束
对于每组数据输出两个整数的和
Input
1 1 2 2 0 0
Output
2 4
#include<iostream>
using namespace std;
int main()
{
int a,b;
while(cin>>a>>b&&(a!=0&&b!=0))
{
cout<<a+b<<endl;
}
return 0;
}
4.2.2 do…while循环
作用:满足循环循环条件,执行循环语句
语法:do{循环语句}while(循环条件);
解释:先执行一次循环语句,再判断循环条件
#include<iostream>
using namespace std;
int main()
{
int n=0;
do
{
cout<<n<<" "; //0 1 2 3 4 5 6 7 8 9
n++;
}while(n<10);
return 0;
}
4.2.3 for循环
作用:满足循环循环条件,执行循环语句
语法:for(起始表达式 ; 条件表达式 ; 末尾循环体){循环语句;}
#include<iostream>
using namespace std;
int main()
{
for(int i=0;i<10;i++)
{
cout<<i<<" "; //0 1 2 3 4 5 6 7 8 9
}
return 0;
}
也可以写成以下形式:
#include<iostream>
using namespace std;
int main()
{
int i=0;
for(;;)
{
if(i>=10)
{
break;
}
cout<<i<<" "; //0 1 2 3 4 5 6 7 8 9
i++;
}
return 0;
}
Tips:算法竞赛中经常使用到for循环
4.2.4 嵌套循环
说明:在循环体中再嵌套一层循环
例如输出一个10*10的加号阵
#include<iostream>
using namespace std;
int main()
{
for(int i=0;i<10;i++) //行循环
{
for(int j=0;j<10;j++) //列循环
{
cout<<"+ ";
}
cout<<endl; //列循环结束一轮,换行,再进行列循环
}
return 0;
}
输出如下:
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
4.3 跳转语句
4.3.1 break语句
作用:跳出选择结构或循环结构
使用时机:
1.switch条件语句:终止case并跳出switch
2.循环语句:跳出当前的循环语句
3.嵌套循环:跳出最近的内层循环
e.g.1
#include<iostream>
using namespace std;
int main()
{
//根据等级对学生进行评价
//A:优秀
//B:良好
//C:一般
//D:及格
//其他:不及格
char grade=0;
cout<<"请给出学生等级"<<endl;
cin>>grade;
switch(grade)
{
case 'A':
cout<<"优秀"<<endl;
break;
case 'B':
cout<<"良好"<<endl;
break;
case 'C':
cout<<"一般"<<endl;
break;
case 'D':
cout<<"及格"<<endl;
break;
default:
cout<<"不及格"<<endl;
}
return 0;
}
e.g.2
#include<iostream>
using namespace std;
int main()
{
for(int i=0;i<10;i++)
{
if(i==5)
{
break;
}
cout<<i<<" "; //0 1 2 3 4
}
return 0;
}
e.g.3
#include<iostream>
using namespace std;
int main()
{
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
if(j==5)
{
break;
}
cout<<"*"<<" ";
}
cout<<endl;
}
return 0;
}
4.3.2 continue语句
作用:循环语句中,跳出本次循环中余下尚未执行的语句,继续执行下一次循环
#include<iostream>
using namespace std;
int main()
{
for(int i=0;i<100;i++)
{
if(i%2==0)
{
continue;
}
cout<<i<<" "; //1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
}
return 0;
}
4.3.3 goto语句
作用:可以无条件跳转语句
语法:goto
标记
解释:跳转到标记位置
#include<iostream>
using namespace std;
int main()
{
cout<<1<<endl;
goto FLAG;
cout<<2<<endl;
cout<<3<<endl;
cout<<4<<endl;
FLAG:
cout<<5<<endl;
return 0;
}
输出:
1
5
5. 数组
5.1 特点
1.数组中每一个数据元素都是相同的数据类型
2.数组是由连续的内存位置组成的
3.数组元素下标从0开始索引
5.2 一维数组
5.2.1 定义方式
1.数据类型 数组名[len];
2.数据类型 数组名[len] = {value1,value2,...};
3.数据类型 数组名[] = {value1,value2,...};
#include<iostream>
using namespace std;
int main()
{
//定义1
int array[10];
//用数组下标直接赋值
array[0]=1;
array[1]=2;
array[2]=3;
//利用下标输出
cout<<array[0]<<" ";
cout<<array[1]<<" ";
cout<<array[2]<<" ";
cout<<endl;
//————————————————————————————————————————————————————
//定义2
int array1[10]={1,2,3}; //{}内数据不足10个,其余数据自动补0
for(int i=0;i<10;i++)cout<<array1[i]<<" ";
cout<<endl;
//————————————————————————————————————————————————————
//定义3
int array2[]={1,2,3,4,5,6,7,8,9,10};
for(int i=0;i<10;i++)cout<<array2[i]<<" ";
return 0;
}
输出结果如下:
1 2 3
1 2 3 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10
5.2.2 统计数组占用内存大小
#include<iostream>
using namespace std;
int main()
{
int array[10]={1,2,3,4,5,6,7,8,9,10};
cout<<"数组所占内存空间大小为:"<<sizeof(array)<<endl; //40
cout<<"每个元素所占内存空间为:"<<sizeof(array[0])<<endl; //4
cout<<"数组元素个数为:"<<sizeof(array)/sizeof(array[0])<<endl; //10
return 0;
}
5.2.3 获取内存中的地址
#include<iostream>
using namespace std;
int main()
{
int array[10]={1,2,3,4,5,6,7,8,9,10};
cout<<"数组首地址为:"<<(int)array<<endl; //此处转为十进制了
cout<<"数组中第一个元素地址为:"<<(int)&array[0]<<endl;
cout<<"数组中第二个元素地址为:"<<(int)&array[1]<<endl;
return 0;
}
5.2.4 一维数组的输入和输出
Tips:算法竞赛中通常要用到一维数组的输入和输出
第一行输入一个整数n
第二行输入n个数
输出这n个数
#include<iostream>
using namespace std;
const int N = 10;
int arr[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>arr[i];
for(int i=0;i<n;i++)
cout<<arr[i]<<" ";
return 0;
}
5.3 二维数组
5.3.1 定义方式
1.数据类型 数组名[行数][列数];
2.数据类型 数组名[行数][列数]={{数据1,数据2},{数据3,数据4}};
3.数据类型 数组名[行数][列数]={数据1,数据2,数据3,数据4};
4.数据类型 数组名[][列数]={数据1,数据2,数据3,数据4};
#include<iostream>
using namespace std;
int main()
{
//定义1
int array1[2][3];
array1[0][0]=1;
array1[0][1]=2;
array1[0][2]=3;
array1[0][3]=4;
array1[0][4]=5;
array1[0][5]=6;
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
cout<<array1[i][j]<<" ";
}
cout<<endl;
}
//----------------------------------------------
//定义2
int array2[2][3]=
{
{1,2,3},
{4,5,6}
};
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
cout<<array2[i][j]<<" ";
}
cout<<endl;
}
//----------------------------------------------
//定义3
int array3[2][3]={1,2,3,4,5,6};
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
cout<<array3[i][j]<<" ";
}
cout<<endl;
}
//----------------------------------------------
//定义4
int array4[][3]={1,2,3,4,5,6};
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
cout<<array4[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
输出均为:
1 2 3
4 5 6
5.3.2 统计数组占用内存大小
#include<iostream>
using namespace std;
int main()
{
int array[2][3]=
{
{1,2,3},
{4,5,6}
};
cout<<"二维数组大小:"<<sizeof(array)<<endl; //24
cout<<"二维数组一行大小:"<<sizeof(array[0])<<endl; //12
cout<<"二维数组元素大小:"<<sizeof(array[0][0])<<endl; //4
cout<<"二维数组行数:"<<sizeof(array)/sizeof(array[0])<<endl; //2
cout<<"二维数组列数:"<<sizeof(array[0])/sizeof(array[0][0])<<endl; //3
return 0;
}
5.3.3 获取内存中的地址
#include<iostream>
using namespace std;
int main()
{
int array[2][3]=
{
{1,2,3},
{4,5,6}
};
cout<<"二维数组首地址:"<<array<<endl; //此处地址为十六进制
cout<<"二维数组第一行地址:"<<array[0]<<endl;
cout<<"二维数组第二行地址:"<<array[1]<<endl;
cout<<"二维数组第一个元素地址:"<<&array[0][0]<<endl;
cout<<"二维数组第二个元素地址:"<<&array[0][1]<<endl;
return 0;
}
5.3.4 二维数组的输入和输出
Tips:算法竞赛中通常要用到二维数组的输入和输出
输入两个整数m,n
输入一个m*n的二维数组
输出这个二维数组
#include<iostream>
using namespace std;
const int N = 10;
int arr[N][N];
int main()
{
int m,n;
cin>>m>>n;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
cin>>arr[i][j];
}
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
6. 函数
作用:将一段经常使用的代码封装起来,减少重复代码
6.1 函数的定义
函数的定义一般由5部分构成:返回值类型,函数名,参数列表(传入函数的数据),函数体语句(函数执行语句),return表达式(返回数据)
语法:
返回值类型 函数名(参数列表)
{
函数体语句
return表达式
}
e.g. 一个函数实现两个数相加
#include<iostream>
using namespace std;
int add(int num1,int num2)
{
int sum=num1+num2;
return sum;
}
int main()
{
cout<<add(1,2); //输出3,函数的调用,详见6.2
}
6.2 函数的调用
作用:使用定义好的函数
语法:函数名(参数)
#include<iostream>
using namespace std;
int add(int num1,int num2)
{
int sum=num1+num2;
return sum;
}
int main()
{
int a=10;
int b=10;
int sum=add(a,b);
cout<<sum<<endl; //20
a=100;
b=100;
sum=add(a,b);
cout<<sum<<endl; //200
return 0;
}
6.3 函数值传递
定义:值传递就是通过函数调用将实参传入形参
形参的变化并不影响实参
#include<iostream>
using namespace std;
void swap(int num1,int num2) //void类型无需return返回值,详见6.4函数的样式分类
{
cout<<"交换前:"<<endl;
cout<<"num1 = "<<num1<<endl;
cout<<"num2 = "<<num2<<endl;
int temp = num1;
num1 = num2;
num2 = temp;
cout<<"交换后:"<<endl;
cout<<"num1 = "<<num1<<endl;
cout<<"num2 = "<<num2<<endl;
}
int main()
{
int a = 10;
int b = 20;
swap(a,b); //形参的变化不影响实参
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
return 0;
}
输出结果如下:
交换前:
num1 = 10
num2 = 20
交换后:
num1 = 20
num2 = 10
a = 10
b = 20
6.4 函数的样式分类
函数常见样式一般有四种:无参无返、有参无返、无参有返、有参有返
#include<iostream>
using namespace std;
//无参无返
void fun1()
{
//void a=10; //不能创建变量,无法分配内存
cout<<"这个是fun1"<<endl;
}
//-------------------------------------------------
//有参无返
void fun2(int a)
{
cout<<"这个是fun2"<<endl;
cout<<"a="<<a<<endl;
}
//-------------------------------------------------
//无参有返
int fun3()
{
cout<<"这个是fun3"<<endl;
return 10;
}
//-------------------------------------------------
//有参有返
int fun4(int a,int b)
{
cout<<"这个是fun4"<<endl;
int sum = a+b;
return sum;
}
int main()
{
fun1();
fun2(10);
cout<<fun3()<<endl;
cout<<fun4(10,20)<<endl;
return 0;
}
输出结果如下:
这个是fun1
这个是fun2
a=10
这个是fun3
10
这个是fun4
30
6.5 函数的声明
作用:告诉编译器函数名称及如何调用函数。
语法:返回值类型 函数名(参数列表);
函数的声明可多次,函数的定义只有一次
#include<iostream>
using namespace std;
int sum(int a,int b); //函数的声明
int sum(int a,int b); //函数的声明可多次
int sum(int a,int b); //函数的声明可多次
int main()
{
cout<<sum(10,20);
return 0;
}
int sum(int a,int b) //函数声明之后可以再主函数后写函数的定义
{
int sum=a+b;
return sum;
}
7. 结构体
7.1 结构体概念
用户自定义的数据类型,允许用户存储不同的数据类型
7.2 结构体的定义
语法:struct 结构体名{结构体成员列表};
创建变量方法:
struct 结构体名 变量名
struct 结构体名 变量名={value1,value2};
定义结构体时创建变量
#include<iostream>
using namespace std;
//结构体的定义
struct student
{
string name;
int age;
int score;
};
int main()
{
//创建变量方法1
struct student stu; //"struct"关键字可省略
stu.name = "xcx"; //结构体变量用操作符"."访问成员
stu.age = 18;
stu.score = 90;
cout<<"name:"<<stu.name<<" age:"<<stu.age<<" score:"<<stu.score<<endl;
//name:xcx age:18 score:90
return 0;
}
#include<iostream>
using namespace std;
//结构体的定义
struct student
{
string name;
int age;
int score;
};
int main()
{
//创建变量方法2
struct student stu = {"hwjw",20,100};
cout<<"name:"<<stu.name<<" age:"<<stu.age<<" score:"<<stu.score<<endl;
//name:hwjw age:20 score:100
return 0;
}
#include<iostream>
using namespace std;
//结构体的定义
struct student
{
string name;
int age;
int score;
}stu;
int main()
{
stu.name = "shy";
stu.age = 19;
stu.score = 95;
cout<<"name:"<<stu.name<<" age:"<<stu.age<<" score:"<<stu.score<<endl;
//name:shy age:19 score:95
return 0;
}
7.3 结构体数组
作用:将自定义结构体放入到数组中方便维护
语法:struct 结构体名 数组名[len] = {{},{},{},...,{}};
#include<iostream>
using namespace std;
//结构体的定义
struct student
{
string name;
int age;
int score;
};
int main()
{
struct student stu[3]=
{
{"xcx",18,90},
{"hwjw",20,100},
{"shy",19,90}
};
for(int i=0;i<3;i++)
{
cout<<"name:"<<stu[i].name<<" age:"<<stu[i].age<<" score:"<<stu[i].score<<endl;
}
return 0;
}
输出结果如下:
name:xcx age:18 score:90
name:hwjw age:20 score:100
name:shy age:19 score:90
7.4 结构体数组的输入和输出
Tips:算法竞赛中通常会用到结构体数组的输入和输出
#include<iostream>
using namespace std;
struct student
{
string name;
int age;
int score;
}stu[3];
int main()
{
//输入
for(int i=0;i<3;i++)
{
cin>>stu[i].name>>stu[i].age>>stu[i].score;
}
//输出
for(int i=0;i<3;i++)
{
cout<<"姓名:"<<stu[i].name<<" 年龄:"<<stu[i].age<<" 成绩:"<<stu[i].score<<endl;
}
return 0;
}
输入:
xcx 19 90
hwjw 20 100
shy 19 100
输出:
姓名:xcx 年龄:19 成绩:90
姓名:hwjw 年龄:20 成绩:100
姓名:shy 年龄:19 成绩:100
7.5 结构体嵌套结构体
例如:一个老师结构体中记录一个学生结构体
#include<iostream>
using namespace std;
//学生结构体
struct student
{
string name;
int age;
int score;
};
//老师结构体
struct teacher
{
string name;
int age;
int id;
struct student stu; //嵌套学生结构体
}tea;
int main()
{
tea.name="shy";
tea.age=19;
tea.id=20222245;
tea.stu.name="xcx";
tea.stu.age=18;
tea.stu.score=90;
cout<<"教师姓名:"<<tea.name<<" 年龄:"<<tea.age<<" 职工号:"<<tea.id<<endl;
cout<<"学生姓名:"<<tea.stu.name<<" 年龄:"<<tea.stu.age<<" 分数:"<<tea.stu.score;
//教师姓名:shy 年龄:19 职工号:20222245
//学生姓名:xcx 年龄:18 分数:90
return 0;
}
7.6 结构体做函数参数
作用:将结构体作为参数向函数中传递
传递方式:值传递、地址传递
算法竞赛基本不用,只做了解
#include<iostream>
using namespace std;
//定义结构体
struct student
{
string name;
int age;
int score;
};
//值传递
void showStudent_v(student stu)
{
stu.age = 18;
cout<<"show函数中 姓名:"<<stu.name<<" 年龄:"<<stu.age<<" 分数:"<<stu.score<<endl;
}
//地址传递
void showStudent_s(student *stu)
{
stu->age = 18;
cout<<"show函数中 姓名:"<<stu->name<<" 年龄:"<<stu->age<<" 分数:"<<stu->score<<endl;
}
int main()
{
student stu = {"shy",19,100};
//值传递
showStudent_v(stu);
cout<<"main函数中 姓名:"<<stu.name<<" 年龄:"<<stu.age<<" 分数:"<<stu.score<<endl;
//地址传递
showStudent_s(&stu);
cout<<"main函数中 姓名:"<<stu.name<<" 年龄:"<<stu.age<<" 分数:"<<stu.score<<endl;
return 0;
}
输出结果如下:
show函数中 姓名:shy 年龄:18 分数:100
main函数中 姓名:shy 年龄:19 分数:100
show函数中 姓名:shy 年龄:18 分数:100
main函数中 姓名:shy 年龄:18 分数:100
不想修改主函数中的数据用值传递,想修改主函数中的数据用地址传递
7.7 结构体算法竞赛例题
题目: lcryin的排序题
题目描述:
lcryin已经在bodongli老师的c语言课堂上学了简单的冒泡排序,但是现在lcryin遇到了一个难题,他想知道在坐标系上的n个点到原点的距离的平方并将距离平方及其坐标从小到大输出,你能帮他解决这个问题嘛。
输入描述:
第一行有一个整数n,表示点的个数。(0<n<10)
接下来n行,每行有两个整数x,y表示这个点的坐标。(-1000000<x,y<1000000)
输出描述:
输出n行。
每行包含三个数x,y,dis2表示该点的坐标及其距离的平方。
示例:
输入
5 1 2 2 3 3 4 4 5 5 6
输出
1 2 5 2 3 13 3 4 25 4 5 41 5 6 61
分析:根据题意可知dis2=x2+y2,题目要求使用冒泡排序方法进行升序排序,算法竞赛中排序一般直接使用sort()函数。我们可以把x,y,dis2通过结构体进行操作。
Code:
#include<iostream>
#include<algorithm> //sort()函数要使用algorithm头文件
using namespace std;
typedef long long ll; //怕dis2太大,直接开long long
struct point
{
ll x;
ll y;
ll dis2;
}p[11]; //题目中n的范围是0~10,多开几个防止数组越界
bool cmp(point a,point b)
{
return a.dis2<b.dis2; //设置排序方式,将dis2升序排序
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>p[i].x>>p[i].y;
p[i].dis2=p[i].x*p[i].x+p[i].y*p[i].y; //计算dis2
}
sort(p,p+n,cmp); //sort()排序
for(int i=0;i<n;i++)
{
cout<<p[i].x<<" "<<p[i].y<<" "<<p[i].dis2<<endl;
}
}
标签:std,匠心,cout,int,namespace,ACM,C++,using,include From: https://blog.csdn.net/weixin_52784450/article/details/136587584shy:能看到这里并学懂,说明你们已经踏上了ACM算法竞赛之路,不过只是刚刚入门,只学了些基础语法,后续会涉及到很多算法和函数,届时更能体会到算法竞赛的乐趣(≧∇≦)ノ。
hwjw:算法竞赛不用学指针吗?
shy:算法竞赛中基本不用指针,很多指针都可以用其他的方式来代替。比如图论题可以用数组或STL的vector等来代替。
xcx:好多函数不会用怎么办啊?
shy:不用担心,比如说7.7的sort()排序,之后会新建专题进行系统化讲解。
hwjw:学完这些基础语法,遇到题还是不会做怎么办呀?
shy:算法竞赛其实是一个积累的过程,多刷题会发现很多新的知识点,每做一道题就会有一份新的收获。随着时间的沉淀,积累的知识越来越多,经验也越来越多,到时候解题自然游刃有余。
xcx、hwjw:好耶好耶!感觉现在动力满满,有点迫不及待学习新的知识了!!