* 对应课程: 4.1.1\~5.3.3
目录
- while 循环
- do-while 循环
- 例子 求对数
- 灵魂三问
- 例1 猜数游戏
- 例2 算平均数
- 例3 对多位数的逆序排列
- for 循环
- 例子 求素数
- 循环嵌套
- 跳出嵌套
- 方法一 接力break
- 方法二 goto
- 例题 数学题
- 例题 正序分解正整数
- 例题 求最大公约数
- 法一 朴素解法
- 法二 辗转相除法
while 循环
while (condition) {
code; // 循环体
}
不多解释, 更详细的请看这篇↓
Day09_while和break
do-while 循环
do{
code; // 循环体
} while (condition);
该结构进入循环的时候不做检查, 即, 代码至少运行一次
注意: 由于圆括号()
表示的是语句, 因此在最后一定要记得加上分号;
例子 求对数
#include <stdio.h>
#include <math.h>
int main()
{
int x;
int ret = 0;
printf("The num ?\n");
scanf("%d", &x);
int t = x;
while (x > 1)
{
x /= 2;
ret++;
}
printf("log2 of %d is %d", t, ret);
if (pow(2, ret) != t)
{
printf("(approximately)");
}
return 0;
}
小套路: x
在参与了运算后改变了, 先用一个t
来备份
灵魂三问
- 循环要执行几次?
- 循环停止时输出了什么?
- 循环结束后, 变量的值是多少?
例1 猜数游戏
计算机想一个数, 告诉玩家的猜测是大还是小, 直到猜中, 最后告诉用户猜了多少次
思路:
+ 随机数, 存入number
+ 一个负责记次数的变量count
初始化为零
+ 让用户输入一个数字a
+ count
递增
+ 判断两者关系, 并输出”大/小”
+ 如果不相等返回第三步
+ 否则输出”猜中”次数
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(time(0));
int number = rand() % 100 + 1;
int count;
int a = 0;
printf("我已经想好了一个1到100以内的整数\n");
do
{
printf("请猜这个1到100之间的整数: ");
scanf("%d", &a);
count++;
if (a > number)
printf("你猜的数偏大\n");
else if (a < number)
printf("你猜的数偏小\n");
} while (a != number);
printf("答案正是%d, 你一共猜了%d次\n", number, count);
return 0;
}
注释:
+ srand(time(0));
的作用是初始化随机数, 具体原理不多解释
简单来说可以理解为 让随机数有随机数的样子
+ 调用rand();
会返回一个随机的整数, 注意区别于其他语言
例2 算平均数
输入一系列正整数, 最后输入-1表示结束, 输出平均数
#include <stdio.h>
int main()
{
int number;
int sum = 0;
int count = 0;
printf("计算平均数\n输入一系列正整数, 最后输入-1表示结束\n");
scanf("%d", &number);
while (number != -1)
{
sum += number;
count++;
scanf("%d", &number);
}
printf("平均数为: %.1f\n", 1.0 * sum / count);
return 0;
}
例3 对多位数的逆序排列
#include <stdio.h>
int main()
{
int x1 = 0, x2 = 0, digit = 0, ans = 0;
printf("\n输入一个多位正整数: ");
scanf("%d", &x1);
x2 = x1;
/* 方法一: 逐位输出 */
printf("\n方法一的结果: ");
while (x1 > 0)
{
digit = x1 % 10;
x1 /= 10;
printf("%d", digit);
}
/* 方法二: 获得转换后的数字再输出 */
while (x2 > 0)
{
digit = x2 % 10;
x2 /= 10;
ans = ans * 10 + digit;
}
printf("\n方法二的结果: %d", ans);
return 0;
}
输出结果如下:
输入一个多位正整数: 700
方法一的结果: 007
方法二的结果: 7
for 循环
引入: 要算阶乘
n!
此时要有一个计数器, 特点是:
开始时要声明, 每次要判断, 最后还要做++
运算
for
的语法
for(count=0; count<max; count++)
作为理解, 可以把 for 读作 对于, 比如:
对于一开始的
count=0
, 当count<max
时, 循环一次, 在每轮循环完成后, 使得count++
另外, 由于 计数器 在循环外没用, 因此可以在循环中定义ta
注意: for 会在循环一开始判断循环条件
这一点和 while 是类似的
以下是求阶乘的代码 (做了优化处理)
#include <stdio.h>
int main()
{
int n;
printf("输入要求阶乘的正整数: ");
scanf("%d", &n);
int i = n;
int ans = 1;
for (; n > 1; n--)
{
ans *= n;
}
printf("%d 的阶乘为: %d\n", i, ans);
return 0;
}
该程序以巧妙的方式, 考虑到了n
为0
或1
的情况
例子 求素数
#include <stdio.h>
int main()
{
int x;
printf("判断素数: ");
scanf("%d", &x);
int i;
int isPrime = 1;
for (i = 2; i < x / 2; i++)
{
if (x % i == 0)
{
isPrime = 0;
break;
}
}
if (isPrime == 1)
{
printf("是素数\n");
}
else
{
printf("不是素数\n");
}
return 0;
}
这里的
break
用于跳出循环
还有一个关键字continue
用于进入下一轮循环
循环嵌套
获取1\~100内所有素数
#include <stdio.h>
int main()
{
int x;
for (x = 2; x <= 100; x++)
{
int i;
int isPrime = 1;
for (i = 2; i <= x / 2; i++)
{
if (x % i == 0)
{
isPrime = 0;
break;
}
}
if (isPrime == 1)
{
printf("%3d", x);
}
}
return 0;
}
获取前50个素数
#include <stdio.h>
int main()
{
int x;
int count = 0;
for (x = 2; count < 50; x++)
{
int i;
int isPrime = 1;
for (i = 2; i < x / 2 + 1; i++)
{
if (x % i == 0)
{
isPrime = 0;
break;
}
}
if (isPrime == 1)
{
count++;
printf("%d\t", x);
if (count % 5 == 0)
{
printf("\n");
}
}
}
return 0;
}
值得注意的是, 本段程序的
for
并未使用计数器x
作为判断标志
应当把 for 看作是 while 的简写形式, 不应当带有stereotype
跳出嵌套
凑硬币
#include <stdio.h>
int main()
{
int x;
int one, two, five;
printf("要凑几块钱? ");
scanf("%d", &x);
for (one = 0; one <= x * 10; one++)
{
for (two = 0; two <= x * 10 / 2; two++)
{
for (five = 0; five <= x * 10 / 5; five++)
{
if (one + two * 2 + five * 5 == x * 10)
{
printf("可以用% 3d个一角 加% 3d个二角 加% 3d个五角 得到%d元\n", one, two, five, x);
}
}
}
}
return 0;
}
如果只要求得到一种情况就直接跳出三个循环呢?
方法一 接力break
#include <stdio.h>
int main()
{
int x;
int one, two, five;
int exit = 0;
printf("要凑几块钱? ");
scanf("%d", &x);
for (one = 0; one <= x * 10; one++)
{
for (two = 0; two <= x * 10 / 2; two++)
{
for (five = 0; five <= x * 10 / 5; five++)
{
if (one + two * 2 + five * 5 == x * 10)
{
printf("可以用% 3d个一角 加% 3d个二角 加% 3d个五角 得到%d元\n", one, two, five, x);
exit = 1;
break;
}
}
if (exit == 1)
break;
}
if (exit == 1)
break;
}
return 0;
}
方法二 goto
#include <stdio.h>
int main()
{
int x;
int one, two, five;
int exit = 0;
printf("要凑几块钱? ");
scanf("%d", &x);
for (one = 0; one <= x * 10; one++)
{
for (two = 0; two <= x * 10 / 2; two++)
{
for (five = 0; five <= x * 10 / 5; five++)
{
if (one + two * 2 + five * 5 == x * 10)
{
printf("可以用% 3d个一角 加% 3d个二角 加% 3d个五角 得到%d元\n", one, two, five, x);
goto out;
}
}
}
}
out:
return 0;
}
goto
受人诟病的原因在于, ta破坏了程序的结构性
但在上述的例子中, 其优点是非常显著的
因此, 仅仅在合适的场合使用goto
, 其他地方尽量不使用
例题 数学题
求$f(n)=\sum \limits _{i=1}^1 \frac{1}{n}$
#include <stdio.h>
int main()
{
int n;
int i;
double sum = 0.0;
printf("n: ");
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
sum += 1.0 / i;
}
printf("f(%d)=%f", n, sum);
return 0;
}
求$f(n)=\sum \limits _{i=1}^1 \frac{1}{n}\cdot(-1)^{n+1}$
#include <stdio.h>
int main()
{
int n;
int i;
double sign = 1.0;
double sum = 0.0;
printf("n: ");
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
sum += sign / i;
sign *= -1;
}
printf("f(%d)=%f", n, sum);
return 0;
}
例题 正序分解正整数
输入非负整数, 正序输出每一位数字
+ 输入: 13425
+ 输出: 1 3 4 2 5
注意: 最后的数字后面没有空格
#include <stdio.h>
int main()
{
int x;
int mask=1;
printf("请输入非负整数: ");
scanf("%d", &x);
/* 先获得数位 */
int t = x;
while (t > 9)
{
t /= 10;
mask *= 10;
}
/* 再逐个输出 */
do{
int d = x / mask;
printf("%d", d);
if(mask>9)
printf(" ");
x %= mask;
mask /= 10;
} while (mask > 0);
printf("|<-这是数字的末尾\n");
return 0;
}
本题综合了循环的多个技巧, 实属佳题
尤其要琢磨循环的条件是什么
例题 求最大公约数
输入两个数a
&b
, 输出其最大公约数
+ 输入: 12
18
+ 输出: 6
法一 朴素解法
#include <stdio.h>
int main()
{
int a, b;
printf("输入两个整数: \n");
scanf("%d %d", &a, &b);
int ans = 0;
int i;
for (i = 1; i <= a && i <= b; i++)
{
if (a % i == 0 && b % i == 0)
{
ans = i;
}
}
printf("最大公约数是: %d\n", ans);
return 0;
}
这里用到了逻辑运算, 在这个课程中还没教, 不过不算难
可以看C#课程中相关的知识点: Day06_Convert类型转换_加加减减_关系运算与逻辑判断
法二 辗转相除法
辗转相除法定义:
1. 如果b
等于0
, 计算结束, a
就是最大公约数
2. 否则, 计算a
除以b
的余数, 再让a
和b
互换
3. 返回第一步
#include <stdio.h>
int main()
{
int a, b;
int t;
printf("输入两个整数: \n");
scanf("%d %d", &a, &b);
while (b!=0)
{
t = a % b;
a = b;
b = t;
}
printf("最大公约数是: %d\n", a);
return 0;
}