第一部分 C++编程知识 第三章 分支语句与循环语句
第七节 for循环
一、for循环语法形式
for (表达式1; 表达式2; 表达式3)
语句; //如果循环体想包含更多的语句,可以加上大括号{}
表达式1用于循环变量的初始化。
表达式2用于循环结束条件的判断。
表达式3用于循环变量的调整。
二、for循环的执行流程
首先执行表达式1初始化循环变量。接下来就是执行表达式2的判断部分,表达式2的结果如果为假,则循环结束;表达式2的结果如果为真,则执行循环语句。循环语句执行完后,再去执行表达式3,调整循环变量,然后再去执行判断表达式2的结果是否为0,决定循环是否继续。整个循环的过程中,表达式1初始化部分只被执行1次,剩下的就是表达式2、循环语句、表达式3在循环。
三、for循环的实践
下面我们可以使用for循环写一个简单的代码,来观察for循环的使用。
实现“在屏幕上打印1~10的值”的功能,代码如下:
#include <cstdio>
int main(){
int num = 0;
for (num = 1; num <= 10; ++num)
{
printf("%d ", num);
}
return 0;
}
这段代码就可以实现“在屏幕上打印1~10的值”的功能了,在使用上是比while语句更简单的。值得注意的是,有可能会将上面这段代码写成下面这样:
#include <cstdio>
int main(){
for (int num = 1; num <= 10; ++num){
printf("%d ", num);
}
return 0;
}
这两段代码的区别是,第一段代码中for循环结束后,num的值还可以继续使用,但是代码2中for循环的外边num变量是不可以使用的,num变量只能在for循环中使用。
四、while循环和for循环的对比
for 和 while 在实现循环的过程中都有初始化、判断、调整这三个部分,但是 for 循环的三个部分非常集中,便于代码的维护,而如果代码较多的时候 while 循环的三个部分就比较分散,所以从形式上 for 循环要更优一些。
五、 for循环的应用实例
通过上面的学习,接下来我们可以实现一个比较复杂的功能了——“计算1~100之间3的倍数的数字之和”下面是我解决这个问题所编写的代码:
#include <cstdio>
int main(){
int num = 0;
int sum = 0;
for (num = 1; num <= 100; ++num){
if (0 == num % 3)
sum = sum + num;
}
printf("1到100之间3的倍数的数字之和为:%d", sum);
return 0;
}
当然解决这个问题的办法不止一种,上面的解决方法是最正规按照题目要求的逻辑完成,如果我们换一种算法,也可以直接产生3的倍数,省去了很多次的循环和判断,使代码的效率更高,这是优化后的代码:
#include <stdio.h>
int main(){
int num = 0;
int sum = 0;
for (num = 3; num <= 100; num += 3)
{
sum = sum + num;
}
printf("1到100之间3的倍数的数字之和为:%d", sum);
return 0;
}
【练习一】
班上有学生若干名,给出每名学生的年龄(整数),求班上所有学生的平均年龄,保留到小数点后两位。
· 输入格式:第一行有一个整数n(1 ≤ n ≤ 100),表示学生的人数。其后n行每行有1个整数,表示每个学生的年龄,取值为15到25。
· 输出格式:输出一行,该行包含一个浮点数,为要求的平均年龄,保留到小数点后两位。
【参考答案】
#include <iostream>
#include <iomanip>
using namespace std;
int num, score;
int main(){
cin >> num;
int i = 1;
int sum = 0;
for (i = 1; i <= num; i++){
cin >> score;
sum += score;
}
cout << fixed << setprecision(2) << sum * 1.0 / num << endl;
return 0;
}
【练习二】
2008年北京奥运会,A国的运动员参与了n天的决赛项目(1 ≤ n ≤ 100)。现在要统计一下A国所获得的金、银、铜牌数目及总奖牌数。输入第1行是A国参与决赛项目的天数n,其后n行,每一行是该国某一天获得的金、银、铜牌数目(不超过100)。输出4个整数,为A国所获得的金、银、铜牌总数及总奖牌数。
· 输入格式:第1行是A国参与决赛项目的天数n,其后n行,每一行是该国某一天获得的金、银、铜牌数目,以一个空格分开。
· 输出格式:输出1行,包括4个整数,为A国所获得的金、银、铜牌总数及总奖牌数,以一个空格分开。
【参考输入输出】
【参考答案】
#include <iostream>
using namespace std;
int a, b, c, day;
int suma, sumb, sumc;
int main()
{
cin >> day;
int i = 1;
for (i = 1; i <= day; i++)
{
cin >> a >> b >> c;
suma += a;
sumb += b;
sumc += c;
}
int sum = suma + sumb + sumc;
cout << suma << ' ' << sumb << " " << sumc << ' ' << sum;
return 0;
}
【练习三】
鸡尾酒疗法,原指“高效抗逆转录病毒治疗”(HAART),由美籍华裔科学家何大一于 1996 年提出,是通过三种或三种以上的抗病毒药物联合使用来治疗艾滋病。该疗法的应用可以减少单一用药产生的抗药性,最大限度地抑制病毒的复制,使被破坏的机体免疫功能部分甚至全部恢复,从而延缓病程进展,延长患者生命,提高生活质量。
人们在鸡尾酒疗法的基础上又提出了很多种改进的疗法。为了验证这些治疗方法是否在疗效上比鸡尾酒疗法更好,可用通过临床对照实验的方式进行。
假设鸡尾酒疗法的有效率为 x,新疗法的有效率为 y,如果 y − x 大于5%,则效果更好,如果x − y 大于 5%,则效果更差,否则称为效果差不多。
下面给出 n 组临床对照实验,其中第一组采用鸡尾酒疗法,其他n−1 组为各种不同的改进疗法。请写程序判定各种改进疗法效果如何。
· 输入格式:第一行为整数 n(1 < n ≤ 20);其余 n 行每行两个整数,第一个整数是临床实验的总病例数(小于等于10000),第二个整数是疗效有效的病例数。这 n 行数据中,第一行为鸡尾酒疗法的数据,其余各行为各种改进疗法的数据。
· 输出格式:有 n−1 行输出,分别表示对应改进疗法的效果:如果效果更好,输出 better;如果效果更差,输出 worse;否则输出 same。
【参考答案】
#include <iostream>
using namespace std;
int n, a1, b1;
int main(){
cin >> n;
int i = 2;
cin >> a1 >> b1;
double jixiao = b1 * 1.0 / a1;
for (i = 2; i <= n; i++){
int a2 = 0;
int b2 = 0;
cin >> a2 >> b2;
double xinxiao = b2 * 1.0 / a2;
if (xinxiao - jixiao >= 0.05)
cout << "better" << endl;
else if (jixiao - xinxiao >= 0.05)
cout << "worse" << endl;
else
cout << "same" << endl;
}
return 0;
}
【本题注意点】
1、在算法竞赛中,可能会涉及到部分题目题目部分很长,一定要耐心审题,也不要惧怕题目难度过高。
2、完成本题需要严格遵守以下几点:输入输出格式的严格遵循、浮点数除法的正确实现、循环逻辑的正确控制、浮点数比较的精度问题以及边界条件的处理。
【练习四】
救生船从大本营出发,营救若干屋顶上的人回到大本营,屋顶数目以及每个屋顶的坐标和人数都将由输入决定,求出所有人都到达大本营并登陆所用的时间。
在直角坐标系的原点是大本营,救生船每次从大本营出发,救了人之后将人送回大本营。坐标系中的点代表屋顶,每个屋顶由其位置坐标和其上的人数表示。救生船每次从大本营出发,以速度50米/分钟驶向下一个屋顶,达到一个屋顶后,救下其上的所有人,每人上船1分钟,船原路返回,达到大本营,每人下船0.5分钟。假设原点与任意一个屋顶的连线不穿过其它屋顶。
· 输入格式:第一行,一个整数,表示屋顶数n。接下来依次有n行输入,每一行上包含两个表示屋顶相对于大本营的平面坐标位置的实数(单位是米)、一个表示人数的整数,数之间以一个空格分开。
· 输出格式:一行,救援需要的总时间,精确到分钟(向上取整)。
【参考答案1 —— 基础版】
#include <cmath>
#include <iostream>
using namespace std;
int num;
int main(){
cin >> num;
int i = 1;
double a = 0;
double b = 0;
double c = 0;
double sumtime = 0;
int renshu = 0;
for (i = 1; i <= num; i++)
{
cin >> a >> b;
c = sqrt(a * a + b * b);
double time1 = c / 50 * 2;
cin >> renshu;
double time2 = renshu * 1.5;
double time = time1 + time2;
sumtime += time;
}
cout << (int)ceil(sumtime) << endl;
return 0;
}
【参考答案2 —— 优化版】
#include <iostream>
#include <cmath>
using namespace std;
int n, p;
double x, y;
int main()
{
cin >> n;
double t = 0;
for (int i = 0; i < n; i++)
{
cin >> x >> y >> p;
float dis = sqrt(x * x + y * y);
t += p * 1 + dis / 50 + p * 0.5 + dis / 50;
}
cout << (int)ceil(t) << endl;
return 0;
}
【本题注意点】
1、本题当中应用到了简单的数学知识:直角三角形求斜边长度。
2、两个库函数 —— ceil函数和floor函数
(1)ceil函数 : 接收一个double类型的浮点数x作为参数,返回一个double类型的值。返回值是大于或等于x的最小整数。换句话说,ceil函数会将浮点数向上取整到最接近的整数,定义在头文件< cmath >中。
1)函数原型
double ceil(double x);
2)参数:x —— 需要进行向上取整的浮点数。
3)返回值:返回值是一个double类型的整数,表示大于或等于x的最小整数。
4)示例代码:
#include <cstdio>
#include <math.h>
int main(){
double num1 = 3.14;
double num2 = -3.14;
double num3 = 5.0;
double num4 = -5.0;
printf("ceil(3.14) = %.0f\n", ceil(num1)); // 输出: 4
printf("ceil(-3.14) = %.0f\n", ceil(num2)); // 输出: -3
printf("ceil(5.0) = %.0f\n", ceil(num3)); // 输出: 5
printf("ceil(-5.0) = %.0f\n", ceil(num4)); // 输出: -5
return 0;
}
5)注意事项:ceil函数返回的是double类型,而不是int。虽然返回值是一个整数,但它仍然是浮点数形式。如果需要将其转换为int,需要进行强制类型转换。
(2)floor函数:接收一个double类型的浮点数x作为参数,返回一个double类型的值。返回值是小于或等于x的最大整数。即会将浮点数向下取整到最接近的整数,定义在头文件< cmath >中。
1)函数原型
double floor(double x);
2)参数:x —— 需要进行向下取整的浮点数。
3)返回值:返回值是一个double类型的整数,表示小于或等于x的最大整数。
4)示例代码:
#include <iostream>
#include <cmath>
int main() {
double num1 = 3.14;
double num2 = -3.14;
double num3 = 5.0;
double num4 = -5.0;
std::cout << "floor(3.14) = " << floor(num1) << std::endl; // 输出: 3
std::cout << "floor(-3.14) = " << floor(num2) << std::endl; // 输出: -4
std::cout << "floor(5.0) = " << floor(num3) << std::endl; // 输出: 5
std::cout << "floor(-5.0) = " << floor(num4) << std::endl; // 输出: -5
return 0;
}
【练习五】
,输入一个整数 n,求
。
· 输入格式:输入为一行,含一个正整数 n。
· 输出格式:输出为一行,为 的值,结果保留小数点后 4位小数。
· 说明/提示:1 ≤ n ≤ 1000。
【参考答案1】
#include <cstdio>
#include <iostream>
using namespace std;
int n;
int main(){
cin >> n;
double sum = 0;
double a = 0;
for (int i = 1; i <= n; i++)
{
if (1 == i % 2)
a = 1 * 1.0 / i;
else
a = (-1) * 1.0 / i;
sum += a;
}
printf("%.4f", sum);
return 0;
}
【参考答案2】
#include <iostream>
#include <iomanip>
using namespace std;
int n;
int main()
{
cin >> n;
int i = 0;
float sum = 0;
int flag = 1;
for (i = 1; i <= n; i++)
{
sum += 1.0 / i * flag;
flag = -flag;
}
cout << fixed << setprecision(4) << sum << endl;
return 0;
}
【练习六】
【参考输入输出】
【参考答案】
#include <cstdio>
#include <iostream>
using namespace std;
int n;
int main()
{
int p = 1;
int q = 2;
cin >> n;
int i = 1;
double sum = 0;
for (i = 1; i <= n; i++)
{
sum += q * 1.0 / p;
int ret = p;
p = q;
q = ret + q;
}
printf("%.4f", sum);
return 0;
}