「Java流程控制」循环综合应用

0 阅读6分钟

循环就像城市交通管理系统,不同类型的循环好比各种交通指挥方式:for循环像定时红绿灯,while循环像交警手动指挥,do-while则像必须至少放行一次的应急通道。

想象一个自助餐厅的运营场景:

  1. for循环:像固定菜品的取餐区,知道确切数量(比如10道热菜)
  2. while循环:像现做档口,只要还有客人排队就继续供应
  3. do-while循环:像必须至少询问一次的会员卡办理

这种综合应用场景,最能体现循环在实际开发中的价值。

案例解析

智能点餐系统

编写程序,结合多种循环实现餐厅管理系统。

# 源文件保存为“SmartRestaurant.java”
import java.util.Scanner;

public class SmartRestaurant {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] menu = {"红烧肉", "清蒸鱼", "宫保鸡丁", "麻婆豆腐"};
        int[] prices = {58, 88, 42, 36};
        int[] orders = new int[menu.length];
        int total = 0;
        
        // for循环展示固定菜单
        System.out.println("=== 今日菜单 ===");
        for(int i=0; i<menu.length; i++) {
            System.out.printf("%d. %s %d元\n", i+1, menu[i], prices[i]);
        }
        
        // while循环处理点餐
        boolean ordering = true;
        while(ordering) {
            System.out.print("\n请输入菜品编号(0结束):");
            int choice = scanner.nextInt();
            
            if(choice == 0) {
                ordering = false;
            } else if(choice > 0 && choice <= menu.length) {
                System.out.print("请输入份数:");
                int quantity = scanner.nextInt();
                orders[choice-1] += quantity;
                total += prices[choice-1] * quantity;
            } else {
                System.out.println("输入无效!");
            }
        }
        
        // do-while循环确认支付
        boolean paid = false;
        do {
            System.out.printf("\n总计:%d元,确认支付?(1确认/0取消)", total);
            int confirm = scanner.nextInt();
            if(confirm == 1) {
                paid = true;
                System.out.println("支付成功!");
            } else if(confirm == 0) {
                System.out.println("已取消订单");
                break;
            }
        } while(!paid);
        
        scanner.close();
    }
}

运行示例: 依次输入菜品变化、数量等信息。

=== 今日菜单 ===

  1. 红烧肉 58元
  2. 清蒸鱼 88元
  3. 宫保鸡丁 42元
  4. 麻婆豆腐 36元

请输入菜品编号(0结束):2 请输入份数:1

请输入菜品编号(0结束):4 请输入份数:2

请输入菜品编号(0结束):0

总计:160元,确认支付?(1确认/0取消)1 支付成功!

代码特点

  • for循环处理已知数量的菜单展示
  • while循环灵活处理不确定数量的点餐
  • do-while确保至少执行一次的支付确认
  • 数组存储菜单和订单信息

这个案例展示了如何根据场景特点选择合适的循环结构,就像交通管理员根据路况选择指挥方式。

素数筛法

编写一个程序,应用多种循环的优化素数筛法。

# 源文件保存为“PrimeSieve.java”
public class PrimeSieve {
    public static void main(String[] args) {
        int n = 100;
        boolean[] isPrime = new boolean[n+1];
        
        // 初始化所有数为素数
        for(int i=2; i<=n; i++) {
            isPrime[i] = true;
        }
        
        // 筛除非素数
        for(int i=2; i*i<=n; i++) {
            if(isPrime[i]) {
                for(int j=i*i; j<=n; j+=i) {
                    isPrime[j] = false;
                }
            }
        }
        
        // 输出结果
        System.out.println("100以内的素数:");
        int count = 0;
        for(int i=2; i<=n; i++) {
            if(isPrime[i]) {
                System.out.print(i + " ");
                if(++count % 10 == 0) {
                    System.out.println();
                }
            }
        }
    }
}

运行结果

100以内的素数: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

算法精要

  • 第一个for循环进行初始化
  • 第二个for循环结合while特性(i*i<=n)
  • 内层for循环标记非素数
  • 最后for循环输出结果并控制格式

这种综合应用展示了循环结构在算法中的强大威力,就像交通系统协同工作提升整体效率。

常见错误和解决方案

死循环陷阱

while(total > 0) {  // 条件永远不会变
    System.out.println("Processing...");
    // 缺少修改total的代码
}

解决方案:确保循环条件有被改变的可能

越界访问

for(int i=0; i<=menu.length; i++) {  // 应该用<
    System.out.println(menu[i]);
}

解决方案:注意数组索引从0开始,最大为length-1

混淆循环类型

