目录
问题2:程序读入一个整数,然后输出这个整数是几位数(三位数逆序题)
顺序结构的程序语句只能被执行一次。如果想要同样的操作执行多次,就需要使用循环结构。Java中有三种主要的循环结构:
- while 循环
- do…while 循环
- for 循环
下面列举了循环的几个例子,重点看【例2】【例4】,涉及到培养一些编程的基础素养。
下面列举了循环的几个例子,重点看【例2】【例4】,涉及到培养一些编程的基础素养。
下面列举了循环的几个例子,重点看【例2】【例4】,涉及到培养一些编程的基础素养。
问题1:自动售票机如何能不断投币和出票?
史博:【Java编程】程序结构--分支https://zhuanlan.zhihu.com/p/623603391
当投入的金额不够时,乘客继续投票,直到够10元(余额 + 投入金额 >10)售票机出票、找零。
Scanner in = new Scanner(System.in);
int balance = 0;
while(true)
{
System.out.print("请投币:");
int amount = in.nextInt();
balance = amount + balance; // 余额 = 金额 + 余额
if (balance >= 10)
{
System.out.println("打印车票");
System.out.println("找零:" + (balance-10));
balance = 0; //balance 需要清零
}
}
上面的代码,注意出票完成后balance需要清零 balance = 0。
while语句是一个循环语句,它会首先判断一个条件是否满足,如果条件满足,则执行后面紧跟着的语句括号,然
后再次判断条件是否满足,如果条件满足则再次执行,直到条件不满足为止。
while 语法结构
循环变量初始化;
while(循环条件)
{
循环主体程序;
循环变量更新规则; // 循环体内,要有改变条件的机会;
} // for 每次变化完,循环变量每次自动更新,更新规则写在for语句里
int i = 1;
while(i<=10)
{
printf("%d\n",i); // %d是替换整型输出的占位符,\n是回车字符
i=i+1
}
问题2:程序读入一个整数,然后输出这个整数是几位数(三位数逆序题)
例如: 输入3546, 输出4
输入-2147483647(2的31次方减1),输出10
思路
正常人数,从右往左,个、十、百、千,“1” 后面0个0、1个0、2个0、3个0(位数对应1、2、3、4)。
对于一个数字,先找到它可以被“1后面几个0”除,而这“几个”说的就是"10的几次方",也就是"被10除几次"
的概念。如果可以被n个10除,就用计数器count记n次,这个n的基础上加1,就是位数。
/* 一个数可以被10除1次用if,要不断往下循环,才能看出最后被除了几次,if改成while;
循环条件是true,循环体会被一直执行,停不下来,所以需要增加一个循环条件 while(num>0);*/
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int count = 0;
while (num >0)
{
num = num / 10;
count = count + 1; //计数器
}
调试
程序写好后,需要进行调试(Command +5),在程序适当的地方插入输出来显示变量内容。
验证
常使用边界数据,如有效范围两端的数据、特殊的倍数等:个位数、10、0、负数。
可以查漏:读入的是负数或者0时,也需要被考虑。所以用if...else if...else处理多分支的情况。用数学Math.abs()
绝对值函数可以将正、负数的情况合并,那么上面的程序结构可以简化为两个分支,用if...else即可。
完整代码
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int count = 0;
if(num != 0)
{
while (num > 0 || num < 0) // num > 0 || num < 0 与 !=0(非零)等价
{
num = Math.abs(num) / 10; //正、负数一并考虑Math.abs()
count = count + 1;
}
System.out.println("这是" + count + "位数"); // 等于零的情况
}
else
{
System.out.println("0是1位数"); // 等于零的情况
}
另外,关于算整型数字的位数问题,可以将数字转化为文本,然后.length()的方法。
Scanner in =new Scanner(System.in);
int num = in.nextInt();
System.out.println((num+"").length());
此外,如果输入超出int(2的31次方减1)范围的数字,就会报错。改成long也是。留言区欢迎指点怎么修改~
最后,while是循环执行之前判断是否继续循环,所以有可能循环一次也没有被执行。这时就要看do...while了。
do-while循环和while循环很像,唯一的区别是我们在循环体执行结束的时候才来判断条件。也就是说,无论如
何,循环都会执行至少一遍,然后再来判断条件。
循环变量初始化;
do{
循环主体程序;
循环变量更新规则;
} while(循环条件);
do...while...与while...
如果上面的问题,用do...while代码如下:
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int count = 0;
do
{
num = Math.abs(num) / 10;
count = count + 1;
} while (num != 0); //while后面用;
System.out.println("这是"+count+"位数");
这样输入0也会被执行,只不过到while的时候循环判断不满足条件,就结束。
问题3:计数循环(100开始倒数至0,打印“发射”)
int count = 100;
do
{
System.out.println(count);
count = count - 1;
}while(count >= 0);
System.out.println("发射!");
计数循环三问:
循环执行多少次?101次
循环停下来的时候,有没有打印出最后的0?输出
循环结束后,count的实际值是多少?-1
tips:如果要模拟运行一个很大次数的循环,可以模拟较少的循环次数,然后做出推断。
问题4:算平均数
用户输入一系列正整数,最后输“-1“使输入结束。程序计算这些正整数的平均数,输出输入数字的个数和平均数。
拿到任何问题前需要思考的两件事: 变量-->算法-->流程图-->程序
1. 用什么样的数(变量):程序输入了哪些数?计算的过程中,需要哪些数?都需要记录表达;
2. 计算用什么样的步骤(算法):可以用流程图辅助;
Scanner in = new Scanner(System.in);
int num = in.nextInt(); // 程序先输入一个数
int count = 0;
int sum = 0;
while(num != -1) //“-1“ 相当于开关,当不是-1就进循环,输入-1就停止
{
sum += num; // 要用 num += num 就会把第一个输入的数加2次
count = count + 1;
num =in.nextInt(); // 程序再录入第2个数(如果只在循环外面那层写,就只会录进第1个数,然后一直循环
}
System.out.println("平均数="+(double) sum/count);
小问题
假如程序一开始输入的第一个数就是“-1”的话,不进循环,count = 0(分母),程序结果为“平均数=NaN”。
需要增加一个输出的条件 if(count > 0)。
另外,输出的时候 (double)(sum/count) 与 (double) sum/count 的结果是不一样的!不能加()。
完整代码:
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int count = 0;
double sum = 0;
while(num != -1)
{
sum += num;
count = count + 1;
num =in.nextInt();
}
if(count > 0) //大于0的时候才输出平均数
{
System.out.println("平均数=" + (sum / count));
}
用do...while...也可以来实现,并且避免while里面出现两次 in.nextInt()的情况。但要注意,输入第1次为-1的时候,
sum和count不计算。
Scanner in = new Scanner(System.in);
int num;
int count = 0;
double sum = 0;
do
{
num = in.nextInt();
if(num != -1) // 套一个if
{
sum += num;
count = count + 1;
}
} while(num != -1);
if(count > 0) //大于0的时候才输出平均数
{
System.out.println("平均数=" + (sum / count));
}
问题5:猜数游戏
让计算机先想一个数,然后用户来猜,用户每输入一个数,就告诉它是大了还是小了,直到猜中为止,最后告诉用
户他猜了多少次。
思路
输入:计算机随机生成一个数,范围自定。这里设置为[1,20];myInt001
读取用户输入的数;my Int002
还有一个计数的变量;count
计算:首先考虑到用分段条件if...else if...else,将“猜中”、“猜小了”、“猜大了”三种情况分开。因为没有猜中需要
一直循环,所以要用while或者do...while...。又考虑到如果用户第一次就猜中的情况,用尝试do...while...循环条件
限制为while(myInt001 != myInt002)。
输出:将每次的判断结果输出,告诉用户猜大了还是小了。用户猜中后,告诉其一共猜了多少次。
Random random = new Random();
int myInt001 = random.nextInt(20-1+1)+1; //随机的数 myInt001 范围[1-20]上限-下限+1+下限
Scanner scanner = new Scanner(System.in);
int myInt002; //猜的数 myInt002
int count=0;
do
{
myInt002 = scanner.nextInt();
count ++; //输入多少次,就是猜了多少次
if(myInt001 > myInt002)
{
System.out.println("猜小了,请继续猜:");
}
else if(myInt001 < myInt002)
{
System.out.println("猜大了,请继续猜:");
}
else
{
System.out.println("猜对了!你共猜了"+count+"次");
}
}while (myInt001 != myInt002);
如果用while循环,遇到猜中的情况,甭管是第一次还是若干次后,直接在循环体外输出。分段可以减省为 if...else
if...(最后一个else不用写了)。此外,count的计数次数不受影响。因为初始 myDouble002=5e-6 是一个很小的
浮点数,肯定会满足 myInt001 != myDouble002,从而进入循环体,直到myDouble被用户输入的数字替换掉。用
户输入多少次,就是猜了多少次。如果想法有问题,欢迎留言~
Random random = new Random();
int myInt001 = random.nextInt(20-1+1)+1;
Scanner scanner = new Scanner(System.in);
double myDouble002=5e-6; // 5*10的负6次方 初始是一个非常小的浮点数,不影响随机生成的整数
int count=0;
while (myInt001 != myDouble002)
{
myInt002 = scanner.nextInt();
count ++;
if(myInt001 > myDouble002)
{
System.out.println("猜小了,请继续猜:");
}
else if(myInt001 < myDouble002)
{
System.out.println("猜大了,请继续猜:");
}
}
System.out.println("猜对了!你共猜了"+count+"次");
tips:随机数生成还可以用Math的方法int myInt001 = (int)(Math.random()*100+1(因为Math.random生成的数的范围为[0,1)-->[0,100)-->[1,100]。
问题6:整数分解
一个整数由多位数字组成,如何分解出整数的各个位上的数字(默认从右往左数位数)
例如:
846输出结果如下:
从右往左,第1位上的数字是:6
从右往左,第2位上的数字是:4
从右往左,第3位上的数字是:8
思路
参考【问题2】
首先,如果一个整数%10,取余结果就是第1位(个位)上的数。
同时,拿这个整数/10,得到的商,再%10取余。结果就是第 count+1 位上的数(count 记录为“除以10的次数”)。
最后,while循环的条件如果包括num=0的话,有2种情况,一是num一开始就等于0 ,另外一种是num循环几次后变成0。第二种情况的时候,0会一直循环下去。所以循环条件用num!=0,作为开关。但这样第一种情况num本身就为0的情况,却进不去循环,所以调整用do...while...
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int count = 0;
do
{
count = count +1;
System.out.println("从右往左,第" + count + "位上的数字是:" + Math.abs(num % 10));
num /= 10;
}while (Math.abs(num) > 0);
}
用Math.abs()就是假如为负数也可以显示,所以输入整数的符号是不是在一开始就要判断一下。
上面的情况,如果需要将整数按照逆序方式输出。
例如:8543
输出:3 4 5 8
循环的条件是 num > 0,每次循环体内将 num 的个位数字取出并输出,再将 num 的值更新为 num/10,即去掉个位数字。
Scanner in = new Scanner(System.in);
System.out.print("请输入一个整数:");
int num = in.nextInt();
while (Math.abs(num) > 0) {
System.out.println(Math.abs(num) % 10 + " ");
num /= 10;
}
System.out.println() //用in.close也可以
// 输出结果
3
4
5
8
到此,while...和do...while的小例子举完了,下一节会写另外一个循环结构for循环~
如果以上有问题,欢迎留言~