C语言基础 4. While&DoWhile
文章目录
4.1. 循环
-
数数几位数:
-
程序要读入一个4位以下的(含4位)的正整数, 然后输出这个整数的位数.
- 比如:
输入: 352
输出: 3
- 比如:
-
-
思考:
-
人 VS 计算机
- 人的方式: 眼睛一看就知道了, 352 -> 3
- 计算机的方式: 判断数的范围来决定它的位数, 352(100, 999) -> 3 , 但是人不擅长, 因为人对数字的计算能力比文字弱
-
-
问题:
-
四位数的正整数可以, 那么任意范围的正整数怎么办?
-
换个方式想:
- 352 -> 3 很快
- 12423534524562324784765 是几位, 总不能数吧!?
-
-
数数:
- 1242353452456232478476543245687696543245
- 人: 从左向右数, 一个一个数
- 计算机: 如果换一下, 从右向左, 让这个数每次都整除10, 去掉最右边的数,不断地去,直到没数可去, 在这个过程中不断地计数.
-
if语句数数几位数的代码:
#include <stdio.h>
int main()
{
int num = 0;
int weishu = 0;
printf("请输入一个4位以下(包含4位)的正整数: ");
scanf("%d", &num);
if (num >= 1000) {
weishu = 4;
}
else if (num >= 100) {
weishu = 3;
}
else if (num >= 10) {
weishu = 2;
}
else {
weishu = 1;
}
printf("位数: %d位", weishu);
}
- 循环来数数几位数的代码:
#include <stdio.h>
int main()
{
int num = 0; // 输入num时别用124235345245623247847654去试, 因为C语言中的int是有范围的
int weishu = 0;
printf("请输入一个任意位数的正整数: ");
scanf("%d", &num); // num/10, weishu++;
while (num) { // while(判断条件), 非0为真, 0为假, 真则进入循环, 假则跳出
weishu++; // 计数
num /= 10;
}
printf("位数: %d位", weishu);
return 0;
}
4.2. While
-
while:
-
可以把while翻译成"当", 意思是当条件满足时, 不断重复循环体内的语句. 因为是先判断, 所以有可能循环一次也没有被执行.
-
跟if语句形式很像, 就是将if语句中的if换成while即可, 不同的是,if是一次性的, 而while是反复不断的.
if (num) { weishu++; num / 10; } while (num) { weishu++; num / 10; }
-
-
调整:
-
while循环中要有能够改变判断条件的机会, 要不然有可能变成死循环
- 比如:
while (num) { weishu++; // num / 10; // 将这段代码注释掉, 就变成了死循环 }
- 比如:
-
-
程序中的错误:
while (num) { weishu++; // num /= 10; } 错误信息: 超时 错误原因: while循环中少了调整判断条件的代码 解决办法: 添加上即可 得出结论: 程序编译通过也不一定算是正确了, 也有可能是代码有逻辑上的错误.
-
数位数的代码:
#include <stdio.h>
int main()
{
int num = 0;
int weishu = 0;
printf("请输入一个任意位数的正整数: ");
scanf("%d", &num);
while (num) {
weishu++;
num /= 10;
}
printf("位数: %d位", weishu);
return 0;
}
4.3. DoWhile
-
回顾:
- 刚才的程序有点缺陷, 就是它不能判断0的位数, 所以我们想使用一个先执行循环再判断的循环结构.
-
do while:
-
在进入循环时先执行, 再判断, 如果满足条件则继续下一轮循环, 不满足则结束循环.
-
形式:
- do {
语句;
} while (判断条件); // 注意: while()后面有个分号
- do {
-
-
while和do while:
它们很像, 区别在于它们的循环体执行和判断条件有先有后, while可能一次都不执行, do while是至少执行一次的. -
do while完成的代码:
#include <stdio.h>
int main()
{
int num = 0;
int weishu = 0;
printf("请输入一个任意位数的正整数: ");
scanf("%d", &num);
do {
weishu++;
num /= 10;
} while (num);
printf("位数: %d位", weishu);
return 0;
}
4.4. Test
-
4.4.1. 猜数游戏:
-
让计算机来想一个数, 然后让用户来猜, 用户每输入一个数, 就告诉它是大了还是小了, 直到用户猜中为止, 最后还要告诉用户它猜了多少次.
-
疑问: 如何让计算机来想一个数, 这是个问题, 是让它通过一个特定的东西来生成一个随机数?
- 已经懂了!
#include <time.h> #include <stdlib.h> srand(time(0)); int suijishu = rand() % 100; // 这段代码可以生成一个随机数, %100是为了将这个数 控制在1-99, 因为这个随机数太大了
-
- 代码:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main()
{
srand(time(0));
int suijishu = rand() % 100;
int num = 0;
int count = 0;
printf("欢迎进入猜数字游戏, 现在计算机会自动生成一个1-99之间的数, 然后你来猜, 请输入一个数: \n");
do {
scanf("%d", &num);
if (num > suijishu) {
printf("大了, 请重新输入: \n");
}
else if (num < suijishu) {
printf("小了, 请重新输入: \n");
}
count++;
} while (num != suijishu);
printf("恭喜你, 猜中了! 你一共猜了%d次.\n", count);
return;
}
-
4.4.2. 算平均数:
- 让用户输入一系列的正整数, 最后输入-1表示输入结束, 然后程序计算出这些数的平均数, 输出输入的数字个数和平均数.
-
程序中的错误:
-
scanf(“%d”, num);
错误信息:“scanf”: 格式字符串“%d”需要类型“int *”的参数,但可变参数 1 拥有了类型“int”
错误原因: scanf()中没有在变量前面加上&
解决办法: 加上即可
-
-
代码:
#include <stdio.h>
int main()
{
int num = 0;
int average = 0;
int count = 0;
int sum = 0;
printf("提示: 这个程序是帮你算出这些数的平均数的, 请输入多个正整数, 每输入一个数之后请按一下回车, 接着输入第二个数, 最后输入-1表示输入结束: \n");
while (num != -1) {
sum += num;
scanf("%d", num); // 1 2 3 8 9 -1
count++;
}
average = sum / (count - 1);
printf("你一共输入了%d个数, 它们的平均数是: %d", count - 1, average);
return 0;
}
-
4.4.3. 整数的分解:
-
一个整数是由1至多位数字组成的, 如何分解出整数的各个位上的数字, 然后加以计算?
- 对一个整数做%10的操作, 就得到了它的个位数;
- 对一个整数做/10的操作, 就去掉了它的个位数;
- 然后再对第二步的结果做%10, 就得到了原来数的十位数了;
- 以此类推.
-
-
整数求逆:
- 输入一个正整数, 输出逆序的数, 结尾的0逆序之后要求处理掉.
-
代码:
#include <stdio.h>
int main()
{
int num = 0;
int digit = 0;
int ret = 0;
printf("请输入一个正整数, 会将它逆序输出: \n");
scanf("%d", &num);
while (num > 0) {
digit = num % 10;
// printf("%d", digit); // 这段可以让700逆序成007
ret = ret * 10 + digit; // 核心:每次循环都让原来的结果(ret)往左移一位(*10),再加上新的digit
num /= 10;
}
printf("%d", ret);
return 0;
}
4.5. PAT
-
04-0. 求符合给定条件的整数集(15)
-
给定不超过6的正整数A,考虑从A开始的连续4个数字。请输出所有由它们组成的无重复数字的3位数。
-
输入格式:
输入在一行中给出A。 -
输出格式:
输出满足条件的的3位数,要求从小到大,每行6个整数。整数间以空格分隔,但行末不能有多余空格。 -
输入样例:
2 -
输出样例:
234 235 243 245 253 254
324 325 342 345 352 354
423 425 432 435 452 453
523 524 532 534 542 543
-
-
代码:
#include <stdio.h>
int main()
{
int a;
scanf("%d", &a);
int i, j, k;
//计数
int count = 0;
i = a;
while (i <= a + 3) {
j = a;
while (j <= a + 3) {
k = a;
while (k <= a + 3) {
//去掉有重复数字的数
if (i != j && i != k && j != k) {
printf("%d%d%d", i, j, k);
//完成指定的格式
count++;
if (count == 6) {
printf("\n");
count = 0;
}
else {
printf(" ");
}
}
k++;
}
j++;
}
i++;
}
return 0;
}
-
04-1. 水仙花数(20)
-
水仙花数是指一个N位正整数(N>=3),它的每个位上的数字的N次幂之和等于它本身。例如:153 = 1^3 + 5^3+ 3^3。本题要求编写程序,计算所有N位水仙花数.
-
输入格式:
输入在一行中给出一个正整数N(3<=N<=7)。 -
输出格式:
按递增顺序输出所有N位水仙花数,每个数字占一行。 -
输入样例:
3 -
输出样例:
153
370
371
407
-
-
代码:
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
//假设n为3, 产生100-999之间的数
int i = 1;
int first = 1;
while (i < n) {
first *= 10;
i++;
}
//printf("%d", first);
//遍历100-999
i = first; // 疑问: 为什么这里及以下的i不能用first直接替代
while (i < first * 10) {
//将这个数的每一位都取出来
int tmp = i;
int sum = 0;
int j = 0;
while (j < n) {
int digit = tmp % 10;
tmp /= 10;
j++;
//求每一位的n次幂
int k = 0;
int p = 1;
while (k < n) {
p *= digit;
k++;
}
//将求出的n次幂求和
sum += p;
}
//判断次幂的和与该数是否相等
if (sum == i) {
printf("%d\n", i);
}
i++;
}
return 0;
}
-
04-2. 打印九九口诀表(15)
-
下面是一个完整的下三角九九口诀表:
1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
-
本题要求对任意给定的1位正整数N,输出从11到NN的部分口诀表。
-
输入格式:
输入在一行中给出一个正整数N(1<=N<=9)。 -
输出格式:
输出下三角N*N部分口诀表,其中等号右边数字占4位、左对齐。 -
输入样例:
4 -
输出样例:
1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16
-
-
代码:
#include <stdio.h>
int main()
{
int i = 1;
int n;
scanf("%d", &n);
while (i <= n) {
int j = 1;
while (j <= i) {
if (j * i <= 9) {
printf("%d*%d=%d ", j, i, j * i);
}
else if (j * i >= 10) {
printf("%d*%d=%d ", j, i, j * i);
}
j++;
}
printf("\n");
i++;
}
return 0;
}
-
04-3. 统计素数并求和(20)
-
本题要求统计给定整数M和N区间内素数( 素数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数 ) 的个数并对它们求和。
-
输入格式:
输入在一行中给出2个正整数M和N(1<=M<=N<=500)。 -
输出格式:
在一行中顺序输出M和N区间内素数的个数以及它们的和,数字间以空格分隔。 -
输入样例:
10 31 -
输出样例:
7 143
-
-
代码:
#include <stdio.h>
int main()
{
int m, n;
scanf("%d %d", &m, &n);
//计数, 求和
int count = 0;
int sum = 0;
//产生m到n之间的数
int num = m;
while (num <= n) {
//产生除数
int chushu = 2;
while (chushu < num) {
//试除
if (num % chushu == 0) {
break;
}
chushu++;
}
//全部试除之后, 符合条件的就是素数
if (num == chushu) {
count++;
sum += num;
}
num++;
}
printf("%d %d", count, sum);
return 0;
}
-
04-4. 猜数字游戏(15)
-
猜数字游戏是令系统随机产生一个100以内的正整数,用户输入一个数对其进行猜测,需要你编写程序自动对其与随机产生的被猜数进行比较,并提示大了(“Too big”),还是小了(“Too small”),相等表示猜到了。如果猜到,则结束程序。程序还要求统计猜的次数,如果1次猜出该数,提示"Bingo!“;如果3次以内猜到该数,则提示"Lucky You!”;如果超过3次但是在N(>3)次以内(包括第N次)猜到该数,则提示"Good Guess!“;如果超过N次都没有猜到,则提示"Game Over”,并结束程序。如果在到达N次之前,用户输入了一个负数,也输出"Game Over",并结束程序。
-
输入格式:
输入第一行中给出2个不超过100的正整数,分别是系统产生的随机数、以及猜测的最大次数N。随后每行给出一个用户的输入,直到出现负数为止。 -
输出格式:
在一行中输出每次猜测相应的结果,直到输出猜对的结果或"Game Over"则结束。 -
输入样例:
58 4
70
50
56
58
60
-2 -
输出样例:
Too big
Too small
Too small
Good Guess!
-
-
代码:
#include <stdio.h>
int main()
{
int num1, n, num2 = 0;
scanf("%d %d", &num1, &n);
//计数
int count = 0;
while (num2 >= 0) {
//让用户输入猜的数
scanf("%d", &num2);
//计数
count++;
//判断是否正确
if (num1 < num2) {
printf("Too big\n");
}
else if (num1 > num2) {
printf("Too small\n");
}
else {
if (count == 1) {
printf("Bingo!\n");
break;
}
else if (count <= 3) {
printf("Lucky You!\n");
break;
}
else {
printf("Good Guess!\n");
break;
}
}
if (count == n) {
printf("Game Over!\n");
break;
}
}
if (num2 < 0) {
printf("Game Over!");
}
return 0;
}