C++
1.你的第一段 C++ 代码
#include<bits/stdc++.h>
using namespace std;
int main() {
/*
第一段C++代码
*/
printf("%d\n",233+666);
return 0;
}
我们运行这段代码,就能得到 233+666 的结果 899 了。
我们来对这段代码的一些部分进行一些解读:
-
include
是一个预处理命令,用于引用头文件。头文件是一种包含功能函数、数据接口声明的载体文件,有了头文件,我们可以使用很多自带的功能。常用的头文件有iostream
、cstdio
、algorithm
等,这里的bits/std=c++.h
被称为万能头文件,它包含了几乎所有你能用到的功能,使用这个头文件就不需要写一大堆头文件了,在算法竞赛中使用这个头文件可以节省一些时间。 -
using namespace std;
表明我们使用了标准命名空间,C++ 中的标识符都定义在这个空间里。在算法竞赛中,我们可以默认我们代码的前两行都是在进行引用头文件和声明使用标准命名空间的工作。 -
main()
是主函数,所有的 C/C++ 代码都必须包含主函数,代码将从main()
函数开始进行。 -
大括号用于表示一些语句的集合,一对首尾呼应的大括号用于表示一个代码块。
-
/.../是注释,编译和执行的时候会忽略里面的内容。
-
printf()
是输出函数,用于格式化输出到屏幕。 -
return 0;
表示正常退出程序,不要return
一些奇奇怪怪的东西回去。
在 C++ 中每个语句必须使用 ; 分隔。我们注意到输出的内容就是 233+666 的值 ,我们不妨把 + 换成其他的四则运算符号,看看结果有什么不同。
我们发现当我们printf("%d\n",233/666);
结果是 0 ,这是因为 233 和 666 都是整型常量,此时 / 的含义是整除,那么如何让这个表达式变为实数除法捏。
2.常量和数据类型
常量是固定的值,是在程序运行中不会改变的值。如我们上面代码中的 233 、666 都是常量,是整型类型的常量。当然还有其他类型的常量,常量可以是任何基本数据类型。
下面是一些基本数据类型:
-
整数常量:
- 前缀:0o30(八进制表示),0x30(十六进制表示)
- 后缀:30l, 30L, 30ul
-
实数常量
- 十进制形式: 23.0 24.5 3.56789l
- 指数形式: 23E1 145e-1 356789e1
-
编译器根据表面形式来判断常量类型
- 30,40 为整型(默认int),30.0,40.0为浮点型(默认double)
- 'z' 'h' 'n' 'b'为字符型常量,"zhnb" 是一个字符串常量
我们现在知道了只需要将233 、666 换成 233.0 、666.0就可以了。我们测试一下发现还是不行,这里的原因在于printf
中的%d。
%d是格式占位符,控制输出整数。如果我们想输出实数,可以使用%lf占位符。
3.变量和读入
我们不满足程序只能用来算233 和 666 相加的结果,我们可能需要更强的功能,比如输入两个数计算他们的和。
#include<bits/stdc++.h>
using namespace std;
int main() {
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",a+b);
return 0;
}
-
int a,b;
是定义了两个变量,定义变量的格式为数据类型 变量名表;
可以一次定义多个变量,中间使用逗号隔开。我们可以在程序的任何位置定义变量,但是必须遵循先定义,后使用的规则。而且我们在主函数外定义的全局变量和在函数内部定义的局部变量也是有所不同的。 -
这里的
scanf()
是用于读入,我们可以发现和printf()
一样使用了%d占位符表示读入的是整数,但不一样的是在读入的变量前需要加一个&
。
还有一种特殊的变量叫做常变量,使用const
修饰符定义,定义方式为const 数据类型 变量名=常量值;
通过这种方式定义的变量是不能修改的,也可以视为常量。
上面讲的scanf()
和printf()
其实是 C++ 从继承自 C 语言的读入与输出函数,C++ 也有自己的面向对象方式的输入与输出cin,cout
,我们可以把上面的代码改为以下形式:
#include<bits/stdc++.h>
using namespace std;
int main() {
int a,b;
cin>>a>>b;
cout<<a+b<<endl;
return 0;
}
例题:https://www.luogu.com.cn/problem/P5704
4.操作符、表达式、常用函数
另外还有自增运算符++ 和自减运算符-- ,只能对变量使用。
当不同数据类型的量进行运算时,会发生数据类型的转换。如字符、bool转换为整数参与算数运算、整数和实数运算的时候会被转化为实数。C++ 的转换语法不像Java那么严格,我们甚至可以给一个整型变量赋实数值,因此需要注意强制类型转换。
-
Java风格,C风格: (double) a (int) (x+y) (int) 6.2%4
-
C++风格,把强制类型转换看作是函数,()作为参数:double(a), int(x+y) int(6) %4
运算符优先级:https://blog.csdn.net/caomin1hao/article/details/79510141
C++自带了一些常用的函数,可以简化我们的程序设计:
-
int abs(int x)
返回整数x的绝对值。 -
double fabs(double x)
返回实数x的绝对值。 -
double ceil(double x)
返回不小于x的最小整数,double floor(double x)
返回不大于x的最大整数。 -
double exp(double x)
返回\(e^x\)的值,double pow(double a,double b)
返回\(a^b\)的值。 -
double log10(double x)
返回\(\log_{10}x\)的值,double log(double x)
返回\(\log x\)的值。 -
double sqrt(double x)
返回\(\sqrt{x}\)的值。 -
sin,cos,tan,acos,asin
等三角函数,其中acos(-1)
常用于获取比较精确的\(\pi\)的值。
例题:https://www.luogu.com.cn/problem/P5708
5.分支结构
分支结构是程序设计中非常必要的结构,我们可以指定一个或多个评测条件,已经条件为真时的执行的语句(必需的)、条件为假时的语句(可选的)。
分支结构的基本形式是if:
if( 表达式 ) {
/*
表达式为真时执行的语句块
*/
}
else {
/*
表达式为假时执行的语句块
*/
}
当语句块仅有一个语句的时候,可以不使用大括号。
可以在语句块中嵌套子if语句,实现更复杂的逻辑判断。
还有一种表达式叫做三目表达式。也可以看做一种分支结果,其形式为表达式1?表达式2:表达式3
。当表达式1为真时,三目表达式的结果为表达式2,否则为表达式3。
例题:https://www.luogu.com.cn/problem/P5715
6.循环结构
C++ 中主要的循环方式有三种,while()
,do...while()
,for()
(用法和java完全一样),循环结构可以让我们多次执行同一个代码块,大大降低了编程难度。但循环使用不当会导致死循环,使得程序一直无法正常结束,大家在使用循环结构的时候需要注意。
while()
循环的格式为:
while( 表达式 ) {
/*
循环体,循环时执行的语句
*/
}
其逻辑结构为:
do...while()
循环与while()
类似,结构为:
do {
/*
循环体,循环时执行的语句
*/
}while( 表达式 );
逻辑结构为:
两者的区别在于while先判断条件在进入循环体,而do...while()则是先进入循环体再判断条件。
for()
循环专门用于初始化、测试和更新计数器变量,其结构为:
for (初始化;测试;更新)
{
/*
循环体,循环时执行的语句
*/
}
for 循环的第一行是循环头。在关键词 for 之后,括号内有 3 个表达式,用分号分隔(注意第 3 个表达式之后没有分号。
-
第一个表达式是初始化表达式,它通常用于将计数器初始化为其起始值。这是循环执行的第一个动作,只在进入循环前做一次。
-
第二个表达式是测试表达式。它以与 while 和 do-while 循环中的测试表达式相同的方式测试条件,并控制循环的执行。只要这个条件为 true,for 循环的主体将重复。与 while 循环一样,for 循环也是一个预测试循环,因此它在每次迭代之前判断测试表达式。
-
第三个表达式是更新表达式。它在每次迭代结束时执行。通常,这是一个递增循环计数器变量的语句。
例题:https://www.luogu.com.cn/problem/P1035
7.数组
例题:https://www.luogu.com.cn/problem/P3156
数组是同一类型的一组值(例如,10 个 char 或 15 个 in t) ,在内存中顺序存放。整个数组共用一个名字,其中的每一项称为一个元素,对应一个下标,下标从0开始,我们可以通过下标访问元素。C++规定,数组元素个数必须是常量,不能通过赋值修改数组长度。数组的基本定义方式为数据类型 数据名[数组大小];
其中数组大小必须是一个常量(其实变量也可以,但取决与编译器版本,不推荐使用)。
如我们定义int score[10];
。就定义了一个大小为10的数组,其元素为score[0],score[1]...,score[9]
。注意,没有score[10]
,因为我们定义的数组大小为 10,下表从 0 开始,0 到 9 就是这个数组的 10 个元素。
我们可以在定义数组的时候直接初始化:
int point[5] = {1000, 2, 3, 7, 50};
注意{}之间的值的数目不能大于在数组声明时在方括号[ ]中指定的元素数目。
也可以定义时省略数组大小,这样的话数组的大小就是{}之间的值的数目,如:
int point[] = {1000, 2, 3, 7, 50};
这两种方式定义出来的数组内容是完全相同的。
我们可以直接通过[下标]来访问数组中的元素:
#include<bits/stdc++.h>
using namespace std;
int a[105],n;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int sum=0;
for(int i=1;i<=n;i++)
sum+=a[i]*a[i];
printf("%d\n",sum);
return 0;
}
几道题目:
https://www.luogu.com.cn/problem/P1046
https://www.luogu.com.cn/problem/P1047
https://www.luogu.com.cn/problem/P1059