AcWing语法基础课笔记

1、编译环境

采用线上编译,地址:
https://www.acwing.com/file_system/file/content/whole/index/content/172575/

输出一个hello world

1
2
3
4
5
6
7
8
9
10
#include <iostream>

using namespace std;

int main()
{
cout <<"Hello World" << endl;

return 0;
}

先保存代码再点调试运行

2、C++代码一般格式

2.1常用头文件

1
2
#include <cstdio>
#include <iostream>

cstdio中包含printf和scanf
iostream中包含 cin和cout

2.2、using namespace std使用std命名空间

删掉这一句编译会报错

2.3、int main()函数入口

2.4、最后要return 0

3、作业和提交

作业要刷完嗷
https://www.acwing.com/activity/content/punch_the_clock/21/

4、C++基本语法

变量类型:
bool(true=1和false=0) 1B
char ‘c’,’a’,’’,’\n’ 1B
int (-2^31至+2^31-1) 4B
float 1.23 1.23e2(支持科学计数法) 有效位数6~7位 4B
double 15至16位有效数字 8B
long long (-2^63至263-1) 8B
long double 18至19位 12B/16B
1Byte=8bit

4.1定义变量

1
2
3
4
5
6
int a,b=2,c=b;
float d=1.5,e=1,f=1.235;
bool g=true,h=false;
char j='a',k ='b';
long long 1=1231341;
long double m=123.45;

4.2变量输出

1
2
3
int a, b;
cin >> a >> b;//输入
cout << a+b <<endl;

