程序框架
#include"bits/stdc++.h" //万能头文件
using namespace std;
int main(){
return 0;
}
输入输出
cout
:输出 cin
:输入
int
:定义整型变量
对于大部分编程语言来说,编写一个能够输出“Hello, World!”的程序往往是最基本、最简单的。因此,这个程序常常作为一个初学者接触一门新的编程语言所写的第一个程序,也经常用来测试开发、编译环境是否能够正常工作。
代码:
#include"bits/stdc++.h"
using namespace std;
int main(){
cout<<"Hello, World!";
return 0;
}
给定两个数a,b,求a和b的和。输入只有一行a和b,两个数之间用空格隔开,输出a+b的值。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
cout<<a+b;
return 0;
}
换行
endl
:换行 "\n"
=endl
cout<<"Hello, World!"<<endl<<"Hi!";
运行结果:
Hello, World!
Hi!
printf
:输出 scanf
:输入 double
:定义实数变量
表现形式 | 具体含义 |
---|---|
%d | 整形输出 |
%o | 八进制输出 |
%x | 十六进制输出 |
%u | 十进制输出无符号型(unsigned) |
%c | 输出字符 |
%s | 输出字符串 |
%f | 以小数形式输出实数 |
%e | 以指数形式输出实数 |
%g | 根据大小自动选择f格式或e格式,且不输出无意义的零 |
1.整形输出:int m =323; printf("%d,", m);
2.八进制输出
2.1 原数是八进制数的输出:int m =0256; printf("%o,", m);
2.2 原数不是八进制数的输出:int m =256; printf("%o,", m);
这里的256转换为八进制为400
3.十六进制输出
十六进制为0-9、a-f 表示数0-15
3.1 以“%x”形式,表示十六进制整数形式(小写)输出,无前导符0x
int m =323; printf("%x,", m);
3.2 以“%X”形式,表示十六进制整数形式(大写)输出,无前导符0x
int m =323; printf("%X,", m);
3.3 以“%#x”形式,表示十六进制整数形式(小写)输出,有前导符0x
int m =323; printf("%#x,", m);
3.4 以“%#X”形式,表示十六进制整数形式(大写)输出,有前导符0X
int m =323; printf("%#X,", m);
4.十进制输出无符号型(unsigned)
%d 与 %u 的区别:前者带符号,后者没有,而%u 可存储的正数范围比%d 大一倍
int m =323;
cout << endl << endl;
printf("%d,", m);
cout << endl << endl;
printf("%u,", m);
cout << endl << endl;
m = -323;
printf("%d,", m);
cout << endl << endl;
printf("%u,", m);
cout << endl << endl;
5. %c与%s 的输出
%c:单个字符,%s:字符串
定义:char c,string s
输入:scanf(“%c”,&c),scanf(“%s”,s)
输出:printf(“%c”,c),printf(“%s”,s.c_str())]
6. %f 的输出
%m.nf :表示总共输出 m 位,其中小数占 n 位,右对齐,不足m位则左端补空格,m 位包含小数点
float a = 323.323;
printf("%7.2f", a);
scanf的用法
scanf从缓冲区读取数据,每次读取一个数据,如果缓冲区中无内容,则出现堵塞,在运行窗口要求用户输入;
scanf(“%d%d”, &a, &b);
如果a和b都被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
如果遇到错误或遇到end of file,返回值为EOF。
且返回值为int型
scanf可以通过键盘输入数据到变量中,它的格式有以下两种
1.scanf(“输入控制符”,输入参数);
表现形式 | 具体含义 |
---|---|
%d | 读入十进制整数 |
%o | 读入八进制整数 |
%x/%X | 读入十六进制整数 |
%c | 读入一个字符 |
%s | 读入一个字符串 |
%f/%F/%e/%E/%g/%G | 用来输入实数,可以用小数形式或指数形式输入。 |
%u | 读入一个无符号十进制整数 |
h用于d,o,x前,指定为short | |
l用于d,o,x前,指定为long,用e,f 前指定为double |
2.scanf(“非输入控制符 输入控制符”,输入参数);
非控制符一定要原样输入,还有注意如果非输入控制符中有字符
的话,在输入的时候不要忘记切换到英文输入法来输入英文字符
在赋值的时候如果用中文输入法输入了‘ ,’,结果就成了这样
判断/分支结构
if
:如果 else if
:否则如果 else
:否则 char
:定义字符型变量
if(条件1){
条件1成立时执行这里
/*code*/
}
else if(条件2){ //条件一不成立执行这里
条件2成立时执行这里
/*code*/
}
... //可堆叠很多条件
else{ //以上都不成立执行这里
/*code*/
}
Ascii码
ASCII(American Standard Code for Information Interchange:美国信息交换标准代码)码是一套编码标准。
计算机中都是以二进制存储和表示数据的,ASCII码定义了二进制与字符的对应规则。
编码细分
0~31与127:控制字符或通信专用字符(不可显示);
32:空格;
48~57:数字;
65~122:大写和小写字母;
其余:标点、运算符号等。
常用Ascii码
字符 | Ascii |
---|---|
‘0’ | 48 |
‘A’ | 65 |
‘a’ | 95 |
运算符
位运算
位运算的运算分量只能是整型或字符型数据,位运算把运算对象看作是由进位组成的位串信息,按位完成指定的运算,得到位串信息的结果。
&(按位与)、|(按位或)、^(按位异或)、~ (按位取反)。
其中,按位取反运算符是单目运算符,其余均为双目运算符。
位运算符的优先级从高到低,依次为~、&、^、|,
其中~的结合方向自右至左,且优先级高于算术运算符,其余运算符的结合方向都是自左至右,且优先级低于关系运算符。
(1)按位与运算符(&)
按位与运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 & 0 = 0, 0 & 1 = 0, 1 & 0 = 0, 1 & 1 = 1。
即同为 1 的位,结果为 1,否则结果为 0。
例如,设3的内部表示为
00000011
5的内部表示为
00000101
则3&5的结果为
00000001
按位与运算有两种典型用法,一是取一个位串信息的某几位,如以下代码截取x的最低7位:x & 0177。二是让某变量保留某几位,其余位置0,如以下代码让x只保留最低6位:x = x & 077。以上用法都先要设计好一个常数,该常数只有需要的位是1,不需要的位是0。用它与指定的位串信息按位与。
(2)按位或运算符(|)
按位或运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 | 0 = 0, 0 | 1 = 1, 1 | 0 = 1, 1 | 1 = 1
即只要有1个是1的位,结果为1,否则为0。
例如,023 | 035 结果为037。
按位或运算的典型用法是将一个位串信息的某几位置成1。如将要获得最右4为1,其他位与变量j的其他位相同,可用逻辑或运算017|j。若要把这结果赋给变量j,可写成:
j = 017|j
(3)按位异或运算符(^)
按位异或运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0
即相应位的值相同的,结果为 0,不相同的结果为 1。
例如,013^035结果为026。
异或运算的意思是求两个运算分量相应位值是否相异,相异的为1,相同的为0。按位异或运算的典型用法是求一个位串信息的某几位信息的反。如欲求整型变量j的最右4位信息的反,用逻辑异或运算017^j,就能求得j最右4位的信息的反,即原来为1的位,结果是0,原来为0的位,结果是1。
(4)按位取反运算符(~)
按位取反运算是单目运算,用来求一个位串信息按位的反,即哪些为0的位,结果是1,而哪些为1的位,结果是0。例如, ~7的结果为0xfff8。
取反运算常用来生成与系统实现无关的常数。如要将变量x最低6位置成0,其余位不变,可用代码x = x & ~077实现。以上代码与整数x用2个字节还是用4个字节实现无关。
当两个长度不同的数据进行位运算时(例如long型数据与int型数据),将两个运算分量的右端对齐进行位运算。如果短的数为正数,高位用0补满;如果短的数为负数,高位用1补满。如果短的为无符号整数,则高位总是用0补满。
位运算用来对位串信息进行运算,得到位串信息结果。如以下代码能取下整型变量k的位串信息的最右边为1的信息位:((k-1)^k) & k。
移位运算
移位运算用来将整型或字符型数据作为二进位信息串作整体移动。有两个运算符:
<< (左移) 和 >> (右移)
移位运算是双目运算,有两个运算分量,左分量为移位数据对象,右分量的值为移位位数。移位运算将左运算分量视作由二进位组成的位串信息,对其作向左或向右移位,得到新的位串信息。
移位运算符的优先级低于算术运算符,高于关系运算符,它们的结合方向是自左至右。
(1)左移运算符(<<)
左移运算将一个位串信息向左移指定的位,右端空出的位用0补充。例如014<<2,结果为060,即48。
左移时,空出的右端用0补充,左端移出的位的信息就被丢弃。在二进制数运算中,在信息没有因移动而丢失的情况下,每左移1位相当于乘2。如4 << 2,结果为16。
(2)右移运算符(>>)
右移运算将一个位串信息向右移指定的位,右端移出的位的信息被丢弃。例如12>>2,结果为3。与左移相反,对于小整数,每右移1位,相当于除以2。在右移时,需要注意符号位问题。对无符号数据,右移时,左端空出的位用0补充。对于带符号的数据,如果移位前符号位为0(正数),则左端也是用0补充;如果移位前符号位为1(负数),则左端用0或用1补充,取决于计算机系统。对于负数右移,称用0 补充的系统为“逻辑右移”,用1补充的系统为“算术右移”。以下代码能说明读者上机的系统所采用的右移方法:
printf("%d\n\n\n", -2>>4);
若输出结果为-1,是采用算术右移;输出结果为一个大整数,则为逻辑右移。
移位运算与位运算结合能实现许多与位串运算有关的复杂计算。设变量的位自右至左顺序编号,自0位至15位,有关指定位的表达式是不超过15的正整数。以下各代码分别有它们右边注释所示的意义:
(0 << n)
(x >> (1 p-n)) & (0 << n)
new |= ((old >> row) & 1) << (15 – k)
s &= ~(1 << j)
for(j = 0; ((1 << j) & s) == 0; j ) ;
算术运算符
关系运算符
逻辑运算符
复合算式赋值的简写
a=a+b -> a+=b
a=a-b -> a-=b
a=a*b -> a*=b
a=a/b -> a/=b
a=a%b -> a%=b
自增和自减
自增:++
自减:–
a=a+1 -> a++/++a
a=a-1 -> a--/--a
b=a++ 相当于 b=a; a=a+1;
b=++a 相当于 a=a+1; b=a;
口诀:加号在前就先加,加号在后就后加。
循环
一)for循环
1、结构
作用:满足循环条件,执行循环语句
语法:for(起始表达式;循环条件;末尾表达式){循环语句;}
for (语句一; 语句二; 语句四){
语句三;
}
2、代码演示
输出1-10
#include"bits/stdc++.h"
using namespace std;
int main(){
for(int i=1;i<=10;i++){
cout<<i<<"\n";
}
return 0;
}
二)while循环
语法:while(条件表达式){循环语句;}
输出1-10
#include"bits/stdc++.h"
using namespace std;
int main(){
int i=1;
while(i<=10){
cout<<i;
i++;
}
return 0;
}
三)do-while循环
格式:
do{
循环语句;
}while(条件表达式);
1、先执行一遍do中的循环体
2、再判断条件表达式,成立则继续执行循环体
do-while循环至少执行一次循环体
break和continue
当用于循环体时,break语句的作用是使流程从循环体内跳出循环体,即提前结束循环,接着执行循环体下面的语句。
continue的作用为结束本次循环,即跳过循环体下面尚未执行的语句,接着进行下一次是否执行循环的判定。
总体来说,continue语句只结束本次循环,而不是终止整个循环的执行。而break语句则是终止整个循环过程,不再判断执行循环的条件是否成立。,不再判断执行循环的条件是否成立。
阶乘和次方
阶乘
!n 在数学上表示n的阶乘,表示1×2×3×4×…×n,3!就是1×2×3
特殊:0!=1,1!=1
代码:
int s=1;
for(int i=1;i<=n;i++){
s*=i;
}
次方
表示一个数连乘几次,在数学上写作3²,表示两个3相乘,也写作3^2
代码:
a^b:
long long s=1;
for(int i=1;i<b;i++){
s*=a;
}
或者:
cout<<pow(a,b);//pow函数可以计算次方,但返回的是double类型
要加cmath头文件
这里用了long long类型,因为次方的结果可能超出int范围
int 和 long long
int 最大为2³²-1,21亿多是10位数
long long 最大为9223372036854775807,是19位数
数组
一维数组
数组特点:
批量存储数据
放在一块连续的内存空间中
数组中每个元素都是相同数据类型
一维数组的定义方法:
int a[5];
int a[5]={10,20,30};//若数组赋值时有的没有,则系统会自动用0来填充
int a[]={1,2,3,4,5}//定义时不写数组元素长度,但必须赋值。
数组的命名规范与变量名命名规范一致,不要和变量重名
数组中下表是从0开始索引的
一维数组名的用途
1.可以统计整个数组在内存中的长度 sizeof(a)
2.可以获取数组在内存中的首地址 cout<<a<<endl; 一般为16进制数,可以强制类型转换int(a)转换成十进制。结果与cout<<int&a[0]<<endl;一致。
数组名是个常量(首地址),是不能再赋值的。
一维数组的遍历
for(int i=数组起始下标;i<=数组长度;i++){
cout<<数组名称[i];
}
例:
题目描述 Description
一节车厢可以装同一种类的物品,不同的车厢放不同种类的物品,现在要记录每节车厢内可以放下的物品的数量。
现在有 26 种种类不同的物品,请你输出每种物品的数量。
输入描述 Input Description
一行:分别输入26种物品各自的数量
输出描述 Output Description
一行:分别输出26种物品各自的数量
样例输入 Sample Input
22 77 94 87 61 74 91 93 29 13 41 10 94 58 57 100 56 22 73 63 96 30 32 32 91 49
样例输出 Sample Output
22 77 94 87 61 74 91 93 29 13 41 10 94 58 57 100 56 22 73 63 96 30 32 32 91 49
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int y[26];
for(int i=1;i<=26;i++){
cin>>y[i];
}
for(int i=1;i<=26;i++){
cout<<y[i]<<" ";
}
return 0;
}
二维数组
之前讲解的一维数组可以看作是一行连续的数据,只有一个下标,称为一维数组。在实际问题中有很多数据是二维的或多维的,因此C语言允许构造多维数组。多维数组元素有多个下标,以确定它在数组中的位置。本节只介绍二维数组,多维数组可由二维数组类推而得到。
二维数组的定义:
二维数组定义的一般形式是:
dataType arrayName[length1][length2];
其中,dataType 为数据类型,arrayName 为数组名,length1 为第一维下标的长度,length2 为第二维下标的长度。
我们可以将二维数组看做一个 Excel 表格,有行有列,length1 表示行数,length2 表示列数,要在二维数组中定位某个元素,必须同时指明行和列。例如:
int a[3][4];
定义了一个 3 行 4 列的二维数组,共有 3×4=12 个元素,数组名为 a,即:
a[0][0], a[0][1], a[0][2], a[0][3]
a[1][0], a[1][1], a[1][2], a[1][3]
a[2][0], a[2][1], a[2][2], a[2][3]
如果想表示第 2 行第 1 列的元素,应该写作a[2][1]
。
也可以将二维数组看成一个坐标系,有 x 轴和 y 轴,要想在一个平面中确定一个点,必须同时知道 x 轴和 y 轴。
一种是按行排列, 即放完一行之后再放入第二行;
另一种是按列排列, 即放完一列之后再放入第二列
在C++中,二维数组是按行排列的。也就是先存放a[0]
行,再存放a[1]
行,最后存放a[2]
行;每行中的 4 个元素也是依次存放。数组 a 为 int 类型,每个元素占用 4 个字节,整个数组共占用 4×(3×4)=48 个字节。
你可以这样认为,二维数组是由多个长度相同的一维数组构成的。
例:
一个学习小组有 5 个人,每个人有 3 门课程的考试成绩,求该小组各科的平均分和总平均分。
姓名 | Math | C++ | English |
---|---|---|---|
彬彬 | 80 | 75 | 92 |
杰哥 | 61 | 65 | 71 |
阿伟 | 59 | 63 | 70 |
int i, j; //二维数组下标
int sum = 0; //当前科目的总成绩
int average; //总平均分
int v[3]; //各科平均分
int a[5][3]; //用来保存每个同学各科成绩的二维数组
printf("Input score:\n");
for(i=0; i<3; i++){
for(j=0; j<3; j++){
scanf("%d", &a[j][i]); //输入每个同学的各科成绩
sum += a[j][i]; //计算当前科目的总成绩
}
v[i]=sum/5; // 当前科目的平均分
sum=0;
}
average = (v[0] + v[1] + v[2]) / 3;
printf("Math: %d\nCpp Languag: %d\nEnglish: %d\n", v[0], v[1], v[2]);
printf("Total: %d\n", average);
运行结果:
Math: 49
Cpp Languag: 39
English: 38
Total: 42
对于二维数组的初始化还要注意以下几点:
1) 可以只对部分元素赋值,未赋值的元素自动取“零”值。例如:
int a[3][3] = {{1}, {2}, {3}};
是对每一行的第一列元素赋值,未赋值的元素的值为 0。赋值后各元素的值为:
1 0 0
2 0 0
3 0 0
再如:
int a[3][3] = {{0,1}, {0,0,2}, {3}};
赋值后各元素的值为:
0 1 0
0 0 2
3 0 0
2) 如果对全部元素赋值,那么第一维的长度可以不给出。例如:
int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
可以写为:
int a[][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3) 二维数组可以看作是由一维数组嵌套而成的;如果一个数组的每个元素又是一个数组,那么它就是二维数组。当然,前提是各个元素的类型必须相同。根据这样的分析,一个二维数组也可以分解为多个一维数C++语言允许这种分解。
例如,二维数组a[3][4]
可分解为三个一维数组,它们的数组名分别为 a[0]
、a[1]
、a[2]
。
这三个一维数组可以直接拿来使用。这三个一维数组都有 4 个元素,比如,一维数组a[0]
的元素为a[0][0]
、a[0][1]
、a[0][2]
、a[0][3]
。
交换数组元素
交换数组中a[1][1]
和a[3][3]
两杯水,怎么交换他们,假如一杯是可乐,一杯是雪碧,不能像两杯都是水一样混合
这时候就要用一个空的临时杯来交换
现在,tmp里装上了可乐(a[1][1]
)
现在,a[1][1]
里装上了雪碧(a[3][3]
)
这样就完成了交换
代码实现:
int tmp;//创建临时变量
tmp=a[1][1];
a[1][1]=a[3][3];
a[3][3]=tmp;
swap函数可以用于交换两个数,用法:
swap(a[1][1],a[3][3]);
字符串
一.字符串与字符串数组
1 .printf 输出字符串:%s
,例如printf("%s\n", str);
等价于puts(s);
(包括换行符)
2 .字符串就是字符数组加上结束符’\0’
,因此可以使用字符串来初始化字符数组。
【注意】由于每个字符数组结尾含一个’\0’
字符,字符数组的长度至少要比字符串的长度多 1
3.字符数组:数组元素是字符的数组
char a[10]
4.字符数组的定义
char a[10]="hello";YES!
char a[5]="hello";NO!
一般定义字符时定义大一点
从下标0开始存储
5 .字符数组输入:
char s[100];
(1)scanf("%s", s);
//读入整个数组不加&,s数组名本身就是指针,遇到空格会停止
(2)scanf("%s", &s[1]);
//此时s[1]
是一个变量,要加&
(3)cin >> s + 1;
从下标1开始读入
【区分普通数组与字符串数组】: scanf 不能直接读入整数数组,可以读入字符串数组
6 .字符数组输出:
char a1[] = {'A', 'B', 'C'};
char a2[] = "ABCD";
cout << a1 << endl; //从A开始输出
cout << a2 + 1 << endl; //从B开始输出
cout << a3 + 2 << endl; //从C开始输出
7 . 输入输出注意事项:
(1)cin >> str;
// 输入字符串时,遇到空格、回车、结束符会停止(char和string都会停止)
char a[100];
cin >> a;
cout << a << endl;
输入:123 456
输出:123
(2)cout << str << endl;
// 输出字符串时,遇到空格或者回车不会停止,遇到’\0’
时停止
8 .读入一行:
(1)字符串类型:
char s[100];
fgets(s, 100, stdin);
//100表示最多读入的字符数,读入包括空格
【fgets不会过滤空格,结尾回车也不会过滤,都会计入长度】
(2)字符串类型:
char s[100];
cin. getline(s, 100);
//读到空格会停止
(3)string类型:
string s;
getline(cin, s);
//读入包括空格
9.常用函数
都要加头文件 cstring
(1)字符串长度函数
strlen(字符数组名);
char a[10]="hello";
cout<<strlen(a);
(2)复制函数
strcpy(字符数组名1,字符数组名2);//将字符串2复制给字符串1,返回字符串1
char a[10]="hello",b[10]='111';
strcpy(a,b);
cout<<a<<" "<<b;
字典序
从前往后比较ASCII码
在字典中越靠后的字典序越大
(4)字典序比较函数
strcmp(字符数组名1,字符数组名2);
如果字符串1>字符串2,返回正数
如果字符串1=字符串2,返回0
如果字符串1<字符串2,返回负数
string
string:字符串
头文件:string
1.定义:
string 字符串名;
string s="abc*/-+";
2.字符串的输入:
string s;
cin>>s;//cin只能输入不带空格的字符串
getline(cin,s);//可以读取带空格的
字符串可以用’+'来连接
string s1,s2;
cin>>s1>>s2;
cout<<s1+s2;
3.常用函数
(1)长度函数
字符串名.size();
string s="12345";
cout<<s.size();
(2)截取字符串
字符串名.substr(下标起点,截取长度);
string s1="12345",s2;
s2=s1.substr(0,3);
(3)擦除字符串
字符串名.erase(起始下标,擦除长度);
string s1="12345";
cout<<s1.erase(2,4);
(4)字符串插入函数
字符串名.insert(pos,t);//在pos下标插入字符串/字符t
string s1="1345",s2="2";
cout<<s1.insert(1,s2);
(5)字符串查找函数
字符串名.find(t,pos);//从pos下标开始查找字符串/字符t
//也可以简写为:
字符串名.find(t);//默认从0开始
//如果找到了,返回t首字母的下标
//如果没有,返回-1
string s1="1345",s2="2";
cout<<s1.find(s2);
4.字符串的遍历
string s;
cin>>s;
for(int i=0;i<=s.size()-1;i++){
cout<<s[i]<<" ";
}
//或
for(int i=0;i<s.size();i++){
cout<<s[i]<<" ";
}
你是否遇到过这种情况:
输入n,输入n个字符串,再输出,可…
还没输入呢,就结束了因为getline输入是连换行都读取的,所以正确写法应该是这样的:
#include"bits/stdc++.h"
using namespace std;
string s;
int n;
int main(){
cin>>n;
getchar();//接收一个字符,这里用于接收换行,头文件cstdio
//换成getline(cin,s);也行
for(int i=1;i<=n;i++){
getline(cin,s);
cout<<s<<"\n";
}
return false;
}
循环取位数
我们先来看一道题
题目描述 Description
任意输入一个正整数,求这个正整数的各位数字之和。
样例输入 Sample Input
【样例一输入】 123 【样例二输入】 2340 【样例三输入】 1234567
样例输出 Sample Output
【样例一输出】 6 【样例二输出】 9 【样例三输出】 28
![[Pasted image 20220805172835.png]]
首先要写出这一题, 必须要知道怎么把一个数的某一位取出来,这个不难想象
123%10=3(个位)
123/10%10=2(十位)
123/100%10=1(百位)
由此可得:
n%10 //n的个位
n/10%10 //n的十位
n/100%10 //n的百位
n/1000%10 //n的千位
...
理解这个,这题就不难了
Code:
#include<bits/stdc++.h>
using namespace std;
long long s=0,a;
int main(){
cin>>a;
while(a!=0){
s+=a%10;//求和
a/=10;//推到下一位
}
cout<<s;
return 0;
}