课程方向:
知识点主要面向小学**6年级+**的少儿编程 C++ 课程,适用于信奥赛选拔;
课程比较适合理工科父母的亲子互动,教培机构老师的备课参考;
特别注意①:C++ 课程 只有启蒙这一套是 小学阶段适合,后续全部中学;
特别注意②:C++ 课程 仅有本套课程 理工科家长还能亲子,后续只推荐教培老师学习;
特别注意③:虽然是 C++ 编程课程,但和 C++ 几乎没有关系,如何理解?
知识点规划:
启蒙阶段(本套):
后续阶段(非本套):
详情参考:
我会做到哪?
下载安装:
安装后推荐皮肤和设置,并根据自己的喜好调整,深色比较护眼:
(https://cdn.limfx.pro/-img-9dc95fbc-f7b6-4ae0-b095-037cbda041eb-articles-9714a544-0efe-455f-bfbf-1073e7c0692f-articelcontent-fc73af3b-875b-4bd6-b0fb-cabf45a47336/image-20231116112324684.png)
(https://cdn.limfx.pro/-img-9dc95fbc-f7b6-4ae0-b095-037cbda041eb-articles-9714a544-0efe-455f-bfbf-1073e7c0692f-articelcontent-9ed2ee1c-341a-4950-9414-d89df4c43227/image-20231116113611362.png)
第一个C++程序:
#include <iostream>
using namespace std;
int main()
{
cout << "我的第一个C++程序!";
return 0;
}
程序详解:
真正需要理解的就一行:cout << "我的第一个C++程序!";
其余的代码部分,全员基本格式,无须理解,做成模板自动即可;
(https://cdn.limfx.pro/-img-9dc95fbc-f7b6-4ae0-b095-037cbda041eb-articles-9714a544-0efe-455f-bfbf-1073e7c0692f-articelcontent-1475b7dd-46f5-41be-b7db-627a1d21457a/image-20231116160236858.png)
什么是变量?变量就是一个可以存储东西的存储罐,具体特性如下:
(https://cdn.limfx.pro/-img-9dc95fbc-f7b6-4ae0-b095-037cbda041eb-articles-9714a544-0efe-455f-bfbf-1073e7c0692f-articelcontent-197ce1ed-d7f9-4ea3-a9a0-934bdbb22db9/2-1.png)
那么,如何通过编程来实现变量的声明呢?
// 声明一个变量a,类型是整数
int a;
// 注意1:= 不是等于的意思,是赋值的意思
// 注意2:阅读代码从右边向左边阅读,意为:将数字123赋值给变量a
a = 123;
// 输出变量a
cout << a;
从 a=123 的例子中,a是变量名,但变量的名字有什么要求?需要注意哪些规则?能乱起吗?
变量名只能是:a-z、A-Z、0-9以及下划线组成;
变量名第一位不可以是数字;
变量名不可以是 C++ 关键字:比如 int main 之类的;
变量需要定义后才可以使用:int a; a = 123;
变量名区分大小写,A和a不同;
为了让变量名更加的有可读性,比如:你的名字:
// 声明一个字符串
string yourName;
// 字符串类型,需要双引号包含
yourName = "你的名字";
cout << yourName;
虽说叫做四则运算,但其实运算符往往不止加减乘除这四种:
运算 | 符号 | 格式 |
---|---|---|
加 | + | 1 + 1 |
减 | - | 2 - 1 |
乘 | * | 3 * 4 |
除 | / | 6 / 2 |
求余 | % | 10 % 7 |
累加 | ++ | i++ |
累减 | -- | i-- |
在编程语法中乘法 x 用 ***** 号代替,除法 ÷ 用 / 代替。
// endl 表示换行 Ctrl + D复制一行
cout << 1 + 1 << endl;
cout << 3 - 2 << endl;
cout << 4 * 5 << endl;
cout << 9 / 7 << endl;
cout << 7 % 3 << endl;
如果想让用户在键盘输入内容,可以使用 cin 关键字;
// 同时声明两个整型变量
int a,b;
// 输入两个数,并赋值给a和b
// 注意:同时输入a和b时,中间需要用空格键隔开
cin >> a >> b;
// 打印a+b的和
cout << a + b;
所谓的OJ系统,即:用于竞赛编程中,海量刷题的工具系统;
这里推荐两个刷题的OJ平台:
这里摘一段博宜答题须知:
在首页直接输入题号:B2002,可直接进入题目页面;题号不区分大小写;
或者在右侧,有一个 题单 >> 【入门1】顺序结构 >> 题目列表 >> B2002 Hello,World!
开始读题
在 小熊猫C++ 编写代码,并运行结果
将代码复制,回到答题页,选择 提交答案
选择 C++ 标准 ,最近的就行,提交测评
出现全部都是 绿色AC,表示正确
#include <iostream>
using namespace std;
int main() {
cout << "Hello,World!";
return 0;
}
在首页直接输入题号:1000,可直接进入题目页面;
或者在右上角 题单 >> 官方题单 >> 基本运算 >> 1000;
答题和洛谷一样,不再赘述:
#include <iostream>
using namespace std;
int main() {
int a,b;
// 注意输入的变量 空格隔开
cin >> a >> b;
// 输出和
cout << a + b;
return 0;
}
类型名 | 类型声明 | 解释说明 |
---|---|---|
整型 | int | -2147483648 到 2147483647 的范围的整数 |
长整形 | long long | 比上面大很多很多,这里装不下,具体搜索 |
字符型 | char | 赋值只能是一个字符,比如 'A',必须用单引号,双表示字符串不是字符 |
浮点型 | float | 也叫实型或小数型,38位以内的小数,只保留6为有效数字 |
其实还有很多类型,暂时先理解这几个,后续用到的再单独讲解;
// 字符型,切记是单引号
char ch = 'a';
// 长整形 long long b = 100000000000000000; // 浮点型,只能六位 float c = 3.1415926; cout << b << endl; cout << ch << endl; cout << c << endl; return 0;
### 2. 类型转换
- 这里我们只探讨整数和小数之间的转换,其它的放到以后;
- 类型转换分为两种:隐式转换和强制转换;
```c++
// 两边都是整数,结果也是整数:1
cout << 8 / 5 << endl;
// 两边有一边是浮点,结果是浮点:1.6
cout << 8.0 / 5 << endl;
// 强制转换浮点,float()是转换函数,将整数转换成浮点数,8叫做参数
cout << float(8) / 5 << endl;
// 强制转换整型
cout << int(3.14 * 5.25) << endl;
首先要引入相关库:
其次使用 setprecision(n) 函数 来设置保留小数点的位数;
// 输出保留的小数点
// fixed可以在缺少的位数补零,这样就精确保证2位
cout << fixed << setprecision(2) << 3.1415926;
// 声明三个整型变量
int n, a, x;
// 输入三个数并赋值
cin >> n >> a >> x;
// 计算
cout << n - x * a;
// 三个整型变量
int m, n, s;
// 输入
cin >> m >> n >> s;
// 求出高度
int h = s / n;
// 计算
cout << m * h;
// 5个整数
int a, b, c, d, e;
// 输入
cin >> a >> b >> c >> d;
// 全部转换到分钟,然后 第二段时间 - 第一段时间
e = (c * 60 + d) - (a * 60 + b);
// 计算
cout << e / 60 << " " << e % 60;
// 三个整数
int x, y, n;
float a;
cin >> x >> y >> n;
// 总 - 计算用了多少钱
a = n - (x * 1 + y * 1) * 0.9;
// 输出,并保留1位
cout << fixed << setprecision(1) << a;
// t毫升
float t;
// n同学
int n;
// 输入
cin >> t >> n;
// 每个人分得多少毫升,保留三位
cout << fixed << setprecision(3) << t / n << endl;
// 一共需要多少杯子
cout << n * 2 << endl;
// 花圃网格行列数
float n, total, pink;
cin >> n;
// 有多少块
total = n * n;
// 粉色数量, 中间一行一列为:n + n - 1 + 4 (四边)
pink = n + n + 3;
// 求比例
cout << fixed << setprecision(1) << pink / total * 100;
// 输出百分号
cout << "%";
// 三项成绩
int a, b, c;
// 输入
cin >> a >> b >> c;
// 计算
cout << a * 0.2 + b *0.3 + c * 0.5;
// 输入一个四位整数
int a, qian, bai, shi, ge;
cin >> a;
// 拆位
qian = a / 1000;
bai = a / 100 % 10;
shi = a / 10 % 10;
ge = a % 10;
// 倒序
// 这里有一个问题:如果 cout << ge << shi << bai << qian;
// 会有一个测试点无法通过;因为第二个样例中,1600,会去掉零,所以需要通过加整,而不是连整;
cout << ge * 1000 + shi * 100 + bai * 10 + qian;
对于格式化输出,本节课将学习两个函数 scanf() 、 printf() 来取代之前的cin和cout方法;
int a = 1, b = 2;
// cout
cout << a << " + " << b << " = " << a + b;
cout << endl;
// printf
printf("%d + %d = %d", a, b, a + b);
printf() 函数极其方便的原因,它可以先按照自己的输出格式,先写出来,不需要头脑翻译;
然后把需要替换成变量的部分,用 %d 来表示即可,而后续对应的位置换成变量或表达式运算即可;
%d 这里表示占位的内容 是 整型,也有各种其它的占位符,这里罗列出常用的几个:
占位控制符 | 说明 |
---|---|
%d | 整数 |
%f | 浮点数(float) |
%c | 字符 |
%s | 字符串 |
最终的语法结构如下:
printf(格式控制符, 占位替换列表)
从上面例子中,我们使用 scanf() 函数来控制输入:
int a, b;
// scanf
scanf("%d %d", &a, &b);
// printf
printf("%d + %d = %d", a, b, a + b);
先了解下输入参数的格式需求:
scanf(格式控制符, 地址集)
暂时没有办法解释这个地址是什么意思?举个并不恰当但好理解的说明:
在使用 printf() 时,我们需要输出各种特殊字符,比如百分号,换行,以及场宽精度问题等:
符号 | 说明和示例 |
---|---|
\\ | 输出一个斜杠,printf("\\"); |
\n | 换行,printf("\n"); |
%% | 百分号,printf("%"); |
数字 | 场宽,printf("%3d%5d"); |
小数 | 精度,printf("%.2f", 3.1415926); |
// 格式化
printf("%%\\\n");
// 场宽
printf("%3d%5d\n", a, b);
// 精度
printf("%.2f\n", 3.1415926);
// 场宽+精度
printf("%8.2f", 3.1415926);
// 输入一个浮点数,只有一位小数
float a;
int b, qian, bai, shi, ge;
scanf("%f", &a);
// 各个位进位
b = a * 10;
// 拆位
qian = b / 1000;
bai = b / 100 % 10;
shi = b / 10 % 10;
ge = b % 10;
// 合并输出
printf("%d.%d%d%d", ge, shi, bai, qian);
// 四位整数
int a, qian, bai, shi, ge;
cin >> a;
// 拆位
qian = ((a / 1000) + 5) % 10 ;
bai = ((a / 100 % 10) + 5) % 10;
shi = ((a / 10 % 10) + 5) % 10;
ge = ((a % 10) + 5) % 10;
// 输出倒序,本题没有要求必须是整型去零,所以,直接拼装可过
printf("%d%d%d%d", ge, shi, bai, qian);
布尔类型的值,是专门用于各种表达式的判断,只存在两种值:
// 布尔类型,只有两种值:true和false
// true 表示成立, false 表示不成立
// true 输出为1, false 输出为 0
bool a = true;
bool b = false;
cout << a << endl;
cout << b << endl;
名称 | 关系运算符 | 表达式返回值 |
---|---|---|
大于 | > | 成立返回 true(6 > 5),否则为 false(6 > 7) |
小于 | < | 成立返回 true(6 < 8),否则为 false(6 < 5) |
等于 | == | 成立返回 true(6 == 6),否则为 false(6 == 7) |
大于等于 | >= | 成立返回 true(7 >= 6),否则为 false(7 >= 8) |
小于等于 | <= | 成立返回 true(6 <= 6),否则为 false(6 <= 5) |
不等于 | != | 成立返回 true(6 != 5),否则为 false(6 != 6) |
// 返回 true(1) 和 false(0)
cout << (6 > 5) << endl;
cout << (6 > 7) << endl;
cout << (6 < 7) << endl;
cout << (6 == 6) << endl;
cout << (6 == 7) << endl;
cout << (6 >= 4) << endl;
cout << (6 != 6) << endl;
cout << (6 != 5) << endl;
除了关系运算符之外,还有一种叫做逻辑运算符,具体如下:
名称 | 逻辑运算符 | 表达式返回值 |
---|---|---|
&& | x && y | 表示and,x 和 y 同时为 true 时,返回 true,否则返回 false |
|| | x || y | 表示or, x 和 y 只要其中之一为 true,返回 true,否则返回 false |
! | !x | 表示not, x 为 true 时,结果为 false,否则为 true |
# 逻辑运算符
cout << (5 > 6 && 5 > 4) << endl;
cout << (7 > 6 && 5 > 4) << endl;
cout << (5 > 6 || 5 > 4) << endl;
cout << (5 > 6 || 5 < 4) << endl;
cout << !(5 > 6) << endl;
cout << !true << endl;
int a;
bool flag;
// 赋值
cin >> a;
flag = a;
a = flag;
// 输出
cout << a;
// 规则说明
// 注意1:布尔值true(成立) 输出1,false(不成立) 输出0
// 注意2:数值中,非零即为true,0为false
// 下面中,5和-5转换成布尔值均为true
//cout << bool(5) << endl;
//cout << bool(-5) << endl;
int a;
bool flag;
// 输入
cin >> a;
// 赋值
// 条件1:a >= 10
// 条件2:a <= 99
// 整合:a >= 10 && a <= 99
// 看花眼的话,可以加个括号增加可读性
// 括号加法1:(a >= 10 && a <= 99)
// 括号加法2:((a >= 10) && (a <= 99))
flag = ((a >= 10) && (a <= 99));
// 输出
cout << flag;
int a,b;
// 输入
cin >> a >> b;
// 判断,|| 或者,只要成立一个即可
cout << (a >= 10 || b >= 20);
假设你一周七天中只有周一才能穿新衣服,那么就需要 if语句 中 单一条件判断:
graph TD;
S(程序开始)-->A[/输入星期几/]
A --> B{判断是否星期一};
B-->|满足条件|C[穿上新衣];
C-->D([程序结束]);
B---|未满足条件|D(程序结束);
单一条件判断的if语句格式如下:
// 第一个花括号放在第一行末,或第二行开头均可,执行语句需要缩进一个Tab键
if (条件表达式) {
条件成立执行这里;
}
// 注意1:如果成立后的语句只有一句,可以去掉花括号,或放在第一行末
if (条件表达式) 条件成立执行这里;
// 或
if (条件表达式)
条件成立执行这里;
int flag;
cin >> flag;
// flag == 1 返回布尔值,成立的话执行缩进的第一行语句
// 如果有缩进的第二行,且没有括号包含,则无效
if (flag == 1)
cout << "周一穿新衣!";
单一if语句比较高冷,如果未满足条件,ta就不理你了;而else分支则可爱许多;
graph TD;
S([程序开始]) --> A[/输入星期几/]
A --> B{判断是否星期一};
B-->|满足条件|C[穿上新衣];
C-->E(程序结束);
B-->|未满足条件|D[不穿新衣];
D-->E([程序结束]);
if (条件表达式) {
条件成立执行这里;
} else {
条件不成立执行这里;
}
// 单行语句
if (flag == 1)
cout << "周一穿新衣!";
else
cout << "没有新衣穿!";
// 多行语句
if (flag == 1) {
cout << "嘿嘿!";
cout << "周一穿新衣!";
} else {
cout << "哎!";
cout << "没有新衣穿!";
}
int n, a;
cin >> n;
// 判断人数是否刚好30人
if (n % 30 == 0)
a = n / 30;
else
// 31人 = 1 + 1 = 2辆
// 65人 = 2 + 1 = 3辆
a = n / 30 + 1;
// 输出
cout << a;
return 0;
int n;
float sum;
// 输入
scanf("%d", &n);
// 计算
if (n >= 10)
sum = n * 1.2;
else
sum = n * 1.5;
// 格式化,保留小数1
printf("%.1f", sum);
int a, b, c;
cin >> a >> b >> c;
// 判断三角形
if (a + b > c && a + c > b && b + c > a)
cout << "Yes";
else
cout << "No";
return 0;
int n, a, b, c, d, e;
cin >> n;
// 拆位
a = n / 10000;
b = n / 1000 % 10;
c = n / 100 % 10;
d = n / 10 % 10;
e = n % 10;
// 判断 输出
if (a == 5 || b == 5 || c == 5 || d == 5 || e == 5)
cout << a + b + c + d + e;
else
cout << n;
#include <iostream>
using namespace std;
int main() {
int n, a, b, c, d, maxn;
cin >> n;
// 拆位
a = n / 1000;
b = n / 100 % 10;
c = n / 10 % 10;
d = n % 10;
// 求最大值,初始值比规定的小即可,四位数的话最小是0,-1即可
maxn = -1;
// a
if (a > maxn)
maxn = a;
//b
if (b > maxn)
maxn = b;
//c
if (c > maxn)
maxn = c;
//d
if (d > maxn)
maxn = d;
// 输出
cout << maxn;
return 0;
}
int m,t,s,total,re;
cin >> m >> t >> s;
// 总分钟 = m个数 x t分钟 = 50 x 10 = 500分钟
total = m * t;
// 剩余个数 = (总分数total - 已过分数s) / t分钟 = (500 - 200) / 10 = 30
re = (total - s) / t;
//问题:假设有一个测试点是不能被整除的时间,s 是 222
// (500 - 222) / 10 = 27余8,剩下的完整个数是27,所以无需+1 -1操作
cout << re;
(https://cdn.limfx.pro/-img-9dc95fbc-f7b6-4ae0-b095-037cbda041eb-articles-9714a544-0efe-455f-bfbf-1073e7c0692f-articelcontent-34b03d8f-340b-4fc3-a83e-600f0e74c6da/image-20231201112236927.png)
int m,t,s,total,re;
cin >> m >> t >> s;
// 特例1,神仙吃苹果,t是0分钟吃一个,t会当作被除数导致错误
if (t == 0) {
cout << 0;
return 0; // 退出程序,不再往下执行
}
// 总分钟 = m个数 x t分钟 = 50 x 10 = 500分钟
total = m * t;
// 剩余个数 = (总分数total - 已过分数s) / t分钟 = (500 - 200) / 10 = 30
// 问题:假设有一个测试点是不能被整除的时间,s 是 222
// (500 - 222) / 10 = 27余8,剩下的完整个数是27,余数不完整,忽略
// 特例2,假设s时间非常大,有10000
if (total < s) {
cout << 0;
return 0; // 退出程序,不再往下执行
}
re = (total - s) / t;
cout << re;
(https://cdn.limfx.pro/-img-9dc95fbc-f7b6-4ae0-b095-037cbda041eb-articles-9714a544-0efe-455f-bfbf-1073e7c0692f-articelcontent-a3e5a9ae-3f20-4762-9adf-b404ab745cc3/image-20231201114056201.png)
很多时候的分支判断,可能不止一条或两条,此时就需要使用 else if 多重分支结构
if (表达式成立) {
执行语句;
} else if (表达式成立) {
执行语句;
} else if (表达式成立) {
执行语句;
} else if (表达式成立) {
执行语句;
} else {
执行语句;
}
// 8岁之前:成长阶段
// 8-25之间:求学阶段
// 26-60之间:工作阶段
// 大于60:退休阶段
int a;
cin >> a;
// 多重循环
if (a < 8) {
cout << "成长阶段";
} else if (a >= 8 && a <= 25) {
cout << "求学阶段";
} else if (a >= 26 && a <= 60) {
cout << "工作阶段";
} else {
cout << "退休阶段";
}
在某一个成立的条件下,是否还有不同的另外的条件判断呢,此时需要用到嵌套判断
} else {
cout << "退休阶段,请输入孙子孙女数量:";
// 如果退休阶段有很多个孙子孙女,那还是需要打工赚压岁钱的
int b;
cin >> b;
if (b >= 7 && b <=9) {
cout << "无法退休,要打两份工";
} else if (b >=3 && b <= 6) {
cout << "无法退休,要打一份工";
} else if (b < 3) {
cout << "退休生活";
}
}
int a,b,c;
cin >> a >> b >> c;
// 多重判断,从小到大排序
// 无非是:abc,acb,bca,bac,cab,cba 这六种
// 输出的值需要空格 a b c 这样;用printf更方便
if (a <= b && a <=c) {
// a最小
if (b <= c)
printf("%d %d %d", a, b, c);
else
printf("%d %d %d", a, c, b);
} else if (b <= a && b <= c) {
// b最小
if (a <= c)
printf("%d %d %d", b, a, c);
else
printf("%d %d %d", b, c, a);
} else if (c <= a && c <= b) {
// c最小
if (a <= b)
printf("%d %d %d", c, a, b);
else
printf("%d %d %d", c, b, a);
}
int n, a, b, c, maxn, minn;
cin >> n;
// 拆位
a = n / 100;
b = n / 10 % 10;
c = n % 10;
// 求最大值
maxn = -1;
if (a >= b && a >= c) {
maxn = a;
} else if (b >= c) {
maxn = b;
} else {
maxn = c;
}
// 求最小值
minn = 10;
if (a <= b && a <= c) {
minn = a;
} else if (b <= c) {
minn = b;
} else {
minn = c;
}
// 差
cout << maxn - minn;
// 花花年龄,需要的总毫升数,需要的瓶数
int n, sum, t;
cin >> n;
// 判断
if (n > 10) {
// 5天 x 每次毫升25 x 一日3次
sum = 5 * 25 * 3;
} else if (n >= 7 && n <= 10) {
sum = 5 * 15 * 3;
} else if (n >= 3 && n <= 6) {
sum = 5 * 5 * 3;
}
// 求出需要几瓶
if (sum % 120 == 0) {
t = sum / 120;
} else {
t = sum / 120 + 1;
}
cout << t;
// 电费量
int n;
// 电费
float sum;
cin >> n;
// 判断
if (n >= 401) {
// 150 度的花费
sum = 150 * 0.4463;
// 250 度的花费
sum = sum + (400 - 150) * 0.4663;
// 400 度的花费
sum = sum + (n - 400) * 0.5663;
} else if (n >= 150 && n <= 400) {
// 150 及以内的花费
sum = 150 * 0.4463;
// 150 - 400 之间的花费
sum = sum + (n - 150) * 0.4663;
} else {
sum = n * 0.4463;
}
// 输出
printf("%.1f", sum);
// 从周x开始,经过n天,总公里数
int x, n, sum;
cin >> x >> n;
// 一周7天:1 2 3 4 5 6 7
// 样例数据: 10天 从周3开始,双休,8天:250 x 8 = 2000
// 思路:过滤掉双休即可
// 判断n是不是整周,比如:7 14 21,re表示剩余的天数
int re = n % 7;
// 获取全周游泳总天数
int wd = n / 7 * 5;
// 判断思路解析
// 假设从周1开始,经过7或14天,直接:wd * 250
// 假设从周3开始,经过10天,最后一周到周5,无须减双休:(wd + re) * 250
// 假设从周3开始,经过11天,最后一周到周6,需要减1天:(wd + re - 1) * 250
// 假设从周3开始,经过12天,最后一周到周日,需要减2天:(wd + re - 2) * 250
// 有剩余天数
if (re != 0) {
// 情况1:如果一开始就是从周日开始 x == 7,这一天直接减掉-1
// 情况2:如果最后一周到了周六 re + x == 7,这一天也需要-1
if (x == 7 || re + x == 7) {
sum = (wd + re - 1) * 250;
// 情况3:一开始从周六开始,最后一周剩余re+x等于8,表示周日 -2
} else if (x == 6 || re + x == 8) {
sum = (wd + re - 2) * 250;
} else {
sum = (wd + re) * 250;
}
} else {
// 没有剩余天数,直接算:7 / 7 x 5 = 5天 或 14 / 7 x 5 = 10天
sum = wd * 250;
}
// 输出
cout << sum;
// 数据变量
int n, a1, a2, b1, b2, c1, c2;
// 计算变量
int s1, s2, s3;
// 录入数据
cin >> n;
cin >> a1 >> a2;
cin >> b1 >> b2;
cin >> c1 >> c2;
// 题目描述已经说出规则
// 57 / 2 = 28...1
// 方案1
if (n % a1 == 0) s1 = n / a1 * a2;
else s1 = (n / a1 + 1) * a2;
// 方案2
if (n % b1 == 0) s2 = n / b1 * b2;
else s2 = (n / b1 + 1) * b2;
// 方案3
if (n % c1 == 0) s3 = n / c1 * c2;
else s3 = (n / c1 + 1) * c2;
// 判断大小,假设s1最小
int minn = s1;
if (s2 <= minn) minn = s2;
if (s3 <= minn) minn = s3;
// 输出
cout << minn;
// 十颗苹果的高度
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
cin >> a1 >> a2 >> a3 >> a4 >> a5 >> a6 >> a7 >> a8 >> a9 >> a10;
// 最大高度
int h;
cin >> h;
// 管它能不能够到,都站在板凳上
h += 30;
// 数量,初始化,否则有警告
int sum = 0;
// 判断
if (h >= a1) sum++;
if (h >= a2) sum++;
if (h >= a3) sum++;
if (h >= a4) sum++;
if (h >= a5) sum++;
if (h >= a6) sum++;
if (h >= a7) sum++;
if (h >= a8) sum++;
if (h >= a9) sum++;
if (h >= a10) sum++;
// 输出
cout << sum;
除了if ... else条件分支,还有一种 switch .. case 分支,用于变量均为等于成立的分支方案:
// case 值1 表示 变量名 == 值1,成立的话,执行下面缩进的语句
// break; 表示跳出switch,否则会继续判断后续的case;
// default 相当于 else,在没有满足条件的时候执行,当然,可以省略这个;
switch (变量名) {
case 值1:
执行语句;
break;
case 值2:
执行语句;
break;
case 值3:
执行语句;
break;
...
default:
执行语句;
}
王二狗要下楼倒垃圾,垃圾分类有四种,他到底应该倒哪个桶呢?
// 垃圾种类
int n;
// 输入提示
cout << "请输入垃圾种类的序号:" << endl;
cout << "1.表示可回收垃圾!" << endl;
cout << "2.表示有害垃圾!" << endl;
cout << "3.表示厨余垃圾!" << endl;
cout << "4.表示其它垃圾!" << endl;
cout << "请输入1-4:";
cin >> n;
// switch分支
switch (n) {
case 1:
cout << "王二狗往可回收垃圾桶倒了垃圾!";
break;
case 2:
cout << "王二狗往有害垃圾桶倒了垃圾!";
break;
case 3:
cout << "王二狗往厨余垃圾桶倒了垃圾!";
break;
case 4:
cout << "王二狗往其它垃圾桶倒了垃圾!";
break;
default:
cout << "你往哪里倒???倒错了吧!";
break;
}
// 1-9
int n;
cin >> n;
// switch
switch (n) {
case 1:
cout << "one";
break;
case 2:
cout << "two";
break;
case 3:
cout << "three";
break;
case 4:
cout << "four";
break;
case 5:
cout << "five";
break;
case 6:
cout << "six";
break;
case 7:
cout << "seven";
break;
case 8:
cout << "eight";
break;
case 9:
cout << "nine";
break;
default:
cout << "out";
break;
}
// 年,月
int y, m;
cin >> y >> m;
// switch判断月份
switch (m) {
// 合并相同的case
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
cout << 31;
break;
case 4: case 6: case 9: case 11:
cout << 30;
break;
case 2:
// 判断闰年平年
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
cout << 29;
else
cout << 28;
break;
}
计算机最大的一个特性就是快速的重复执行有规律的运算,for循环语句 就是做这种事的
for (循环变量初始化;循环条件;循环变量增或减) {
循环体
}
graph TD;
A([开始程序]) --> B[循环变量初始化]--> C{循环判断};
C-->|到达循环终值|E([结束循环]);
C-->|未到达循环终值|D[执行循环体]-->F[循环变量自增]-->C;
使用 for 循环语句,输出1-10这十个数字:
// 输出1-10,每个数字换行
// int i = 1; 循环变量初始化,从1开始
// i <= 10; 循环判断,当i目前小于等于10时,继续执行循环体
// i++;让循环变量进行累加,效果为:i = i + 1,没有这个过程就死循环啦
// cout << i << endl; 循环体,也就是可执行语句的部分
// 流程图文字版如下:
// 第一步:int i = 1;初始化循环变量,这条语句只执行一次
// 第二步:i <= 10; 判断循环条件;
// 第三步:cout << i << endl; 第二步条件成立后,执行这一步,不成立,退出for语句;
// 第四步:i++;增值变量;然后回到第二步继续
// 后续一直循环2,3,4步,直到退出for语句位置;
for(int i=1;i<=10;i++){
cout << i << endl;
}
cout << "退出 for 循环后执行我!";
通过 for 循环 代码将一个月的零花钱保存起来,1号存1块,2号存2块...30号存30块,共存了多少钱。
// 存钱变量
int sum = 0;
// 累加和
for(int i=1;i<=30;i++){
// sum = sum + i;
sum += i;
}
// 输出
cout << sum;
// 十位 个位
int a, b;
// 循环10-99之间,包含10和99
for(int i=10;i<=99;i++){
// 拆位
a = i / 10;
b = i % 10;
// 判断
if (a == 2 || b == 2) cout << i << endl;
}
// 百 十 个
int a, b, c;
// 循环三位数 100-999
for(int i=100;i<=999;i++){
// 拆位
a = i / 100;
b = i / 10 % 10;
c = i % 10;
// 立方和
if (a * a * a + b * b * b + c * c * c == i) cout << i << endl;
}
// 两个正整数
int n,k;
// 两类数之和,统计次数
int a = 0,b = 0,acount = 0;
// 输入
cin >> n >> k;
// 循环1-n之间
for(int i=1;i<=n;i++){
// 求a数,并累加
if (i % k == 0) {
a += i;
acount ++;
} else {
b += i;
}
}
// 输出
printf("%.1f ", float(a) / acount);
printf("%.1f", float(b) / (n - acount));
// 这题是洛谷官方教材的题目,上面是我做的,循环次数略多
// 以下是官方给的方案,利用了倍数和等差公式
// 倍数通过 i = k 起步,i += k,每次增值k
// 等差数列求和:
// 1-100的和,d为1时,等差公式:(a1 + an) x n / 2
// cout << (1 + 100) * n / 2; // 5050
// 直接循环k的倍数即可
// 直接从k的值初始化,i+=k意思是i = i + k,每次增值k的倍数
for(int i=k;i<=n;i+=k) a += i;
// b的值,利用等差公式
b = (1 + n) * n / 2 - a;
// a的循环次数,n / k 即可
printf("%.1f ", float(a) / (n / k));
printf("%.1f", float(b) / (n - n / k));
// 整数
int n, a, b, c, d, count = 0;
cin >> n;
// 循环1-n
for(int i=1;i<=n;i++){
// 拆位
a = i / 1000;
b = i / 100 % 10;
c = i / 10 % 10;
d = i % 10;
// 判断需求
if ((a + b + c + d) % 2 != 0 && (a + b + c + d) % 5 != 0) count++;
}
// 输出
cout << count;
for嵌套是什么意思?for语句的循环体再执行一个for语句吗?没错!
// 先来个简单的需求,完成下列图形
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
// 首先,开启纬度思想,一维即:一行一条线;二维则:多行多列是个面
// 第一步,先考虑输出一行
for(int i=1;i<=5;i++){
cout << "* ";
}
// 第二步,将一行改成一列试试,为后续扩展铺路
for(int i=1;i<=5;i++){
cout << "* " << endl;
}
// 第三步,将每一列当成一个for循环,再铺出一行
for(int i=1;i<=5;i++){
for(int j=1;j<=5;j++){
cout << "* ";
}
cout << endl; // 一列换一次行
}
利用 for循环 嵌套,实现一个不重复的 九九乘法表
// 第一步:先考虑1x1=1...1x9=9 这一列
for(int i=1;i<=9;i++){
printf("1x%d=%d\n", i, 1 * i);
}
// 第二步:将输出的每一项换成for循环输出9项
// 循环逻辑:
// i = 1时,j = 1 2 3 4 5 6 7 8 9
// i = 2时,j = 1 2 3 4 5 6 7 8 9
// ...
// i = 9时,j = 1 2 3 4 5 6 7 8 9
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
printf("%dx%d=%2d ", i, j, i * j);
}
printf("\n");
}
// 第三步:去掉右上部分的重复, 1 x 2 = 2 和 2 x 1 = 2 这种
// 问题:每次j都循环满9次是导致重复的根源,如何处理?
// 解题:第1行,后8个是重复的,第2行,后7个是重复的,以此类推;
// 编码:那么只要将每次循环的次数和i保持一致即可。
for(int i=1;i<=9;i++){
for(int j=1;j<=i;j++){
printf("%dx%d=%2d ", i, j, i * j);
}
printf("\n");
}
// 正方形边数
int n;
cin >> n;
// 循环1-n
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
// 第一行和第n行是满星
// 第一列和第n列也要星
if (i == 1 or i == n or j == 1 or j == n)
cout << "*";
else
cout << " ";
}
cout << endl;
}
// 行数
int n;
cin >> n;
// 最外层控制行数,比如样例的5行
for(int i=1;i<=n;i++) {
// 中层控制三块三角形
for(int j=1;j<=3;j++){
// 假设第一次循环
// 第一行星号前后有4个空格,那就需要循环4次,星号1次
// 以此类推:第二行,前后3个空格,星号3次
for(int z=1;z<=n-i;z++){
cout << " ";
}
// 星号是:1 3 5 每行+2:i*2-1
// i = 1 z<=1*2-1=1
// i = 2 z<=2*2-1=3
// i = 3 z<=3*2-1=5
for(int z=1;z<=i*2-1;z++){
cout << "*";
}
for(int z=1;z<=n-i;z++){
cout << " ";
}
}
cout << endl;
}
// 整数n, 总和sum
int n, sum = 0;
cin >> n;
// 循环1-n
for(int i=1;i<=n;i++){
// 希望累加的过程
// i = 1, 1
// i = 2, 1 x 2
// i = 3, 1 x 2 x 3
// i = 4, 1 x 2 x 3 x 4
// 最后,把每一行乘积的结果累加
int temp = 1;
for(int j=1;j<=i;j++){
// 1 * 1 * 2 * 3 * 4
temp *= j;
}
sum += temp;
}
cout << sum;
// 整数n
int n;
cin >> n;
// 循环1-n
for(int i=1;i<=n;i++){
// 输出
cout << i << ":";
// 循环1-i
for(int j=1;j<=i;j++){
// 求因子
if (i % j == 0) cout << j << " ";
}
// 换行
cout << endl;
}
// n,表示要输入比较的数
// 求最大最小值
int n, maxn = -1, minn = 1001;
cin >>n;
// 循环赋值
for(int i=1;i<=n;i++){
// 临时变量
int temp;
cin >> temp;
// 求最大最小
if (temp < minn) minn = temp;
if (temp > maxn) maxn = temp;
}
// 极差
cout << maxn - minn;
// n,a,count,maxn
int n, a, prev, count = 1, maxn = 0;
cin >> n;
// 由于需要邻值对比,先单独把第一个值保存至prev
cin >> prev;
// 1-n循环,由于首值已录,这里直接从第2值开始
for(int i=2;i<=n;i++){
cin >> a;
// 判断当前值是否是上一值+1,计数器+1
if (a == prev + 1) count++;
// 计时器还原
else count = 1;
// 求最大值
if (maxn < count) maxn = count;
// 将当前值换成下一个
prev = a;
}
// 输出
cout << maxn;
变量作用域分为局部和全局,在之前的解题中存在不同位置,效果也不尽相同;
// 首先,函数还没学过,不考虑
int a = 5;
// 在if里面声明的变量和外部的区别
if (5 > 3) {
// 判断体内可以访问外部变量a
// 此时a可以理解为全局变量(不考虑函数),在哪里可以访问(赋值取值)
cout << a;
}
// 在if体内的变量
if (5 > 3) {
int b = 3;
cout << b;
}
// 访问不了b,因为它是局部变量,只能在所在的if体内访问
cout << b;
// 这里int i属于for体内的局部变量i
for(int i=1;i<=5;i++){
//...
}
// 外部无法访问,直接报错
cout << i;
// 可以提到外面来声明来保证全局性
int i;
for(i=1;i<=5;i++){
//...
}
// 可以访问,并且是6,因为for最后执行是i++
cout << i;
// 之前短除法的临时变量
for(int i=1;i<=10;i++){
// 这里的tmp在for外部就无法访问了
// 它就是临时工,在for体内用的
// 所以总结:想要在体内用不想在外面用,就在体内声明
// 如果要全局都能使用,就在外部声明,比如程序代码的第一行
int tmp = 0
}
break 的作用是在循环体内,可设置条件来退出这个循环;
// break退出
for(int i=1;i<=10;i++){
// 当遇到5退出整个循环
if (i == 5) break;
// 输出i
cout << i << endl;
}
continue 的作用是在循环体内,可设置条件来退出当前这次循环,然后继续执行下一次循环;
// continue退出
for(int i=1;i<=10;i++){
// 当遇到5退出当前循环,continue需要卸载循环体最前面才有意义
if (i == 5) continue;
// 输出i
cout << i << endl;
}
// 质数 = 素数,只能被1和本身整除
// n
int n;
cin >> n;
// 循环2~n-1
for(int i=2;i<=n-1;i++){
// 判断i是否为因子,找到第一个即最小的因子
// 天坑:此题如果测试数据n是20,那因子为2,10,则10最大,但10不是质数
// 审题:题目说了由两个不同质数的乘积,10不是质数,所以测试数据不会给20让你测
// 再审题:由两个不同的质数,不是多个,还必须是质数。。。20 不符合要求的
if (n % i == 0) {
// 求出较大的数
cout << n / i;
break;
}
}
// n, count, sum
int n, count = 0, sum = 0;
cin >> n;
// 循环2~n-1
for(int i=2;i<=n;i++){
// 判断质数
bool flag = true;
for(int j=2;j<=i-1;j++){
// 能被整除,说明不是质数,退出j循环
if (i % j == 0) {
flag = false;
break;
}
}
// 既然不是质数,退出i的本次循环,直接循环下一个i
// continue 在这里卡住,不再执行后续代码
if (!flag) continue;
// 判断到目前质数的和是否大于n,大于直接break退出整个i循环
if (sum + i > n) break;
// 如果没被continue卡住,则说明是质数,输出i,并count+1,累加sum
cout << i << endl;
count++;
sum += i;
}
// 输出计数器
cout << count << endl;
// n
int n;
cin >> n;
// 循环1-n*n
for(int i=1;i<=n*n;i++) {
// 个位数,补零
if (i < 10) cout << 0 << i;
else cout << i;
// 判断n的倍数,换行
if (i % n == 0) cout << endl;
}
// 空一行
cout << endl;
// 循环1-n,负责n列,计数器count
int count = 1;
for(int i=1;i<=n;i++){
// 输出空格
for(int j=1;j<=n-i;j++){
cout << " ";
}
// 输出数字
for(int j=1;j<=i;j++){
if (count < 10) cout << 0 << count;
else cout << count;
count++;
}
cout << endl;
}
//n, sum, maxn, minn
int n, sum = 0, maxn = -1, minn = 11;
cin >> n;
// 循环1-n
for(int i=1;i<=n;i++){
// 输入分数
int c;
cin >> c;
// 累加分
sum += c;
// 求最大最小值
if (maxn < c) maxn = c;
if (minn > c) minn = c;
}
// 去掉最大值和最小值
sum = sum - maxn - minn;
// 计算输出分数
printf("%.2f", (float)sum / (n - 2));
// k天数, coin金币, day当前累计天
int k, coin = 0, day = 0;
cin >> k;
// 简单捋一下
// i=1, 第1天:+1
// i=2, 第2,3天:+2 +2
// i=3, 第4,5,6天:+3 +3 +3
// ...
// 现在给出的k是天数
// 根本不清楚i的末值是多少,那就无限循环吧(死循环)
// 死循环可以将条件去掉,但保留分号,循环体通过判断退出即可
// 外层循环,表示轮次,第1次1天,第2次2,3天,第3次4,5,6天中的次
for(int i=1;;i++) {
// 将轮次中的天数累加到day里
for(int j=1;j<=i;j++){
// 累加天数
day++;
// 累加金币
coin += i;
// 退出机制
if (day == k){
cout << coin << endl;
return 0;
}
}
}
while 循环相当于 for 循环,可以不用计数器,需要先进行条件判断,也可设置死循环
// 死循环:条件是1或者true,让它永远成立即可
while(1){
cout << 123;
}
// 利用计数器输出1-10
int a = 1;
while(a <= 10) {
cout << a << endl;
a++;
}
// 死循环中途退出
// 支持break、continue
int a = 1;
while(1){
if (a == 5) break;
cout << 123;
a++;
}
do while 循环相当于 while 循环,可以将条件判断至于循环体下方,让其无条件先循环一次
// 不管条件是否满足,至少要执行一次循环体
int a = 1;
do{
cout << 123;
} while(a < 0);
// m高度,审题有0.5,所以是浮点型
float m = 100;
// count计数器
int count = 0;
// 大于等于0.5就一直循环
while(m >= 0.5){
count++;
m /= 2.0;
}
cout << count;
// 人数
int n = 0;
// 不知道人数,只能无脑死循环
while(1){
// 每循环一次n+1,统计人数
n++;
// 余数同时成立即可
if (n % 5 == 1 && n % 6 == 5 && n % 7 == 4 && n % 11 == 10) {
cout << n;
break;
}
}
// s目标距离, f每次游泳的时间, count步数
float s, f = 2, count = 0;
cin >> s;
// 先别废话,让她游
do {
// 每次游泳就要减去一次距离
s -= f;
// 每次游泳的距离是上一次的0.98
f *= 0.98;
// 累加步数
count++;
} while(s > 0);
// 输出步数
cout << count;
之前我们拆位使用了整除+求余的方式,但对于不确定位数的整数就会捉襟见肘
// 要求输入三至五位整数
// 将每一位输出
int n;
cin >> n;
// 使用短除法
// 通过求余得到末尾:
// 比如 123 % 10 = 3
// 然后 12 % 10 = 2 ... 1 % 10 = 1...最终除数为0
while(n != 0) {
// 输出拆位
cout << n % 10 << endl;
// 整除
n /= 10;
}
int n, count = 0;
cin >> n;
// 循环1-n,1-9不含0,直接从10开始
for(int i=10;i<=n;i++){
// 短除
int temp = i;
while(temp != 0) {
// 102: 2..0(+1)..1
if (temp % 10 == 0) {
count++;
break; // 只要包含0就行了,退while
}
// 整除
temp /= 10;
}
}
cout << count;
// n原数,f新数
int n, f = 0;
cin >> n;
// 不用考虑负数
while(n != 0){
// 拆位
int g;
g = n % 10;
// 假设123,上一轮f得到了3,这次要30+2=32,最后要320+1=321
// 第一轮,由于f是0,所以,f * 10 + g = 3
f = f * 10 + g;
// 整除
n /= 10;
}
cout << f;
int n, x, count = 0;
cin >> n >> x;
// 循环1-n
for(int i=1;i<=n;i++){
//拆位
int temp = i;
while(temp != 0) {
if (temp % 10 == x) count++;
temp /= 10;
}
}
cout << count;
// x是个位,α乘积即x本身
int x;
cin >> x;
// 大于10,忽略个位数
while(x >= 10){
// 初始乘积变量
int temp = 1;
// 拆位循环
while(x != 0) {
// 获取个位
int g = x % 10;
// 乘积,非零
if (g != 0) temp *= g;
// 整除
x /= 10;
}
// 将乘积返回给x,进入下一次循环
x = temp;
}
cout << x;
// money钱, cost花销, mather妈
int money = 0, cost = 0, mather = 0;
// 1-12月循环
for(int i=1;i<=12;i++) {
// 每个月+300元
money += 300;
// 输入这个月花销
cin >> cost;
// 如果持有100或以上,就把整百交给妈妈
// 比如有180,交给妈妈100,有280,交给妈妈200
// 扣去当月花销
money -= cost;
while (money >= 100) {
mather += 100;
money -= 100;
}
// 如果发现钱是负的
if (money < 0) {
printf("-%d", i);
return 0;
}
}
// 输出money
cout << money + mather + (mather * 0.2);
穷举即枚举,我们会在下一套课程中讲解 暴力枚举,那么现在先简单的了解下
// 假设只有一个小孩,成人拥有的票钱 = 40 - 3
// 成人票最多买:37 / 8 = 4张,循环1-4张
for(int i=1;i<=(40-3)/8;i++) {
// 第一次循环:1张成人票,减去-8,再看看买小孩的票,能否整除
// 第i次以此类推
int x;
// 得到买小孩票的钱
x = 40 - i * 8;
// 判断是否能整除
if (x % 3 == 0) cout << i << " " << x / 3 << endl;
}
// 100分, 累计count
int f = 100, count = 0;
// 先从5分开始,1分2分至少一个:(100 - 2 - 1) / 5 = 5分钱个数
for(int i=1;i<=(100-2-1)/5;i++){
// 嵌套2分:(100 - 5 - 1) / 2 = 2分个数
for(int j=1;j<=(100-5-1)/2;j++){
// i第一轮,j第一轮:一个5分+一个2分,93个1分
// i第一轮,j第二轮:一个5分+两个2分,91个1分
// i第一轮,j第三轮:一个5分+三个2分,89个1分
// ...
// i第三轮,j第一轮:三个5分+一个2分,83个1分
// ...
// i第三轮,j第五轮:三个5分+五个2分,75个1分
// ...
// 得到1分钱银币的总分数
// 在循环中,值>=1,说明可以整除1
if (f - (i * 5 + j * 2) >= 1) count++;
}
}
cout << count;
// 总树木
int n;
cin >> n;
// 从桃树开始,梨树和苹果树至少各两棵(偶数限制)
// 累加也是偶数:i=i+2
for(int i=2;i<=n-2-2;i=i+2){
// 然后是梨树
for(int j=2;j<=n-2-2;j=j+2){
// i第一轮,j第一轮:桃树2,梨树2,苹果树18-2-2=14
// 和兑换银币那个例子一样,下面不循了
// 得到当前轮苹果树
int p = n - i - j;
// 规则判断成立时输出三种树
if (i <= j && j <= p)
printf("%d %d %d\n", i, j, p);
}
}
数组分为:一维、二维、多维,大部分情况下只用一维,少量二维,多维很少
变量只能存储一条数据,数组可以存储多条数据;
比如我要声明一个可以存放10条数据数组:
// 声明可以存放10条数据的数组,数组里的值(或叫元素)为整数
int a[10];
a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | a[8] | a[9] |
---|---|---|---|---|---|---|---|---|---|
78 | 59 | 66 | 12 | 9 | 128 | 98 | 73 | 52 | 76 |
从上述的数组数据结构图中,总结几点:
// 对数组a下标5,也就是第6个位置赋值
a[5] = 128;
// 输出123
cout << a[5];
// 没有赋值的数组会随机出现不同值
cout << a[3];
// 当然这里有一个目前还没有学习的概念:全局变量和局部变量
// 如果把int a[10]放在int main()外部,就是全局,那么不赋值默认就是0
// 如果是局部变量:没有赋值的还有可能默认0,我们可以用循环查看
for(int i=0;i<=19;i++){
printf("a[%d]=%d\n", i, a[i]);
}
第二种数组的赋值方式,采用花括号对声明的数组直接赋值:
// 花括号直接赋值
int a[10] = {78, 59, 66, 12, 9, 128, 98, 73, 52, 76};
// 通过循环逐步输出,注意,i从0开始,i<=9或<10
for(int i=0;i<=9;i++){
printf("a[%d]=%d\n", i, a[i]);
}
// 如果你设置了a[20],但{}里只有10个数据,则会用整数0填充
for(int i=0;i<=19;i++){
printf("a[%d]=%d\n", i, a[i]);
}
如果不确定赋值的个数,可以采用动态方案赋值:
// 但这样,就无法得知长度了;需要通过以后学习的sizeof()函数来获取,先不深入探讨
int a[] = {1, 2, 3, 4, 5}
至于无法一开始初始化指定值,又怕未赋值导致随机值,可以先初始化零;
// 初始化0:方案一
int a[10] = {};
// 初始化0:方案二
int a[10] = {0};
什么是下标越界:声明时,超过了指定的范围就是下标越界,规定:不要越界;
下标越界,有些平台会报异常,有些不报错(这种最要命,程序没错,数据错了检查不出来)
所以,不要越界;
比如,你int a[10],你赋值时就初始化时,就无法对a[20]赋值,导致随机数字;
int a[10] = {0};
cout << a[12];
// 整型数组,长度100,默认0,废弃a[0],+1
int a[101] = {0};
int n;
cin >> n;
// 循环1-n,注意:如果从1开始,废弃a[0]
// 循环0-n,注意:i<n 去掉等号
for(int i=1;i<=n;i++) cin >> a[i];
// 支撑数:不在第一位,不在最后一位,掐头去尾
for(int i=2;i<=n-1;i++){
// 当前值比左右两边都大
// 上一个值:a[i-1],下一个值:a[i+1]
if (a[i] > a[i-1] && a[i] > a[i+1]) cout << a[i] << endl;
}
// 球
int a[101] = {0}, n, cnt = 0;
cin >> n;
// 赋值
for(int i=1;i<=n;i++) cin >> a[i];
// 对比值
int x;
cin >> x;
// 统计
for(int i=1;i<=n;i++){
// 判断
if (a[i] == x) cnt++;
}
// 求概率
printf("%.2f", cnt / float(n));
// 病人
int a[101] = {0}, n;
cin >> n;
// 赋值
for(int i=1;i<=n;i++) cin >> a[i];
// 四个年龄段
int cnt[4] = {0};
// 循环病人
for(int i=1;i<=n;i++){
// 判断
if (a[i] >= 0 && a[i] <= 18) cnt[0]++;
if (a[i] >= 19 && a[i] <= 35) cnt[1]++;
if (a[i] >= 36 && a[i] <= 60) cnt[2]++;
if (a[i] >= 61) cnt[3]++;
}
// 循环年龄段,注意,年龄是从下标0开始赋值的 i<=3 或 i<4
for(int i=0;i<=3;i++){
printf("%d %.2f%%\n", cnt[i], cnt[i] / float(n) * 100);
}
// 鱼
int a[101] = {0}, n;
cin >> n;
// 赋值
for(int i=1;i<=n;i++) cin >> a[i];
// 外层循环所有鱼
for(int i=1;i<=n;i++){
// 思路:让当前的鱼和除了自己的每一条对比,比自己不可爱的就+1
int cnt = 0;
// 内层循环要对比的鱼
// 因为鱼只能看到它左边的鱼,所以要忽略它右边的鱼
for(int j=1;j<=n;j++){
// 碰到自己了,退出
if (i == j) break;
// 累计,审题后得知等于不计数,必须大于
if (a[i] > a[j]) cnt++;
}
// 输出
cout << cnt << " ";
}
// 数
int a[100001] = {0}, n, x;
cin >> n;
// 循环1-n
for(int i=1;i<=n-2;i++){
// x
cin >> x;
// 将a数组中下标为x,即a[x]做个标记,比如设置为1
a[x] = 1;
}
// 再次循环1-n
for(int i=1;i<=n;i++){
// 输出值为零的数组元素
if (a[i] == 0) cout << i << " ";
}
int n, a[101] = {0};
cin >> n;
// 循环1-n学号,赋值
for(int i=1;i<=n;i++) cin >> a[i];
// 求最大最小值位置
int minn = 101, maxn = -1, min_index = 0, max_index = 0;
for(int i=1;i<=n;i++){
if (a[i] < minn) minn = a[i], min_index = i;
if (a[i] > maxn) maxn = a[i], max_index = i;
}
cout << max_index << " " << min_index;
// 本题并没有让你输入n限制数组赋值个数,可以考虑while
int a[101] = {0};
// 新知识点:++i 和 i++ 的区别
// int i = 1;
// int b = ++i; // 或 i++
// cout << b;
// ++i 语法 是将本身i累计后再参与运算;
// i++ 语法 是先将i参与运算(比如赋值),然后本身再累加
// 融合到数组中
// int i = 1;
// a[i++] = 100; // 如果i当前为1,那么a[1] = 100,然后i再变成2
// cout << a[1]; // 100
// cout << a[2]; // 0
int i = 0, tmp;
// 死循环走起
while(true) {
cin >> tmp;
if (tmp == 0) break;
// 赋值
a[++i] = tmp;
}
// 看下i的值和数量是否对的上
//cout << i;
// 倒数,从末尾循环到开头
while(i != 0){
cout << a[i--] << " ";
}
int n, a[101] = {0}, i = 1;
cin >> n;
// 第一个
a[1] = n;
// 循环
while(n != 1) {
// 判断偶数
if (n % 2 == 0)
n = n / 2;
else
n = n * 3 + 1;
a[++i] = n;
}
// 倒着输出
while(i != 0){
cout << a[i--] << " ";
}
int l, m, a[10001] = {0};
cin >> l >> m;
int u, v = 0;
// m行
for(int i=1;i<=m;i++){
cin >> u >> v;
// 从u点到v点
for(int j=u;j<=v;j++){
a[j] = 1;
}
}
int total = 0;
// l总树木,题目说从0开始
for(int i=0;i<=l;i++){
if (a[i] == 0) total++;
}
// 输出
cout << total;
int m, n, a[10] = {0};
cin >> m >> n;
// 循环n-m
for(int i=m;i<=n;i++){
// 短除拆位
int tmp = i;
while(tmp != 0) {
a[tmp % 10]++;
tmp /= 10;
}
}
// 统计
for(int i=0;i<=9;i++){
cout << a[i] << " ";
}
int n, a[101] = {0}, b[101] = {0}, cnt = 0;
cin >> n;
// 循环n
for(int i=1;i<=n;i++) cin >> a[i];
// i 从数组第一位开始
for(int i=1;i<=n;i++) {
// j 从数组第二位开始,这样实现:第一位+第二位
for(int j=i+1;j<=n;j++) {
// z 用来对比值
for(int z=1;z<=n;z++) {
if (a[i] + a[j] == a[z] && b[z] != 1) {
// 5
// 2 5 3 4 7
// 这一组数据中:2 + 5 = 7 和 3 + 4 = 7 算重复,要去重
// 但题目中很难知道要剔除这种重复,是一个坑点,从错误的测试点获知的
// 再审题,她说有多少个数?不是几种方案,所以,两个结果7算一个数
// 4
// 1 4 5 2
// 这一组重复为:1 + 4 = 5, 4 + 1 = 5;要去掉一个重复,保留一个
// 可以暴力枚举,但只要每次j向后移一位,即可自然去重
// printf("%d+%d=%d\n", a[i], a[j], a[z]);
// i : 1 4 5 2
// j : 1 4 5 2 (j+1)
// z : 1 4 5 2
// 第一轮:1 + 4, 1 + 5, 1 + 2
// 第二轮:4 + 5, 4 + 2
// 第三轮:5 + 2
cnt++;
// 标记a[z]的结果数字被统计过了
b[z] = 1;
}
}
}
}
// 统计
cout << cnt;
int x, y;
cin >> x >> y;
// 循环
for(int i=x;i<=y;i++){
// 短除拆位
int tmp = i * i;
// 不是7位数,直接下一次循环
if (tmp < 1000000 || tmp > 9999999) continue;
// 临时数组
int a[10] = {0};
while(tmp != 0){
// 个位求余
a[tmp % 10]++;
// 去掉个位
tmp /= 10;
}
// 判断重复
bool flag = true;
for(int j=0;j<=9;j++){
if (a[j] > 1) {
flag = false;
break;
}
}
// 输出
if (flag) cout << i << endl;
}
int n, m;
float maxn = -1.0;
cin >> n >> m;
// 数组赋值
int a[101] = {0};
for(int i=1;i<=n;i++) cin >> a[i];
// 循环1-n
for(int i=1;i<=n;i++){
// 每次循环从i的值开始
// 假设 n m : 6 3 数组:3 6 1 5 6 4
// 第一轮:3 6 1
// 第二轮:6 1 5
// 第三轮:1 5 6
// 循环,不足m个,则不再统计
if (i + m - 1 <= n) {
float sum = 0.0;
for(int j=i;j<=i+m-1;j++){
sum += a[j];
}
// 对比
if (sum / m > maxn) maxn = sum / m;
}
}
// 输出
printf("%.2f", maxn);
int n, a[101] = {0};
cin >> n;
// 赋值
for(int i=1;i<=n;i++) cin >> a[i];
// 处理
for(int i=1;i<=n;i++){
// 条件1:本身礼物数>=10
// 条件2:礼物数是4的倍数
// 满足条件,直接退
if (a[i] >= 10 && a[i] % 4 ==0)
continue;
else {
// 补礼物循环次数,比如初始0,至多补12次
for(int j=1;j<=12;j++){
a[i] += 1;
if (a[i] >= 10 && a[i] % 4 ==0) break;
}
}
}
// 由于课程进度未学习到函数sort排序或排序算法(冒泡、选择、插入等)
// 属于超纲提高难度(类似打游戏中越级打怪,或禁翻滚、禁药打怪)
// 只用之前学习过的几个知识点将排序做起来
// 知识点1:求极值(最大最小值)
// 知识点2:嵌套循环,外层次数,内层对比
// 知识点3:标记已知最大值,去重复,避免再次对比
// i:5 次循环
// j:12 32 12 24 20 对比数据
// 声明新数组,存放排序好的
int z[101] = {0};
for(int i=1;i<=n;i++){
// 初始化最大值
int maxn = -1;
// 初始化找到的最大值的位置
int index = -1;
for(int j=1;j<=n;j++){
// 求出当前最大值
if (a[j] > maxn) maxn = a[j], index = j;
}
// 将原本最大值的位置标记,设置-1
a[index] = -1;
// 将最大值赋值给当前i循环的位置,也就是最前面
z[i] = maxn;
}
// 输出所有
for(int i=1;i<=n;i++) cout << z[i] << " ";
int n, a[101] = {0};
cin >> n;
// 赋值
for(int i=1;i<=n;i++) cin >> a[i];
// 新数组
int z[101] = {0};
// 嵌套循环求极值
for(int i=1;i<=n;i++){
// 初始化最大值和位置
int maxn = -1, index = -1;
// 求最大值
for(int j=1;j<=n;j++){
if (a[j] > maxn) maxn = a[j], index = j;
}
// 将原本的最大值标记-1
a[index] = -1;
// 将最大值赋值给新数组当前i的位置
z[i] = maxn;
}
// 输出
for(int i=1;i<=n;i++){
// 判断
if (i <= 2) printf("%d %d\n", z[i], 500);
if (i >= 3 && i <= 6) printf("%d %d\n", z[i], 300);
if (i >= 7 && i <= 10) printf("%d %d\n", z[i], 100);
if (i >= 11) printf("%d %d\n", z[i], 0);
}
int n, a[8] = {0}, b[8] = {0};
cin >> n;
// 彩票有7个号码,存储中奖号码
for(int i=1;i<=7;i++) cin >> a[i];
// 循环n组购买彩票的号码
for(int i=1;i<=n;i++){
// 计数器
int cnt = 0;
// 读入一组7位号码
for(int j=1;j<=7;j++){
int tmp;
cin >> tmp;
// 读入的数和中奖的7位一一对比
for(int z=1;z<=7;z++){
if (tmp == a[z]) cnt++;
}
}
// 假设cnt++两次,是五等奖
// b[2] = 1,五等奖显示在第6个位置上
// 假设还有一张也是五等奖b[2] = 2张
b[cnt]++;
}
// 倒序
for(int i=7;i>=1;i--){
cout << b[i] << " ";
}
所谓的二维数组,就是数组里还有一个数组,类似嵌套循环,多维数组就是数组里的数组里的数组;
声明格式:
数据类型 数组名[行数][列数] // 就是两层嵌套循环
二维数组构建一个矩阵表格:
a[0,0] -> 78 | a[0,1] -> 102 | a[0,2] -> 44 |
---|---|---|
a[1,0] -> 92 | a[1,1] -> 165 | a[1,2] -> 92 |
a[2,0] -> 67 | a[2,1] -> 278 | a[2,2] -> 39 |
// 上面的构建,从0开始的,也可以和之前废弃0从1开始
int a[3][3];
// 硬赋值
a[0][0] = 78;
a[0][1] = 102;
a[0][2] = 44;
a[1][0] = 92;
a[1][1] = 165;
a[1][2] = 95;
a[2][0] = 67;
a[2][1] = 278;
a[2][2] = 39;
// 二维数组较好理解的初始化,内嵌的花括号表示一行,逗号结束表示换行
int b[3][3] = {{78, 102, 44}, {92, 165, 95}, {67, 278, 39}}
// 二维数组本质也是一维数组,可按照一维方式赋值
int b[3][3] = {78, 102, 44, 92, 165, 95, 67, 278, 39};
// 嵌套循环输出
// 输出矩阵为:
// 第一轮:a[0][0] a[0][1] a[0][2]
// 第二轮:a[1][0] a[1][1] a[1][2]
// 第三轮:a[2][0] a[2][1] a[2][2]
for(int i=0;i<=2;i++){
for(int j=0;j<=2;j++){
printf("%5d", a[i][j]);
}
printf("\n");
}
多为数组,三维:数组里的数组里的数组,不用理解到其它学科的纬度
// 题外话:不用理解成几何里三维立体,四维超立体,或天文里的四维时空,没那么复杂
// 用三维表示地球村,一维:地球,二维:国家:三维:省份,用数字代替
int b[3][3][3] = {
{
{1, 2, 3}, {4, 5, 6}, {7, 8, 9}
},
{
{11, 11, 12}, {13, 14, 15}, {16, 17, 18}
},
{
{20, 21, 22}, {23, 24, 25}, {26, 27, 28}
}
};
for(int i=0;i<=2;i++){
for(int j=0;j<=2;j++){
cout << "( ";
for(int z=0;z<=2;z++){
cout << b[i][j][z] << " ";
}
cout << "), ";
}
cout << endl;
}
int n, m, a[11][11] = {0};
cin >> n >> m;
// i从0开始也行,从1开始也行
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) cin >> a[i][j];
}
// 最大值没给范围,那就把第一个值初始
int maxn = a[1][1], minn = a[1][1];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
// 求最大值
if (maxn < a[i][j]) maxn = a[i][j];
// 求最小值
if (minn > a[i][j]) minn = a[i][j];
}
}
// 求差
cout << maxn - minn;
int n, m, a[101][101] = {0};
cin >> n >> m;
// 赋值
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) cin >> a[i][j];
}
// 判断
// 第一行:[1,1] [1,2] [1,3] [1,4]
// 第二行:[2,1] [2,2] [2,3] [2,4]
// 第三行:[3,1] [3,2] [3,3] [3,4]
// 第四行:[4,1] [4,2] [4,3] [4,4]
// 已知第一行,末行,第一列,末列不存在靶心,去除减少循环次数
for(int i=2;i<=n-1;i++){
for(int j=2;j<=m-1;j++){
//将上下左右相邻的判断一下
if (a[i][j] > a[i-1][j] && a[i][j] > a[i][j-1] && a[i][j] > a[i][j+1] && a[i][j] > a[i+1][j])
cout << a[i][j] << endl;
}
}
int n, a[10][10] = {0};
cin >> n;
// 假设n=4
// a[1,1] a[1,2] a[1,3] a[1,4]
// a[2,1] a[2,2] a[2,3] a[2,4]
// a[3,1] a[3,2] a[3,3] a[3,4]
// a[4,1] a[4,2] a[4,3] a[4,4]
// 初始化行和列,
int i = 0, j = 0;
// 假设n=4,则执行16次,累加可以在循环体执行
for(int z=1;z<=n*n;){
// 朝右
i++;j++;
while(j <= n && !a[i][j]){
a[i][j] = z;
j++;z++;
}
// 朝下,i下移一位,j左移一位,保证不越界
i++;j--;
while(i <= n && !a[i][j]){
a[i][j] = z;
i++;z++;
}
// 朝左,i上移一位,j左移一位
i--;j--;
while(j >= 1 && !a[i][j]){
a[i][j] = z;
j--;z++;
}
// 朝上,j右移一位
i--;j++;
while(i >= 1 && !a[i][j]){
a[i][j] = z;
i--;z++;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%3d", a[i][j]);
}
printf("\n");
}
// 杨辉三角形特性
// 1.第一行只有数字:1
// 2.每一行头尾数字:1
// 3.每一个非头尾数字是上一行对应左右的和:
// 比如a[5][3] = a[4][2] + a[4][3]
// 4.第n行数字的和为:2的n-1次方
// 1+5+10+10+5+1=32 为: 2 x 2 x 2 x 2 x 2 = 32
// 1
// 1 1
// 1 2 1
// 1 3 3 1
// 1 4 6 4 1
// 1 5 10 10 5 1
// 为了方便观察,改为以上图形,程序上不需要考虑左边空隙
int n, a[21][21] = {0};
cin >> n;
// 初始首行
a[1][1] = 1;
// 循环
for(int i=2;i<=n;i++){
// 每一行的列数正好是当前的i数
for(int j=1;j<=i;j++){
a[i][j] = a[i-1][j-1] + a[i-1][j];
}
}
// 输出
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cout << a[i][j] << " ";
}
cout << endl;
}
int n, a[1001][4] = {0}, cnt = 0;
cin >> n;
// 将学生成绩赋值
for(int i=1;i<=n;i++) cin >> a[i][1] >> a[i][2] >> a[i][3];
// 用之前学习过的对比法
// 90 90 90
// 85 95 90
// 80 100 91
// 第一第二行对比90和85差距<=5,90和95差距<=5,90和90差距<=5
// 第一第三行对比...
// 第二第三行对比... 直到所有同学之间对比过
// 求所有成绩小于5的对数,比如有两个人对比过成立就是1对
// 外层循环所有学生i=1表第一行学生成绩
// 3个学生对比的话,1,2比,1,3比 2,3比,不会用到3,则n-1
for(int i=1;i<=n-1;i++){
// 内层循环从第二个学生开始:即i+1,+1了,次数n-1
for(int j=i+1;j<=n;j++){
// 检查正确性
//printf("%d-%d-%d:%d-%d-%d\n", a[i][1], a[i][2], a[i][3], a[j][1]...);
// 标记
bool flag = true;
// 求成绩对比是否小于<=5
for(int z=1;z<=3;z++){
// 差<=5
if (a[i][z] < a[j][z]) {
if (a[j][z] - a[i][z] > 5) {
flag = false;
break;
}
} else {
if (a[i][z] - a[j][z] > 5) {
flag = false;
break;
}
}
}
// 判断flag
if (!flag) continue;
// 继续判断和差<=10
int x = a[i][1] + a[i][2] + a[i][3];
int y = a[j][1] + a[j][2] + a[j][3];
if (x < y) {
if (y - x > 10) continue;
} else {
if (x - y > 10) continue;
}
// 能走到这里,就累加
cnt++;
}
}
// 输出
cout << cnt;
int n, a[40][40] = {0};
cin >> n;
// 样例:3 x 3
// 8 1 6
// 3 5 7
// 4 9 2
// 初始第一次二维下标位置,在第一行中间:n/2+1
int x = 1, y = n / 2 + 1;
// 初始第一个值
a[x][y] = 1;
// 假设n=3
for(int i=2;i<=n*n;i++){
if (x == 1 && y != n) {
// 帮助理解的假设推导3x3
// 1.若(i-1)的值在第一行不在最后一列,只有8和1,反推i为9和2
// 2.将i填入最后一列,9和2填入最后一行
// 3.(i-1)所在列的右一侧,也就是8或1所在列右一侧9(3,2),2(3,3)
// y当前为非n,推导在i-1的右一侧,即+1
y++;
// x当前为1,移到最后一行n
x = n;
} else if (x != 1 && y == n) {
// 1.若(i-1)在最后一列但不在第一行,7和2
// 2.将i填入第一列,即将8和3填入第一列
// 3.(i-1)所在行的上一行
// x为非1,即不在第一行,即x-1
x--;
// y为n,调整到第一列,即y=1
y = 1;
} else if (x == 1 && y == n) {
// 1.若(i-1)在第一行最后一列,就是6
// 2.将i写入(i-1)的正下方,7写入(2,3)
// 正下方的行,x+1
x++;
// 列没动,不写
} else if (x != 1 && y != n) {
// 1.若(i-1)不在第一行也不在最后一列:3,5,4,9
// 2.若(i-1)的右上方未填数,将i填入(i-1)位置的右上方
// 3.若填了数,则在正下方填入
// 判断(i-1)右上方是否为0,x-1 y+1 表示右上方
if (a[x-1][y+1] == 0) {
x--;
y++;
} else {
// 正下方
x++;
}
}
// 统一赋值
a[x][y] = i;
}
// 输出
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout << a[i][j] << " ";
}
cout << endl;
}
// 三维
int a[21][21][21] = {0}, w, x, h, q, ans = 0;
// 输入 长宽高
cin >> w >> x >> h >> q;
// 被激光切割的组数q
while(q--){
int x1, y1, z1, x2, y2, z2;
cin >> x1 >> y1 >> z1 >> x2 >> y2 >> z2;
// 三重循环标记被切割的方块
for(int i=x1;i<=x2;i++){
for(int j=y1;j<=y2;j++){
for(int k=z1;k<=z2;k++){
a[i][j][k] = 1;
}
}
}
}
// 输出三维,求0的个数,即为剩下的方块体积
for(int i=1;i<=w;i++){
for(int j=1;j<=x;j++){
for(int k=1;k<=h;k++){
if (a[i][j][k] == 0) ans++;
}
}
}
cout << ans;
函数或叫自定义函数,是用户自己定义的一种函数,适用于将大量重复的代码进行封装调用
自定义函数说明:
// 创建一个无返回值的自定义函数,通过调用执行
// 比如重复输出10组星号三角形
// 星号三角
void star() {
for(int i=1;i<=3;i++){
for(int j=1;j<=i;j++){
cout << "*";
}
cout << endl;
}
}
int main() {
for(int i=1;i<=10;i++){
star();
}
return 0;
}
函数中有两个重要的概念:参数和返回值,用于更加灵活的使用函数;
参数:
// 带参数的void类型函数
// 控制输出的星数
// num:每行个数
// line:行数
// def:显示的字符
void star(int num, int line, string def = "*") {
for(int i=1;i<=line;i++){
for(int j=1;j<=num;j++){
cout << def;
}
cout << endl;
}
// 特别注意:函数里声明的变量num,line,def,i,j在star函数体外无法识别
}
int main() {
// 调用,并传参
star(5, 5);
star(3, 3, "@");
return 0;
}
返回值:
// 计算一个圆的面积和周长的和
// 圆的面积:π * r * r
float area(int r) {
float pi = 3.14;
return pi * r * r;
}
// 圆的周长:π * r * 2
float circ(int r) {
float pi = 3.14;
return pi * r * 2;
}
int main() {
// 输入半径r
int r;
cin >> r;
// 计算面积+周长的和
cout << area(r) + circ(r);
return 0;
}
之前一直在使用变量,即:可以改变的量;而常量是相对的产物,即:定义后就不可改变的量;
常量:
// 创建一个常量PI
const float PI = 3.14;
// 圆的面积:π * r * r
float area(int r) {
return PI * r * r;
}
// 圆的周长:π * r * 2
float circ(int r) {
return PI * r * 2;
}
// 1. 甲乙两者年龄只和是两位数
// 2. 这个两位数是一个质数
// 3. 这个质数(个位+十位=13)
// 4. 甲比乙大13
// 求甲乙分别是多少?
// 声明和变量
int sum = 0;
// 枚举(穷举)出所有情况
// 假设乙最小1,那么甲就是14,乙最大就是99-13=86
// 循环1-86之间,但当乙到达44时,和为101,也就是说43是头
for(int i=1;i<=43;i++){
// 求和
sum = i + (i + 13);
//cout << i << " " << sum << endl;
// 判断这个和是不是质数以及数字之和是13
// 先用常规方法,然后改函数,第一次用函数会因缺少经验无从下手
// 标记
bool flag = true;
// 判断质数,只能被1和本身整除
for(int j=2;j<=sum-1;j++){
if (sum % j == 0) {
flag = false;
break;
}
}
// 标记判断
if (flag == false) continue;
//cout << i + 13 << " " << i << " " << sum << endl;
// 判断数字之和13
int a = sum / 10;
int b = sum % 10;
if (a + b == 13) {
cout << i + 13 << " " << i << " " << endl;
}
}
// 判断质数
bool isZ(int n) {
for(int j=2;j<=n-1;j++){
if (n % j == 0) {
// 只要执行了return 函数就终止执行
return false;
}
}
// 上面循环体没有执行return,就继续执行下面的return
return true;
}
// 判断和
bool isS(int n) {
int a = n / 10;
int b = n % 10;
// 执行了return true将终止往下执行
if (a + b == 13) return true;
// 没有执行true,则继续返回false
return false;
}
int main() {
int sum = 0;
for(int i=1;i<=43;i++){
sum = i + (i + 13);
// 判断输出
if (isZ(sum) && isS(sum))
cout << i + 13 << " " << i << endl;
}
return 0;
}
// 求约数和
int sum(int n) {
int tmp = 0;
// 1到n-1,题目说除了本身
for(int i=1;i<=n-1;i++){
if (n % i == 0) tmp += i;
}
return tmp;
}
int main() {
int a, b;
cin >> a >> b;
//if ((对a求约数和) == b && (对b求约数和) == a)
if (sum(a) == b && sum(b) == a) cout << "yes";
else cout << "no";
return 0;
}
// 之前学习过除了函数的变量作用域
// 1. 我们可以意识到:函数体内的变量,其它函数或外部全局都无法识别
// 2. 外部全局声明的变量,叫做全局变量,所有区域均可识别
// 3. 当然,至于全局和局部变量重名会怎样,可自行测试,建议别重名
// 在和main等函数同一平级声明的变量为全局变量
// 我们要创建一个全局计数器变量cnt;
int cnt = 0, a[1500];
// 判断闰年函数
void isR(int year) {
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
//cnt++;
//cout << year << endl;
// 这里的顺序是a[cnt] = year, 然后cnt++
a[cnt++] = year;
}
}
int main() {
// 题目非常初级,主要学习下函数,实际答题中并不强制
int x, y;
cin >> x >> y;
// 循环
for(int i=x;i<=y;i++){
// 判断闰年,将判断的方式作为函数处理
// 它需要判断后输出,或者不输出,可以用void类型,否则还需要返回判断
isR(i);
}
cout << cnt << endl;
// 输出
for(int i=0;i<cnt;i++){
cout << a[i] << " ";
}
return 0;
}
graph LR
A["fn(n)"]-->B["fn(n-1)"]
B-->C["fn(n-2)"]
C-->D["fn(n-3)"]
D-->E["fn(直到1)"]
// 什么是递归?即:通过函数自我执行的方式表现出循环的效果
// 求n!,也就是阶乘,之前做过,这次作为递归入门
// 之前用循环做的,如下:
// i = 1, 1
// i = 2, 1 x 2
// i = 3, 1 x 2 x 3
// i = 4, 1 x 2 x 3 x 4
// i = n, 1 x ... x n
// fn
int fn(int n) {
// 假设n=4,然后递减循环 4 3 2 1
// 递归则不需要再循环
// 递归思维:n x (n - 1) x (n - 2) x (n - 3) ...
// 理 解:return n * fn(n - 1);
// 调 用:fn(4)
// 第一轮:return 4 * fn(3),fn(3)又调用了自己,就进入第二轮
// fn(3)这块本身是:return 3 * fn(n-1) 也就是:3 * fn(2)
// 第二轮:return 4 * 3 * fn(2)
// 第三轮:return 4 * 3 * 2 * fn(1) 1到头了,单独判断返回1即可
// ...
// 最终轮:fn(1),判断if n == 1 return 1即可,最终为:return 4 * 3 * 2 * 1
// 先判断1停止递归
if (n == 1) return 1;
// 递归
return n * fn(n - 1);
}
int main() {
int n;
cin >> n;
// 递归求n!
cout << fn(n);
return 0;
}
// 树根
int fn(int n) {
int sum = 0;
// 短除
while(n != 0){
sum += n % 10;
n /= 10;
}
// 判断sum是否是个位数
if (sum < 10) return sum;
// 递归
return fn(sum);
}
int main() {
int n;
cin >> n;
// 调用函数
cout << fn(n);
return 0;
}
(https://cdn.limfx.pro/-img-9dc95fbc-f7b6-4ae0-b095-037cbda041eb-articles-9714a544-0efe-455f-bfbf-1073e7c0692f-articelcontent-bce1dbd2-4ba9-4483-a788-7c3e475c8198/image-20240125161802209.png)
// 1. 移动只能一块一块移动
// 2. 大的不能放到小的上面
// 3. 最终状态从A到C状态,如上图
// 手动计步如下:
// 1块:1步
// 2块:3步
// 3块:7步
// 4块:15步
// 要求输入n块,<= 20,求多少步
// 已知n == 1,那么就 1 步
// 假设n == 2,先将小块移动到B,花了1步,大块移动到C花了1步,小块再移动到C;
// 结论:小块2步 + 大块1步 = 3步
// 假设n == 3,先将小块移动到C,花了1步,中块移动到B,花了1步,小块移动到B,花了2步
// 大块移动到C,花了1步,小块移动到A,花了3步,中块移动到C,花了2步
// 小块移动到C,花了4步
// 结论:小块4步 + 中块2步 + 大块1步 = 7步
// 假设n == 4,结论:8 + 4 + 2 + 1 = 15,找到规律:每次都是x2的步数,也就是2的n次方-1
// 用这种规律直接:2 * 2 * 2 * 2 - 1 = 15 步;
// 非常有意思的事,深入研究规律后,直接循环做出来了。根本无需递归
int n;
cin >> n;
int step = 1;
// 输出
for(int i=1;i<=n;i++){
step *= 2;
}
cout << step - 1;
// 那我们再思考用递归来做一下:
// 步数:n = 1, 2, 3, 4 步 = 1, 3, 7, 15
// 公式:2 * fn(n - 1) + 1,fn(n - 1)是上一层,x 2 + 1 = 本层步数
// 代码:return 2 * fn(n - 1) + 1,方便理解,列出轮次:
// 第一轮:return 2 * fn(3) + 1
// 第二轮:return 2 * (2 * fn(2) + 1) + 1
// 第三轮:return 2 * (2 * (2 * fn(1) + 1) + 1) + 1
// 第四轮:return 2 * (2 * (2 * 1 + 1) + 1) + 1 = 15
// 汉诺塔
int fn(int n) {
// n == 1
if (n == 1) return 1;
return 2 * fn(n - 1) + 1;
}
int main() {
int n;
cin >> n;
cout << fn(n);
return 0;
}
// 1. 每一天吃当前数量的一半+1个
// 2. 第n天发现只剩1个
// 3. 求共多少个
// 假设n == 4,剩1个
// 没有思路就先猜,第3天,大概是4个,吃一半加1个,正好剩1个,这个很容易猜到;
// 但我们可能要cin >> n,fn(n);输入4,不可能判断n == 4 return 1;
// 但我们知道n == 1是第一天,我们要反向思考这题:
// 原本:1:22 2:10 3:4 4:1 从后向前推:(当前 + 1) * 2
// 反向:1:1 2:4 3:10 4:22
// 换成递归格式为:return (fn(n-1) + 1) * 2,并且 n == 1 return 1;
// 轮次列表:
// 第一轮:return (fn(3) + 1) * 2
// 第二轮:return (((fn(2) + 1) * 2) + 1) * 2
// 第三轮:return (((((fn(1) + 1) * 2) + 1) * 2) + 1) * 2
// 第四轮:return (((((1 + 1) * 2) + 1) * 2) + 1) * 2 = 22
// 猴子吃桃
int fn(int n) {
// 界限
if (n == 1) return 1;
// 逆推
return (fn(n-1) + 1) * 2;
}
int main() {
int n;
cin >> n;
// 递归
cout << fn(n);
return 0;
}
// 先硬算,然后找规律
// n:块数
// 1:1 2:3 3:6 4:10 5:15
// 1:1
// 2:1+2
// 3:1+2+3
// 4:1+2+3+4
// 5:1+2+3+4+5
// 方块
int fn(int n) {
// 界限
if (n == 1) return 1;
// 上一层的个数 + 本层多出来的 = 本层个数
return fn(n - 1) + n;
}
int main() {
int n, sum = 0;
cin >> n;
// 题目要求将所有层数将每一层累加
for(int i=1;i<=n;i++){
sum += fn(i);
}
cout << sum;
return 0;
}
// 数据范围:10的18次方= 1000000000000000000
// int取值范围:-2147483648~2147483647 (10的10次方)
// long long取值范围 9223372036854775808~+9223372036854775807 (10的19次方)
// 故这里取long long 长整型
// 分割,求最大公约数
long long fn(long long m, long long n) {
// 辗转相除法->欧几里得算法
// 算法:
// 1. 如果m % n == 0,那么n是最大数公约数,比如 8 % 4 == 0,4 就是
// 2. 如果m % n != 0,假设:m = 15 n = 12,将12交给m,将15%12余数交给n
// 3. 递归直到 == 0;
// 求余判断
if (m % n == 0) {
return n;
} else {
return fn(n, m % n);
}
}
int main() {
long long m, n;
cin >> m >>n;
// 求值
cout << fn(m, n);
return 0;
}
#include <iostream>
#include <cmath> // 数序函数库 或math.h
using namespace std;
int main() {
// 绝对值
cout << abs(-5) << endl;
// 向上取整,有小数进一位,5.11=6
cout << ceil(5.11) << endl;
// 向下取整,截断取,5.95=5
cout << floor(5.95) << endl;
// 四舍五入
cout << round(5.55) << endl;
// 平方根
cout << sqrt(16) << endl;
// 幂函数,10的4次方的值
cout << pow(10, 4) << endl;
// 自然常数e为:2.71828...
// exp(n)为指数函数,获取e的n次方,1次方即自己
cout << exp(1) << endl;
// 对数函数log(n),即幂的逆运算
// 获取以e为底的n的对数
cout << log(exp(3)) << endl;
// 还有sin(正弦)、cos(余弦)、tan(正切)启蒙涉及不到
return 0;
}
// 取最小值
cout << min(1, 9) << endl;
// 取最大值
cout << max(1, 9) << endl;
// 用函数减少重复
float dis(float a, float b, float c, float d) {
return sqrt((a - b) * (a - b) + (c - d) * (c - d));
}
int main() {
float x1, x2, x3, y1, y2, y3, sum = 0;
cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
// 两点距离:
sum += dis(x2, x1, y2, y1);
sum += dis(x3, x2, y3, y2);
sum += dis(x3, x1, y3, y1);
// 输出
printf("%.2f", sum);
return 0;
}
#include <iostream>
#include <math.h>
using namespace std;
int main() {
int a, b, c, d;
// 循环四位数
for(int i=1100;i<=9988;i++){
a = i / 1000;
b = i / 100 % 10;
c = i / 10 % 10;
d = i % 10;
// 判断
// 四位的车号刚好是一个整数的平方
// sqrt(16) = 4,怎么判断4的平方是16
// sqrt(26) = 5.xxx sqrt(25) = 5
// 4 x 4 = sqrt(16) * sqrt(16)
// floor(sqrt(26)) = 5 ?= sqrt(26) = 5.xxx
if (a == b && c == d && a != c && sqrt(i) == floor(sqrt(i))) {
cout << i << endl;
}
}
return 0;
}
// 判断质数
bool isP(int x) {
// 1不是质数,直接返回0。
if (x == 1) return 0;
// 循环验证质数,1和本身不参数,2~x-1
// for(int i=2;i<=x-1;i++)
// 优化算法:
// 1.假设x = 16,它不是质数,因子有:2, 4, 4, 8
// 2.假设x = 20,它不是质数,因子有:2, 4, 5, 10
// 3.假设x = 30,它不是质数,因子有:2, 3, 5, 6, 10, 15
// 寻找规律:
// 1.这些因子的最大值,基本是数值的一半,i<=x/2即可;
// 2.这些因子中间来一刀,左右两侧是配对的。比如x=30,只要循环到5-6之间即可,sqrt(30)
// 循环验证
for(int i=2;i<=sqrt(x);i++){
if (x % i == 0) return false;
}
return true;
}
int main() {
int n;
cin >> n;
// 循环1-n赋值
for(int i=1;i<=n;i++) {
// 题目要求存入数组,本题其实没必要,它只能检测结果,不能检测你代码
int tmp;
cin >> tmp;
if (isP(tmp)) cout << tmp << " ";
}
return 0;
}
// 计算每个学生的得分
float score(int x[], int m) {
int minn = 11, maxn = -1, sum = 0;
// 遍历数组x
for(int i=1;i<=m;i++){
// 大小
minn = min(x[i], minn);
maxn = max(x[i], maxn);
// 累加
sum += x[i];
}
return float(sum - minn - maxn) / (m - 2);
}
int main() {
int n, m, a[21];
float maxn = -1;
cin >> n >> m;
// 外层循环选手
for(int i=1;i<=n;i++){
// 内层循环分数,并赋值
for(int j=1;j<=m;j++) cin >> a[j];
// 将每个学员的分数组传给函数处理返回平均分
maxn = max(maxn, score(a, m));
}
// 输出
printf("%.2f", maxn);
return 0;
}
字符类型,即:char 类型 或 C 风格字符串,可以存储字符或字符串的类型;
字符类型说明:
强调一下:char 类型 不是 string,string是声明的字符串,可以放一串字符;而char,只能放一个;
如何表示字符串?可以用字符数组来表示:
a[0] | a[1] | a[2] | a[3] | a[4] | a[5] |
---|---|---|---|---|---|
h | e | l | l | o | \0 |
//char a = 'A';
//cout << a;
// 5位不够,需要预留一位存储\0(空字符null)来表示结束
char a[6] = "hello";
cout << a;
初始化声明方法和普通数组差不多:
// 初始化字符数组
char a[6];
// 初始化并直接赋值
char b[6] = {"hello"};
// 初始化并赋值初始值
char c[6] = {0};
// 动态初始
char d[] = {"world"};
ASCII码,即:美国标准信息交换代码;用于和计算机数据通信;
通过上述表查阅到:小写a的十进制编码为97,然后逐步递增。大写的A是65,往后逐步递增;
什么是十进制,ASCII码到底如何和计算机通信,解决了啥问题?自己百度查阅,我们只关注答题啊;
// 字符型a
char a = 'a';
// 输出它的十进制,即整型数值
cout << int(a);
// 整型数值65
int b = 65;
// 输出它的字符
cout << char(b);
char a;
cin >> a;
// 查表:a 97,A 65 梳理两点:
// 1. a跑到A,a - 32 = 65
// 2. A跑到a,A + 32 = 97
// 是否需要转换整数后判断?答:不需要
// 直接字符判断即可,它底层会自行转换判断
// 直接判断>='A',意味>=97,得到大写的范围
if (a >= 'A' && a <= 'Z') {
a += 32;
} else {
a -= 32;
}
// 输出a
cout << a;
char a[110] = {0};
cin >> a;
// 1. 小写变大写,其它不变
// 2. 如果本身是大写,则不变
// 3. 如果是数字和符号,则不变
// 怎么循环去判断是否要大写?
// 可以判断字符数组最后一位是'\0'结束
// cout << a[0]; 从0开始填入字符的
// 死循环
int cnt = 0;
while(1){
// 遇到结尾就退出
if (a[cnt] == '\0') break;
// 判断是小写
if (a[cnt] >= 'a' && a[cnt] <= 'z') a[cnt] -= 32;
// 累加
cnt++;
}
// 输出
cout << a;
char a[60] = {0};
int n;
cin >> n;
cin >> a;
// 上节课用while结合\0 break,这次用for
// 注意:字符数组从0开始,条件虽然也可以死循环,但也可以直接判断
// for(int i=0;a[i]!='\0';i++) 直接判断不等于结尾就一直循环
// 当然,还可以简化,直接 a[i] 也行,因为 \0 和 0 一样,表示false
for(int i=0;a[i];i++){
// 假设n=1,xyz = yz{,缺少越界判断
// cout << char(int(a[i]) + n);
int tmp = int(a[i]);
// a 97 z 122
// 假设 n 10, y 121 + 10 = 131, 131 - 122 + 97 - 1即可
if (tmp + n > 122) {
cout << char(tmp + n - 122 + 97 - 1);
} else {
cout << char(tmp + n);
}
}
字符数组是如何获取它的长度,比如占用多少,或者有多少个字符?之前的题目,都只是判断\0结束
sizeof:
它可以返回一个字符数组所占的内存字节数(字节数理解为:数组分配的一个个小格子)
比如 : char a[10] = "hello" , 它占用了多少?
// 占用10个字节,{"hello"} 和 {'h','e','l','l','o'}; 都一样
char a[10] = "hello";
cout << sizeof(a);
// 占用6个字节,不定式,末尾\0占一个
char a[] = "hello";
cout << sizeof(a);
所以,想用 sizeof 操作符 来 获取字符个数,其实并不方便。当然,用 a[] 这种 ,然后 - 1也可以。
cstring是 C 标准库头文件, 包含了一些 C 风格字符串的类型和函数;
基本使用:
首先要引入 cstring : #include
#include <iostream>
#include <cstring>
using namespace std;
使用 strlen() 函数 来获取 字符数组的长度:
// cstring下的strlen函数获取
// 并不会统计占用,也不会统计结束符
// 结果为:5
char a[10] = "hello";
cout << strlen(a);
使用 strcpy() 和 strncpy() 函数赋值字符数组:
// 无法直接复制
// char b[20] = a;
// cout << b;
// strcpy复制字符数组
char b[20];
strcpy(b, a);
cout << b;
// strncpy复制指定个数
char c[20];
strncpy(c, a, 3);
cout << c;
使用 strcat() 和 strncat() 函数,连接字符数组:
// 连接两个字符数组
char a[20] = "hello";
char b[10] = ", world!"; // 函数本身会返回连接后的字符串 // 参数1:被添加的字符数组; // 参数2:添加的字符数组; cout << strcat(a, b) << endl; // a被添加了,所以它增加了字符 cout << a << endl; // b不变 cout << b << endl;
// 连接部分字符数组 char a[20] = "hello"; char b[10] = ", world!"; cout << strncat(a, b, 5) << endl; cout << a << endl; cout << b << endl;
- 使用 **strchr()** 和 **strstr()** 函数,来实现字符数组查找:
```c++
// 查找字符在数组中的位置
char a[20] = "hello, world!";
// 获取第一次查询到的字符位置,并往后输出字符
cout << strchr(a, 'o');
// 获取到底是第几个位置
cout << strchr(a, 'o') - a + 1;
// 查询一串字符在数组中的位置
char a[20] = "hello, world!";
cout << strstr(a, "or");
cout << strstr(a, "or") - a + 1;
char s[110];
int a[130] = {0};
cin >> s;
// 循环输入的字符
// 获取长度,strlen返回的是size_t(无符号整型),用int转换
for(int i=0;i<=int(strlen(s));i++){
// 转换成ascii,移位到数组初始,并累计
a[int(s[i])]++;
}
// 假设a最大
int maxn = 97;
// 输出字母的ascii次数
for(int i=98;i<=122;i++){
// 比大小,注意这里必须有等于,方便将ascii码大的交给maxn
if (a[maxn] <= a[i]) maxn = i;
}
// 输出
cout << char(maxn);
char s[110];
cin >> s;
// 获取字符总长度
int len = strlen(s);
// 获取逗号所处的位置
int index = strchr(s, ',') - s + 1;
// 循环输出
for(int i=index;i<=len-1;i++) cout << s[i];
// 输出逗号
cout << ',';
// 复制逗号左的字符
char left[len] = {0};
strncpy(left, s, index - 1);
cout << left;
char s[110];
int a[30] = {0}; // 从0开始存储a-z
cin >> s;
// 求出s长度
int len = strlen(s);
// 最大最小值
int maxn = -1, minn = len;
// 循环97-122
// 或者0-25,用当前字母的ascii-97或-'a'即可
// cout << 98 - 'a'; 相当于98 - 97
for(int i=0;i<=len-1;i++){
a[s[i] - 'a']++;
}
// 求最大值和最小值
for(int i=0;i<=25;i++){
if (a[i] != 0) {
maxn = max(maxn, a[i]);
minn = min(minn, a[i]);
}
}
// 判断质数
int d = maxn - minn;
// 特殊
if (d == 0 || d == 1) {
cout << "No Answer" << endl;
cout << 0;
return 0;
}
// 循环
for(int i=2;i<=sqrt(d);i++){
if (d % i == 0) {
cout << "No Answer" << endl;
cout << 0;
return 0;
}
}
// 输出结果
cout << "Lucky Word" << endl;
cout << maxn - minn;
// 判断是否回文
bool isHW(char x[]) {
int len = strlen(x);
// 情况1:回文必须是偶数
if (len % 2 != 0) return false;
// 情况2:必须是回文
// 假设传过来的是: ABBA,判断03、12是否相等
// 假设传过来的是: ABBAABBA,判断07、16、25...是否相等
for(int i=0;i<=len/2-1;i++){
if (x[i] != x[len - 1 - i]) return false;
}
return true;
}
int main() {
char s[110];
cin >> s;
// 截取一半,如果用strcpy也行,但需要另外创建一个字符数组变量
// 此方法,给一半后面位置强行改为0,表示结束了
// s[len / 2] = '\0';
// cout << s;
// 截取后的字符数组
// 循环判断是不是回文:即倒过来也一样
while(isHW(s)){
s[strlen(s) / 2] = '\0';
}
// 输出最终长度
cout << strlen(s);
return 0;
}
string是标准模板库 STL 中提供处理字符串的工具类型,可以直接赋值使用,无须设置数组;
字符串类型:
可以直接赋值,无须数组化,但本身又是数组;
string是弹性长度,根据你赋值的内容自动伸缩,无须考虑赋值越界问题;
// 字符串需双引号
string s = "hello!";
cout << s;
// string本身也是数组
cout << s[0];
cout << s[3];
cout << s[5];
字符串类型,有非常多的实用函数工具,这里把最最常用的罗列出来,后续课程逐步补充
首先,字符串类型 string 本质是一个类(和之前的类型有所区别),它函数语法是类形式的语法:
// 字符串
string s = "hello";
// 获取字符串长度size()或length()方法
cout << s.size();
cout << s.length();
cout << s.max_size(); // 获取最大字符数
// 拼接方法append(),在s后面添加字符串
s.append(", world!");
cout << s;
// 拼接字符串,直接用+号也能实现
s += ", world!";
cout << s;
// 插入字符(一个),push_back()末尾插入
s.push_back('a'); // 一个字符单引号
cout << s;
// 指定位置插入字符或字符串:insert()
s.insert(3, "@@@"); // 字符串形式,两个参数:位置和字符串
cout << s;
s.insert(3, 4, '#'); // 字符形式,三个参数:位置、个数、单个字符
cout << s;
// 查找字符串中是否包含某个字符:find()
// 不存在返回:-1,存在返回:位置
cout << s.find("ll"); // 只有一个参数时
// 参数2,从第几个位置查找,自然找不到,会返回一个超大的数
// 超大数不好判断没找到,一般是最好返回-1
// 但由于find()本身返回的是无符号整数,即:没有负数,所以无法返回-1
// 直接用 int 转换下即可
cout << int(s.find("ll", 3)) << endl;
// 或赋值方案
int index = s.find("11", 3);
cout << index;
// 字符串截取:substr
cout << s.substr(2); // 从第2个位置截取到最后
cout << s.substr(2,2); // 从第2个位置截取2个
其它现代语言数据类型转换都比较方便,而C++这种语言机制导致转换起来较为麻烦
char字符转int:
// 先抛出问题:string数字转int,常规方法int转不了
string x = "97";
cout << x + 1; // 语法错误,无法相加
cout << int(x) + 1; // 语法错误,无法转换
// 字符 char转ascii码
char y = 'a';
cout << y; // 输出字符a
cout << int(y); // 输出ascii码97,所以,用int转换char字符,只会得到ascii码
// 字符数字 char转int
char z = '8';
cout << int(z); // 输出的是56,得到的是ascii码
cout << z - '0'; // 输出的是8,可以得到整型8
cout << z - '0' - 1; // 输出的是7,为了验证是不是int,减1便知
cout << atoi(&z); // 输出的是8,&表示z变量的引用地址(指针),不用理解,记住语法即可
// 关于指针和引用地址,会在后续课程中专门篇幅讲解(不是本套),目前都是有意避开,避不开的强记
将 string 转换成 int 的思路:就是先让 string 变成 char 的引用,然后用 atoi() 函数转换
string字符转int:
// string转int
string k = "123";
// 先转换到char的指针,使用c_str()函数就是这个意思
// 然后再用atoi函数包裹转成int
cout << atoi(k.c_str()) + 1; // 124
// 当然还提供了直接转换的函数stoi
string p = "456";
cout << stoi(p);
string s;
cin >> s;
// +号位置
int i = s.find("+");
// left
string a = s.substr(0, i);
// right 1+2=
string b = s.substr(i+1, s.length() - (i+1) - 1);
// 输出
cout << atoi(a.c_str()) + atoi(b.c_str());
string s;
cin >> s;
int p = s.find("=");
// left
string a = s.substr(0, p);
// right
string b = s.substr(p+1);
// 假设1234,则有三种情况:123+4 12+34 1+234
for(int i=1;i<=p-1;i++){
int x = stoi(a.substr(0, p-i));
int y = stoi(a.substr(p-i));
if (x + y == stoi(b)) {
printf("%d+%d=%d", x, y, stoi(b));
return 0;
}
}
// 输出
cout << "Impossible!";
在读入字符串时,遇到换行和空格,它是认为下一次 cin 读入,这给我们编码带来一些麻烦
getline()读入一整行:
// 先抛出问题,假设s1输入=> hello world!
string s1;
cin >> s1;
cout << s1; // 结果为hello,空格后的字符串会理解为下一次cin
// scanf也不行
string s2;
scanf("%s", &s2); // 直接报错,无法使用
cout << s2;
// scanf单字符输入
char a;
scanf("%c", &a); // 单字符输入,不管输入多少,得到1个字符
cout << a;
// scanf字符数组输入,字符数组本身是引用地址,无须&前缀
char s[10];
scanf("%s", s); // 输入多少,输出多少,可是遇到空格就没了
cout << s;
// getline(cin, str) 参数1:固定cin,参数2:输入的字符串变量 // getline()函数 适用于 string类型 string s; getline(cin, s); // 输入 hello world! 不会被空格断掉 cout << s;
### 2. fgets()函数
> 对于字符数组,我们可以采用 fgets() 函数读入一整行
- fgets()读入一整行:
```c++
// 字符数组s
char s[20];
// 参数1:要存储的字符数组
// 参数2:限定最大读入长度,防止越界
// 参数3:固定参数,表示标准输入
fgets(s, sizeof(s), stdin);
cout << s;
cin.getline()读入一整行:
// 和fgets()函数类似
char s[20];
cin.getline(s, sizeof(s));
cout << s;
string s;
getline(cin, s);
int cnt = 0;
// 统计
for(int i=0;i<=(int)s.length()-1;i++){
// string被拆分单字符,用单引号判断
if (s[i] != ' ') cnt++;
}
cout << cnt;
string s;
getline(cin, s);
string x;
getline(cin, x);
// 查找位置
int p = s.find(x);
// 判断
if (p == -1) {
// 总长度
int len = s.length();
// 去掉空格数
for(int i=0;i<=(int)s.length()-1;i++){
if (s[i] == ' ') len--;
}
// 去掉末尾点
cout << len - 1;
}
else {
int cnt = 0;
// 计算到p的空格数
for(int i=0;i<=p;i++){
if (s[i] == ' ') cnt++;
}
// 三个空格,就是第四个单词
cout << cnt + 1;
}
本节课,学习一下 cctype 头,让我们更舒适的去判断数字、字母或其它值的判断
cctype 标准头:
#include <cctype> // 不同的版本,可能非必要导入
char a = 'A';
// isalpha() 判断一个字符是否是字母(a-zA-Z)
cout << isalpha(a); // 非字母返回0,小写字母返回2,大写返回1
// isdigit() 判断一个字符是否是数字(0-9)
cout << isdigit(a); // 非数字返回0,数字返回1
// isalnum() 判断一个字符是否是数字、字母(0-9a-zA-Z)
cout << isalnum(a); // 非返回0,数字4,小写2,大写1
// islower() 判断小写字母(a-z)
// isupper() 判断大写字母(A-Z)
// ispunct() 判断标点符号
// isspace() 判断空格、制表符、换行符
// isblank() 判断空格、制表符
// 转换大小写 char b = 'A'; cout << char(toupper(b)); // 转换成大写 cout << char(tolower(b)); // 转换成小写
# 128. P1308.NOIP2011.普及组.统计单词数
<div style="text-align:right;color:#666;font-size:20px;">主讲老师 - 李炎恢</div>
### 1. 代码详解
```c++
// 转成小写
string to_lower(string x) {
// 先将字符全部转换成小写
for(int i=0;i<=(int)x.length();i++){
// 如果是大写字母,就转成小写
if (isupper(x[i])) {
x[i] = char(tolower(x[i]));
}
}
return x;
}
int main() {
string w, s;
getline(cin, w);
getline(cin, s);
// 处理大小写
w = to_lower(w);
s = to_lower(s);
// 单词而不是字符串,需要给单词前后加上空格
w = " " + w + " ";
s = " " + s + " ";
// 判断是否找到
int i = s.find(w);
// 找不到直接-1
if (i == -1) {
cout << -1;
} else {
int cnt = 0;
int f = i; // 第一次出现的位置
// 有多个单词,用while循环逐个找
while(i != -1){
cnt++; // 找到一个就+1
i = s.find(w, i + 1); // 在i位置找到,就+1位置往后继续找
}
cout << cnt << " " << f;
}
return 0;
}
string s;
cin >> s;
// 连续字符,初始空字符串
string num, maxn = "";
// 循环
for(int i=0;i<=(int)s.length()-1;i++){
// 判断是否是数字
if (isdigit(s[i])) {
num += s[i];
} else {
// 把连续的数字字符比较后赋值给maxn
if (num.length() > maxn.length()) maxn = num;
// 清空
num = "";
}
}
// 输出位置
cout << s.find(maxn) + 1;
int n, a, b;
char p = ' ';
// 这里需要\n,因为getline读取一行,会读取到换行符,导致漏行
scanf("%d\n", &n);
// 循环
for(int i=1;i<=n;i++){
string s;
getline(cin, s);
// 判断字符第一位是否为数字
if (isdigit(s[0])) {
a = stoi(s);
b = stoi(s.substr(s.find(" ") + 1));
} else {
p = s[0];
s = s.substr(2);
a = stoi(s);
b = stoi(s.substr(s.find(" ") + 1));
}
// 先将a和b,外加运算符长度得到
int len = (to_string(a) + to_string(b)).length() + 2;
// 运算
switch (p) {
case 'a':
printf("%d+%d=%d\n", a, b, a+b);
len += (to_string(a+b)).length();
printf("%d\n", len);
break;
case 'b':
printf("%d-%d=%d\n", a, b, a-b);
len += (to_string(a-b)).length();
printf("%d\n", len);
break;
case 'c':
printf("%d*%d=%d\n", a, b, a*b);
len += (to_string(a*b)).length();
printf("%d\n", len);
break;
}
}
结构体:即一组变量的聚合体,可以将非同类型的数据绑定成一体的这么个东西
// 结构体类型创建,并对内部变量直接赋初始值
struct info {
string name = "王二狗";
int age = 15;
char gender = 'A';
float weight = 1.55;
bool flag = true;
};
// 定义一个结构体变量:struct info a;
// 而struct可以省略,方便阅读,可以把info当成自定义类型
info a;
int main() {
// 调用结构体变量
cout << a.name << endl;
cout << a.age << endl;
cout << a.gender << endl;
cout << a.weight << endl;
cout << a.flag << endl;
return 0;
}
// 初始化交给变量声明
struct info {
char name[20];
int age;
char gender;
float weight;
bool flag;
};
// 可以初始化{}
info a = {};
// 初始化0,需要把string改为char name[20],否则报错
info a = {0};
// 对标赋值
info a = {"张三", 12, 'B', 1.38, true};
// 还有一种结合在一起的写法
struct info {
char name[20];
int age;
char gender;
float weight;
bool flag;
} a = {"张三", 12, 'B', 1.38, true};
结构体数组:如果要实现多组结构体数组,和普通数据使用方法一样,结合结构体语法即可
数组语法:
struct grade {
string name;
int age;
char gender;
};
int main() {
// 不省略struct,提高可读性
struct grade s[3] = {{"张三", 15, 'A'}, {"李四", 14, 'B'}, {"王五", 13, 'A'}};
// 输出结构体数组第一条
cout << s[0].name << " " << s[0].age << " " << s[0].gender;
return 0;
}
// 学员信息
struct info {
string name;
int age;
int score;
};
int main() {
// 初始化结构体
struct info stu[10];
int n;
cin >> n;
// 赋值
for(int i=1;i<=n;i++) cin >> stu[i].name >> stu[i].age >> stu[i].score;
// 计算
for(int i=1;i<=n;i++){
// 年龄+1岁
stu[i].age++;
// 分数+20%,但不大于600分
if (stu[i].score * 1.2 < 600) stu[i].score *= 1.2;
else stu[i].score = 600;
}
// 输出
for(int i=1;i<=n;i++){
cout << stu[i].name << " " << stu[i].age << " " << stu[i].score << endl;
}
return 0;
}
struct info {
char name[10];
int chi;
int mat;
int en;
};
int main() {
struct info stu[1010];
int n;
cin >> n;
// 赋值
for(int i=1;i<=n;i++)
cin >> stu[i].name >> stu[i].chi >> stu[i].mat >> stu[i].en;
// 求最大值
int maxn = -1, index = -1;
for(int i=1;i<=n;i++){
// 总分
int total = stu[i].chi + stu[i].mat + stu[i].en;
if (maxn < total) maxn = total, index = i;
}
// 输出最厉害
cout << stu[index].name << " " << stu[index].chi << " "
<< stu[index].mat << " " << stu[index].en;
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
// 结构体
struct info {
char name[20];
char uid[10];
char sex;
};
struct info stu[1010];
int n;
// 性别判断
char getSex(char str[], int mark) {
char sex;
for(int j=1;j<=n;j++){
char tmp[20];
if (mark == 0) strcpy(tmp, stu[j].uid);
else strcpy(tmp, stu[j].name);
// 对比所有uid或name
if (strcmp(str, tmp) == 0) {
sex = stu[j].sex;
}
}
return sex;
}
// isD
char isD(char s[]) {
if (isdigit(s[0])) return getSex(s, 0);
else return getSex(s, 1);
}
int main() {
cin >> n;
// 赋值
for(int i=1;i<=n;i++)
cin >> stu[i].name >> stu[i].uid >> stu[i].sex;
// 询问
int m;
cin >> m;
char s1[20], s2[20];
for(int i=1;i<=m;i++){
// 读入一组询问
cin >> s1 >> s2;
// 判断性别
if (isD(s1) == isD(s2)) cout << "N" << endl;
else cout << "Y" << endl;
}
return 0;
}
本文章使用limfx的vscode插件快速发布