注意,提交的时候要先输入两个数据,再点运行
Accepted通过
Wrong Answer 答案错误
Time Limit Error 超时
Memory Limit Error 超内存
Segmentation Fault 数组越界
Compile Error 编译错误
Presentation Error 表示错误
注意打卡界面是markdown语法代码前面记得加4个`

4.2.1输出多个变量

1
2
3
int a, b;
cin >> a >> b;//输入
cout << a+b << ' ' << a*b <<endl;

4.3 scanf和printf

这两个函数是在 cstdio.h中的,记得加头文件

1
2
3
4
5
6
7
8
9
10
11
#include <cstdio>
#include <iostream>

using namespace std;
int main ()
{
int a,b;
scanf("%d%d",&a,&b);
printf("a+b=%d\na*b=%d\n",a+b,a*b);
return 0;
}

整数%d,浮点数%f,%.2f表示保留两位小数
字符%c,double %lf, long long %ll

4.4关于空格的读入

1.cin

1
2
3
cin >> a >> b;
printf ("%c %c",a,b);
//输入a c输出a c

2.scanf

1
2
3
4
scanf("%c%c",&a,&b);
printf("%c %c",a,b);
//输入ac输出a c
//输入a c输出a

可见cin可以自动过滤空格,且cin、cout的效率比scanf、printf低

4.5四则运算

加法a+b
出发a-b
乘法a*b
除法a/b
取余a%b 注意取余结果的符号只和前面有关

1
2
3
int a=5,b=-2;
printf("%d",a%b);
return 0;

结果为1

4.6变量类型强制转换

int→float
float→int(下取整,损失精度)
int←→char(ASCII码)

1
2
char c='A';
cout << (char)(c+32)<<endl;

输出结果为a

两个不同类型的变量之间运算,低精度会向精度高的一方转换

5、printf和c++中的判断结构

5.1 printf的用法

printf的格式化输出:想让每个输出占的宽度一定该怎么办?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

using namespace std;

int main()
{
int a=1;
int b=12;
int c=123;
int d=123456;
printf("%5d\n",a);
printf("%5d\n",b);
printf("%5d\n",c);
printf("%5d\n",d);
return 0;
}

输出结果:

1
2
3
4
    1
12
123
123456

可以发现结果是不足五个字符的话前面补空格,超出了不管,全部输出

如果想要左对齐怎么办?

1
printf("%5d\n",a);

修改为:

1
printf("%-5d\n",a);

输出结果:

1
2
3
4
1    
12
123
123456

现在是不足五位补空格,如果我们想补0该怎么办?

1
printf("%5d\n",a);

改为:

1
printf("%05d\n",a);

输出结果:

1
2
3
4
00001
00012
00123
123456

5.2浮点数如何固定长度?

1
2
double f = 12.34;
printf("%05.1lf",f);

输出为:

1
012.3

%05.1lf中的这一句,0表示的是不足5位的占零;5表示要输出5位;.1表示的是小数点后保留一位,lf是double对应的输出;
注意:小数点要占一位

5.3 if语句

基本的if语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

using namespace std;

int main()
{
int score;
cin >> score;
if (score>=60)
{
cout << "PASS" << endl;;
}
else
{
cout << "FAILED" << endl;
}
return 0;
}

注意,if和else之后不要加分号,加了有空语句
if和else后面只有一个句子的时候可以省略空格;

1
2
3
4
5
if (score>=60)
cout << "PASS" << endl;
else
cout << "FAILED" << endl;
return 0;

5.4判断语句的表示方式

大于等于:

1
2
3
4
5
6
大于 >
小于 <
大于等于 >=
小于等于 <=
等于 ==
不等于 !=

5.5 else if 的由来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cin score;
if (a > 90)
cout << "great" ;
else
if (a > 80)
cout << "good" ;
else
if (a > 70)
cout << "normal" ;
else
if (a > 60)
cout << "pass" ;
else
cout << "failed" ;

删去不必要的空格就能得到 if else

1
2
3
4
5
6
7
8
9
10
11
cin score;
if (a > 90)
cout << "great" ;
else if (a > 80)
cout << "good" ;
else if (a > 70)
cout << "normal" ;
else if (a > 60)
cout << "pass" ;
else
cout << "failed" ;

5.6 一道练习题

简单计算器输入两个数,以及一个运算符+-*/
输出两个数运算的结果
运算符为/且被除数为0时输出 Divided by zero !
运算符不是+-*/时输出 Invalid Operator

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

using namespace std;

int main()
{
double a,b;
char c;
cin >> a >> c >> b;
if (c=='+')
printf("%.1lf+%.1lf=%.1lf",&a,&b,&(a+b));
else if (c=='-')
printf("%.1lf-%.1lf=%.1lf",&a,&b,&(a-b));
else if (c=='*')
printf("%.1lf*%.1lf=%.1lf",&a,&b,&(a*b));
else if (c=='/')
{
if (b!=0)
printf("%.1lf/%.1lf=%.1lf",&a,&b,&(a/b));
else
printf("Divided by zero !");
}
else
printf("Invalid Operator");

return 0;
}

出现报错:
a.cpp:11:43: error: lvalue required as unary ‘&’ operand
11 | printf(“%.1lf+%.1lf=%.1lf”,&a,&b,&(a+b));
报错是因为 & 只能作用在变量上,不能作用在表达式上
我们多定义一个变量d来存放运算值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>

using namespace std;

int main()
{
double a,b,d;
char c;
cin >> a >> c >> b;
if (c=='+')
{
d=a+b;
printf("%.1lf+%.1lf=%.1lf",&a,&b,&d);
}
else if (c=='-')
{
d=a-b;
printf("%.1lf-%.1lf=%.1lf",&a,&b,&d);
}
else if (c=='*')
{
d=a*b;
printf("%.1lf*%.1lf=%.1lf",&a,&b,&d);
}
else if (c=='/')
{
if (b!=0)
{
d=a/b;
printf("%.1lf/%.1lf=%.1lf",&a,&b,&d);
}
else
printf("Divided by zero !");
}
else
printf("Invalid Operator");

return 0;
}

输入

1
12/41

输出:

1
0.0/0.0=0.0

感觉是cin出了问题,用scanf看看

1
scanf("%lf%c%lf",&a,&c,&b);

输出还是一样
我们在scanf后面加一句

1
cout<<a<<c<<b<<endl;

输入

1
12+14

输出结果

1
2
12+14
0.0+0.0=0.0

那问题知道出在哪儿了,就在printf的语句上,重新看了一下printf语法,···printf的变量不用&,···全部搞忘了,cout害人不浅啊,重新修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

using namespace std;

int main()
{
double a,b;
char c;
scanf("%lf%c%lf",&a,&c,&b);
if (c=='+')
printf("%.1lf+%.1lf=%.1lf",a,b,a+b);
else if (c=='-')
printf("%.1lf-%.1lf=%.1lf",a,b,a-b);
else if (c=='*')
printf("%.1lf*%.1lf=%.1lf",a,b,a*b);
else if (c=='/')
{
if (b!=0)
printf("%.1lf/%.1lf=%.1lf",a,b,a/b);
else
printf("Divided by zero !");
}
else
printf("Invalid Operator");

return 0;
}

输入

1
1.21334*14134.51532

输出

1
1.2*14134.5=17150.0

6、循环语句

斐波那契数列
f(1)=1,f(2)=1
f(n)=f(n-1)+f(n-2)
求f(n)
令a=f(1),b=f(2),c=f(3)=a+b,b+c作为f(4)的值代替a+b
从(a,b)→(b,c)需要:

1
a=b;b=c;
循环次数 a b
0 f(1) f(2)
1 f(2) f(3)
2 f(3) f(4)
n-1 f(n) f(n+1)

求斐波那契数列的第n项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
int main()
{
int a=1,b=1;
int n;
cin>>n;
int i=0
while(i<n-1)
{
int c=a+b;
a=b;
b=c;
i++;
}
cout<<a<<endl;
return 0;
}

循环的效率比递归更高

6.1 break和continue

break是直接跳过整个循环开始执行下面的语句,continue是跳过本次循环的后面内容,开始下次循环

6.2 打印菱形程序的快速方法

打印

1
2
3
4
5
  *  
***
*****
***
*

整个图形其实是一个n*n的正方形,有n²个元素,找到中心点
两点之间的距离是sqrt((x1-x2)²+(y1-y2)²)
曼哈顿距离:|x1-x2|+|y1-y2| (横坐标差值绝对值+纵坐标差值绝对值)
我们可以看到所有要打印的菱形距离中心点的曼哈顿距离都<=(n/2),n为阶数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int cx = n/2;
int cy = n/2;
for(int i = 0; i < n ; i++)
{
for(int j = 0; j < n ; j++)
{
if ((abs(i-cx)+abs(j-cy))<=n/2)
cout << "*" ;
else
cout << " "> ;
}
cout<<endl;
}

return 0;
}

6.4 while;if;for语句的多语句(和cin混搭)

1
2
3
while(cin>>n,n<=0>)
if(cin>>n,n<=0>)
for(;cin>>n,n<=0>;)

像这行代码,判断句里面有两个语句,最终是由最后一个语句来判断条件
所以可以一直执行输入数据的操作
cin只要有输入就会返回true

6.4 scanf在读入数据时不会自动过滤空格

1
2
cin>>a>>b;
scanf("%d%d",&a,&b);

输入数据为

1
6 1

cin输入的是6和1
scanf输入的其实是6和空格,所以需要调整

1
scanf("%d %d",&a,&b);

6.5scanf的格式化读入

f是format的意思,例如

1
2
scanf("A=%d,B=%d",&a,&b);
cout<<a<<""<<b;

输入

1
A=3,B=2

输出

1
3 2

7、数组

7.1数组初始化

1
2
3
4
5
int a[3]={0,1,2};
int b[]={0,1,2};
int c[5]={0,1,1};//定义了一个长度为5的数组,前三个为0,1,1后面的为0
char d[]={'a','b','c'};
int f[10]={0};//常用的初始化方式

7.2数组长度过长的问题

函数内部的变量(数组)会放进栈空间,栈空间一般默认为1M
如果在main函数内部定义int a[1000000]
则会占用 1000000*4=4000000B≈4000KB≈4MB
栈空间不足会报错
解决方法:定义在main函数外面,此时占用的是堆空间,没有限制

7.3旋转数组

1
int a[5]={0,1,2,3,4};

反转两次后的得到{3,4,0,1,2}
如何反转最快?
长度为n的数组翻转k次
把原数组分为a[0]~a[n-1-k]和a[n-k]到a[n-1]两个部分
再把整个数组翻转得到a[n-1] a[n-2] a[n-3]…a[2] a[1] a[0]
再分别反转两个部分 得到 a[n-k] a[n-k+1]…a[n-1] a[0] a[1]…a[n-1-k]
reverse函数在algorithm头文件里面,reverse(a,b)是翻转从a到b的数

7.4浮点数的比较

浮点数的存储不是精确的,一般认为x和y相差小于1e-6则相等

1
2
3
4
5
6
7
8
9
10
11
12
#include<iostream>
using namespace std;
const double eps = 1e-6

int main()
{
double x=1.23456789;
double a=x*x;
double b=sqrt(a);
if (fabs(x-b)<eps) puts("相等");//fabs是取绝对值的函数
return 0;
}

7.5求2的n次方存在数组中

比如把一个数 1234567891234 存进数组中,一般把从低往高存,这样方便加减乘运算时的进位运算
所以实际上应该是对应a[12]…a[4]a[3]a[2]a[1]a[0]
假如A[]={4,3,2,1,9,8,7,6,5,4,3,2,1}
数组可以很方便的进行大数据的加减乘
比如12345678912342的操作
可以对每一位分别
2,用一个新数组B[]来存储结果

1
B[0]=A[0]*2%10;

用一个变量t来存储进位

1
t=A[0]*2/10;

1
2
B[1]=(A[1]*2%+t)%10;
t=(B[1]*2+t)/10;

直到

1
2
B[n-1]=(A[n-1]*2%+t)%10;
t=(B[n-1]*2+t)/10;

最后还有可能会进位

1
B[n]=t;

7.4 高精度2的N次幂

1
2
3
4
5
6
7
8
#include<iostream>
using namespace std;
const int N =3010
int main()
{

return 0;
}
------ 本文结束 ------