int count = 5;
do {
    System.out.println(count);
    count--;
} while(count > 5);  // 至少执行一次可能不符合预期

解决方案:根据是否需要至少执行一次来选择循环类型

综合练习题

理论练习

  1. 下面代码输出什么?

    int i = 0;
    do {
        System.out.print(i + " ");
        i += 2;
    } while(i < 5);
    

    答案:输出"0 2 4 ",因为先执行后判断

  2. 如何用循环实现输入10个数字并找出最大值? 示例:

    Scanner sc = new Scanner(System.in);
    int max = Integer.MIN_VALUE;
    for(int i=0; i<10; i++) {
        System.out.print("输入数字:");
        int num = sc.nextInt();
        if(num > max) max = num;
    }
    System.out.println("最大值:" + max);
    
  3. 下面代码有什么问题?

    int x = 1;
    while(x < 10) 
        System.out.println(x);
        x++;  // 缺少大括号
    

    答案:缺少大括号导致x++不在循环体内,造成死循环

实战编程题

  1. 编写成绩分析程序:

    • 输入不确定数量的成绩(以-1结束)
    • 统计平均分、最高分、最低分
    • 使用合适的循环结构
    # 源文件保存为“GradeAnalyzer.java”
    import java.util.Scanner;
    
    public class GradeAnalyzer {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int count = 0, sum = 0;
            int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
            
            System.out.println("请输入成绩(-1结束):");
            while(true) {
                System.out.print("成绩" + (count+1) + ": ");
                int score = sc.nextInt();
                
                if(score == -1) break;
                
                sum += score;
                count++;
                if(score > max) max = score;
                if(score < min) min = score;
            }
            
            if(count > 0) {
                System.out.println("平均分:" + (double)sum/count);
                System.out.println("最高分:" + max);
                System.out.println("最低分:" + min);
            } else {
                System.out.println("未输入有效成绩");
            }
            
            sc.close();
        }
    }
    

    运行结果 依次输入成绩,最后一个输入*-1*。

    请输入成绩(-1结束): 成绩1: 96 成绩2: 86 成绩3: 98 成绩4: 36 成绩5: -1 平均分:79.0 最高分:98 最低分:36

  2. 模拟ATM机操作:

    • 初始余额1000元
    • 支持存款、取款、查询
    • 用do-while实现至少执行一次
    • 用while处理不确定次数的操作
    # 源文件保存为“ATMSystem.java”
    import java.util.Scanner;
    
    public class ATMSystem {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            double balance = 1000;
            int choice;
            
            do {
                System.out.println("\n1.查询 2.存款 3.取款 4.退出");
                System.out.print("请选择:");
                choice = sc.nextInt();
                
                switch(choice) {
                    case 1:
                        System.out.printf("当前余额:%.2f元\n", balance);
                        break;
                    case 2:
                        System.out.print("存款金额:");
                        balance += sc.nextDouble();
                        break;
                    case 3:
                        System.out.print("取款金额:");
                        double amount = sc.nextDouble();
                        if(amount > balance) {
                            System.out.println("余额不足!");
                        } else {
                            balance -= amount;
                        }
                        break;
                    case 4:
                        System.out.println("感谢使用!");
                        break;
                    default:
                        System.out.println("无效选择!");
                }
            } while(choice != 4);
            
            sc.close();
        }
    }
    

    运行结果 依次输入成绩,最后一个成绩输入**-1**。

    请输入成绩(-1结束): 成绩1: 98 成绩2: 89 成绩3: 76 成绩4: -1 平均分:87.66666666666667 最高分:98 最低分:76

  3. 打印特殊数字金字塔:

         1    121   12321 1234321

    要求:使用嵌套循环实现

    # 源文件保存为“NumberPyramid.java”
    public class NumberPyramid {
        public static void main(String[] args) {
            int rows = 4;
            for(int i=1; i<=rows; i++) {
                // 打印空格
                for(int j=1; j<=rows-i; j++) {
                    System.out.print(" ");
                }
                // 打印左半边
                for(int k=1; k<=i; k++) {
                    System.out.print(k);
                }
                // 打印右半边
                for(int l=i-1; l>=1; l--) {
                    System.out.print(l);
                }
                System.out.println();
            }
        }
    }
    

循环结构就像程序世界的交通规则,不同类型的循环适用于不同的场景。for循环适合已知次数的任务,while处理条件不确定的情况,do-while则保证至少执行一次。掌握它们的综合应用,就能像熟练的交通指挥员一样,让程序流程井然有序地运行。记住,选择循环类型时要像选择交通方式一样,根据具体需求做出最合适的选择。