一:引言
- 为什么学习编程?
为了“搬砖”。
- 那为什么要打 “ACM”?
当然是为了更好地“搬砖”。
其实编程几乎已经成为当今大学生必备的一个技能,就像几年前掌握“EXCEL、WORD”一样;那么,你怎么在这些人中脱颖而出,特别是科班生,(哪个专业的人都会c++,那你出来干啥)?所以你就得打“ACM”——当然这不是充分必要条件,但是打“ACM”绝对是一条~~“不归路”~~,不会让你后悔的一条路,你会在大四感叹“辛亏俺当时打了ACM”。、
言归正传:
二:the “hello world” vision of c++
#include<iostream>
using namespace std;
int main()
{
cout<<"hello world"<<endl;
return 0;
}
这样第一个程序就写好了。
接下来我们开始正式入门c++
三:简单介绍一下c++程序结构
还是拿 hello world 举例子
#include<iostream>
这个学名叫做“头文件”,其实就是一个工具箱,里面的好多东西,c++创始人或者一些大佬(就那些看似是艺术家的美国老头)给你写好了,你只需要会用就行。不同的头文件会包含不同的工具,但是有一个万能头文件#include<bits/stdc++.h>
,它包含几乎所有我们竞赛要用到的头文件;但是千万不要在课堂上用。
using namespace std;
这个和上一个差不多,学名叫做“命名空间”,也是人家写好了的东西,直接用就行。
main
一条程序的入口,非常重要,程序就是从这个开始执行的,而且一个程序只能由一个main
函数。
return 0
程序结束的标志,其实新标准可以选择不写。
先暂时了解这么多,初学阶段没有必要深究,只需要写程序的时候写不错。
四:变量类型(ACM常用的)
变量:程序中用来存储数据的
类型 | 存储大小 | 值范围 |
---|---|---|
bool | 1 字节 | true(1)或者false(0) |
char | 1 字节 | - 2 7 2^7 27 到 2 7 − 1 2^7-1 27−1 或 0 到 2 8 2^8 28 (不同编译器不同) --ASCII码 |
int | 4 字节 | -
2
31
2^{31}
231 到
2
31
2^{31}
231-1转化成10 进制,大概在1e9 级别 |
long long | 8 字节 | -
2
63
2^{63}
263 到
2
63
2^{63}
263-1转化成10 进制,大概在1e18 级别 |
unsigned long long | 8 字节 | 0 0 0 到 2 64 2^{64} 264 |
double | 8 字节 | 2.3E-308 到 1.7E+308 |
long double | 16 字节 | 3.4E-4932 到 1.1E+4932 |
变量的使用:
int a = 0,b = 1;
int a,b; //如果不初始化,编译器可能会随机赋值。
double a,b;
bool flag = false;
bool flag = 1;
五:输入输出
对于一个变量,你既可以在程序中手动赋值,也可以从键盘中读入。
1.C
版本 ——scanf
、printf
格式化输入输出
格式 | 解释 | 读入类型 |
---|---|---|
%c | 单个字符:读取下一个字符。 | char |
%d | 十进制整数 | int |
%x、%X | 十六进制整数。 | int |
%lld | 十进制整数 | long long |
%f | 浮点数 | double |
- 输入
int a;
scanf("%d",&a);
double b;
scanf("%f",&b)
int c;
scanf("%X",c);
//格式化输入
//假如题目要求你读入a,b,c三个数字,计算加和,但是给出的样式是
1,2,3
6
int a,b,c;
scanf("%d,%d,%d",&a,&b,&c);
- 输出
//从键盘中读入一个数字,并输出
int a;
scanf("%d",&a);
printf("%d",a);//注意,输入有&,输出没有
//格式化和scanf是差不多的。
//如果是输出两个,以空格或者,隔开
int a,b;
printf("%d %d",a,b);
printf("%d,%d\n",a,b);
//`\n`——换行符
//顺便提一句,在程序里出现的所有标点符号尽量使用英文,因为。。。
//双引号引起来的可以使用中文,其他地方使用中文符号,你是编译不过去滴。
//新手一般常常犯这个错误,找了半天,程序逻辑没有问题,一度怀疑人生,而且你还用的是`VC++6.0`
//而且你英语还不好,还看不懂人家给你提示的错误;然后你就被劝退了
//常常遇到的保留小数的问题
double a,b;
scanf("%f%f",&a,&b);
//保留两位小数
printf("%.2f %.2f\n",a,b);
2.c
++版本
相比之下,c++
输入输出就略微简单些了
int a,b;
cin>>a>>b;
cout<<a<<" "<<b<<endl;
//这里的endl相当于`\n`,换行符
double a,b;/char a,b;
cin>>a>>b;
//虽然麻烦,但是c++也可以实现输出保留几位小数
cout<<fixed<<setpresion(2)<<a<<endl;
注意:
cin
遇到空格或者换行符会停止,所以要灵活根据题目输入要求选择不同的输入方式,事半功倍。
- 不同点
速度不同,虽然cin
可以通过以下的几行代码加快速度。
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
但是,当数据范围达到1e5
乃至1e6
级别,还是凸显出C
语言的优势——快。
为什么要追求速度,因为我们竞赛的题目都要求要在秒级跑完,最多的也就是几乎到10000ms
,所以说如果你不重视你程序的时间复杂度
,你就会得到:(不过T着T着就A了)
六、运算符
1.算术运算符
加减乘除 取模 自增 自减
int a = 10,b = 11;
int c = a + b;// 21
c = a - b; // -1
c = a * b; // 110
c = b % a; // 1
//除法
//正常来讲 11 ➗ 10 应该等于 1.1.
//但是在计算机中,如果 a,b 都定义成整型变量,那么 a/b 会将得到的结果自动向下取整
c = a / b; // =1
//如果想得出1.1
double a = 10,b = 11;
double c = a/b;
//或者
int a = 11,b = 10;
double c = a*1.0/b;
//不要问为什么,这是美国佬定的标准
关于自增,自减,是不少同学学习 C C C 语言遇到的第一个坎,其实根本没有那么玄乎,就是自身加一,自身减一,但是由于和其他运算结合的时候,优先级不同,所以 ++a, 和 a++ 会返回不同的结果,我觉得没有必要看课本上说的那些东西,就是说他们单独(一定是单独)出现时,作用是一样的。
2.关系运算符
比较大小,或者等于不等于
运算符 | 描述 |
---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 |
3.逻辑运算符
在计算机中不是真就是假,不存在“没有绝对的真,没有绝对的假”这一说法。
运算符 | 描述 |
---|---|
&& | 称为逻辑与运算符。如果两个操作数都 true,则条件为 true。 |
|| | 称为逻辑或运算符。如果两个操作数中有任意一个 true,则条件为 true。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态,如果条件为 true 则逻辑非运算符将使其为 false。 |
- 短路特性
||
会拥有一个“短路特性”,a,b
是一个表达式,如果 a
的逻辑值为 1
,那么将直接返回 true
,表达式 b
将不再计算。
4.位运算符
计算机中所有的数据都是以二进制存储的。
位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
&
:都为 1
,结果才为 1
。
|
:有一个为 1
,结果就为 1
。
~
:0
变成1
,1
变成0
。
^
:不同为1
,相同为0
。
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假设变量 A 的值为 60,变量 B 的值为 13,则:
60:0011 1100
;
13:0000 1101
;
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与操作,按二进制位进行"与"运算。 | (A & B) 将得到 12,即为 0000 1100 |
| | 按位或运算符,按二进制位进行"或"运算。 | (A | B) 将得到 61,即为 0011 1101 |
^ | 异或运算符,按二进制位进行"异或"运算。不同为1,相同为 0 | (A ^ B) 将得到 49,即为 0011 0001 |
~ | 取反运算符,按二进制位进行"取反"运算。 | (~A ) 将得到 -61,即为 1100 0011 |
<< | 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 | A << 2 将得到240,即为 1111 0000 |
>> | 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 | A >> 2 将得到 15,即为 0000 1111 |
5.赋值运算符
运算符 | 实例 |
---|---|
= | C = A + B 将把 A + B 的值赋给 C |
+= | C += A 相当于 C = C + A |
-= | C -= A 相当于 C = C - A |
*= | C *= A 相当于 C = C * A |
/= | C /= A 相当于 C = C / A |
%= | C %= A 相当于 C = C % A |
<<= | C <<= 2 相当于 C = C << 2 |
>>= | C >>= 2 相当于 C = C >> 2 |
&= | C &= 2 相当于 C = C & 2 |
^= | C ^= 2 相当于 C = C ^ 2 |
|= | C |= 2 相当于 C = C | 2 |
6.其他运算符
- 三目运算符
a?b:c
a
,
b
,
c
a,b,c
a,b,c 均可为表达式
如果 a a a 的逻辑值为 1 1 1,则执行 b b b ; 否则执行 c c c 。
- 取地址符 & \& &
int *a = &p;
7.各种运算符的优先级
类似于,小学学过的,先算乘除,后算加减,有括号的,先算括号。
两种办法:~~1.记表;~~2.加括号。
在做题中可能会遇到的问题:
1.溢出
就是你想表示的数字不在该变量类型所能表示的范围。
例如:
int a = 2147483647(2^31-1);
int c = a + 100;
解决办法就是用 l o n g l o n g long ~long long long 。
实际做题过程中,会牵扯到数据范围的问题,
i
n
t
int
int 大概在
1
e
9
1e9
1e9 ,
l
o
n
g
l
o
n
g
long~long
long long 大概在
1
e
18
1e18
1e18 的范围内,所以看到
1
e
9
1e9
1e9 的范围的时候,你第一想法应该是开
l
o
n
g
l
o
n
g
long ~long
long long ,
1
e
18
1e18
1e18 更不用说了,1e5
你就应该稍微估计一下了,否则的话——“爆ll了”。
2.类型转换
这一部分其实最常用的是
A
S
C
I
I
ASCII
ASCII 码的处理。‘a’ 对应的是 0110 0001
——97,‘A’ 对应的是 0100 0001
——65
,’0‘ 对应的是0011 0000
——48
。
char test = 'a';
cout<<test<<endl;
cout<<int(test)<<endl;
for(int i = 1;i <= 10;i ++){
cout<<(test+i)<<endl;
}
还有一个比较常用的技巧就是把 int
转化为 long long
int a,b;
cin>>a>>b;
long long c = a*1ll + b*1ll;
七:条件控制语句
- 伪代码
if(表达式结果为真){
内容1;
}
else{
内容2;
}
- e x a m p l e example example
int a;
cin>>a;
if(a <20 && a > 10){
cout<<a<<endl;
}
else {
cout<<a+10<<endl;
}
也可以多个:
int a;
cin>>a;
if(a < 30 && a > 20){
cout<<"1:"<<a<<endl;
}
else if(a >= 10){
cout<<"2:"<<a<<endl;
}
else {
cout<<"3:"<<a<<endl;
}
前面讲到的逻辑运算符,常常作为 if
(表达式) 的判断条件。
- 例子1
输入三个数,输出最大的那个。这是某年的新生赛的签到题,很多人没签上。。。
先思考一下该怎么做 ?
int a,b,c;
cin>>a>>b>>c;
int ans = a;
if(ans <= b){
ans = b;
}
if(ans <= c){
ans = c;
}
cout<<ans<<endl;
- 例子2
裁判规定,总分100分;
获得92.8分及92.8分以上的选手获得金牌;
在92.8分以下但在85.6分及85.6分以上的选手获得银牌;
在85.6分以下,但在82.1分及82.1分以上的选手获得铜牌;
分数在82.1分以下的选手不获奖。
请从键盘读入一名选手的分数,判断他应该获得哪个奖项?
如获得金牌,请输出“jin”,银牌请输出“yin”,铜牌请输出“tong”,没有获得奖项请输出“sorry”。
#include<iostream>
using namespace std;
int main()
{
double g;
cin>>g;
if(g >= 92.8){
cout<<"jin"<<endl;
}
else if(g >= 85.6){
cout<<"yin"<<endl;
}
else if(g >= 82.1){
cout<<"tong"<<endl;
}
else{
cout<<"sorry"<<endl;
}
return 0;
}
- 例子3
输入年份,判断是否为闰年。
如果是,则输出 “yes” ,否则输出 “no” 。
提示:闰年的判断有两个条件,只需满足一个即可
1.能够被4整除但不能被 100 整除的为闰年;
2.能够被 400 整除的为闰年;
int year;
cin>>year;
if((year%4 == 0&&year%100!=0)||(year%400==0)){
cout<<"yes"<<endl;
}
else {
cout<<"no"<<endl;
}
八:循环控制语句
1. while
循环
伪代码:
while(表达式 == true){
执行内容;
}
int a = 10;
// while 循环执行
while( a < 20 ){
cout << "a 的值:" << a << endl;
a++;
}
- 死循环
int a = 0;
while(1){
a++;
cout<<a<<endl;
}
2. for
循环
伪代码:
for( a; b ; c )
{
执行内容;
}
a 初始化;
b 判断条件;
c 每执行完一次循环里的内容后,执行一次
所以执行顺序是:
a->b->执行内容->c->b->执行内容->c->b.......
for(int i = 1;i <= 10;i ++){
cout<<i<<" ";
}
cout<<endl;
1 2 3 4 5 6 7 8 9 10
for(int i = 1;i <= 10;i += 2){
cout<<i<<" ";
}
cout<<endl;
1 3 5 7 9
可以缺省:
int i = 0;
for( ;i <= 10;i ++){
cout<<i<<endl;
}
for(int i = 1;i <= 10; ){
cout<<i<<endl;
}
//死循环
for(int i = 1; ;i ++){
cout<<i<<endl;
}
for(;;;){
}
- b r e a k break break 语句
如果在循环过程中,发现不满足条件了,直接跳出整个循环
for(int i = 1;i <= 10;i ++){
cout<<i<<endl;
if(i > 5){
break;
}
cout<<"***"<<endl;
}
1
***
2
***
3
***
4
***
5
***
6
- c o n t i n u e continue continue 语句
循环中某一次满足了条件,不再执行该语句之后的内容,直接进入下一次循环。
for(int i = 1;i <= 10;i ++){
cout<<i<<endl;
if(i == 5)
continue;
cout<<"***"<<endl;
}
1
***
2
***
3
***
4
***
5
6
***
7
***
8
***
9
***
10
***
好了,我们来写一个经典 9x9
乘法表
for(int i = 1;i <= 9;i ++){
for(int j = 1;j <= i;j ++){
cout<<j<<" * "<<i<<" = "<<j*i<<"\t";
}
cout<<endl;
cout<<endl;//空行
}
九:输入问题
1.多组输入
输入包含一系列的a和b对,通过空格隔开。一对a和b占一行。
int a,b;
//C版本
while(scanf("%d %d",&a,&b)!=EOF){
printf("%d\n",a+b);
}
//C++版本
while(cin >> a >> b){
cout << a + b << endl;
}
2.t
组样例
第一行是一个整数t,表示后面会有t行a和b,通过空格隔开。
int t;
cin>>t;
while(t--){
int a,b;
cin>>a>>b;
}
//这个对于还要额外输出比较好用。
//Case #1:
for(int i = 1;i <= t;i ++){
int a,b;
cin>>a>>b;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QTIXgB9p-1632487174657)(https://i.loli.net/2021/09/24/oOn81WeuEkaH65l.png)]
十:一道思维题
if((a==0)&&(b==0)) cout<<0<<endl;
else if((a==b)||(a==-b)) cout<<1<<endl;
else if((abs(a-b)%2)==1) cout<<-1<<endl;
else cout<<2<<endl;