
本教程旨在解决在java中创建动态编号列表并处理用户选择时常见的逻辑错误,特别是关于列表编号的重复累加和选择判断的准确性问题。通过分析一个密码管理器场景中的具体案例,我们将详细讲解如何正确初始化计数器、生成有序列表、以及如何基于用户输入准确地访问对应的数据,从而避免索引越界和逻辑判断失误。
在开发交互式应用程序时,我们经常需要向用户展示一个编号列表,并允许用户通过输入数字来选择列表中的某个项。一个典型的应用场景是密码管理器,它需要列出所有存储的网站,并根据用户的选择显示对应的用户名和密码。
我们的目标是实现以下功能:
原始代码在实现上述目标时,遇到了两个主要问题:
让我们逐一分析:
立即学习“Java免费学习笔记(深入)”;
在原始代码中,websiteNum变量在while (yesNo == 'n')循环外部被初始化(或在某个地方被初始化一次),然后在for循环内部每次迭代时递增。
// ...
// FIXME website num is exponentially increasing everytime no is entered.
for (i = 0; i < (websites.getwebList().size()); i++) {
System.out.print(websiteNum + " - ");
System.out.println(websites.getwebList().get(i));
websiteNum = websiteNum + 1; // 每次显示后递增
}
// ...当外层while循环再次执行时(例如,用户选择不添加密码并再次显示列表),websiteNum的值并没有被重置回1。它会从上次循环结束时的值继续递增,从而产生“2 - website1.com 4 - website2.com”这类错误的编号。
解决方案:每次需要显示列表时,都应该将用于编号的计数器重新初始化为1。
原始代码中,在用户输入选择后,尝试通过以下逻辑来访问数据:
// ...
while (alwaysTrue == true) // 此循环是多余的,且条件恒为真
{
// FIXME always results in cannot access
if (userNum == websiteNum) // 这里的 websiteNum 是列表显示后的最终值
{
System.out.println(websites.getwebList().get(j));
System.out.println(usernames.getuserNameList().get(j));
System.out.println(passwords.getPassList().get(j));
break;
}
else
{
System.out.println("Cannot access, try again.");
break;
}
}
// ...这里的websiteNum在if条件被检查时,其值是上一个for循环结束后,列表的最后一个编号加1。例如,如果列表有2项,websiteNum最终会是3。因此,除非用户恰好输入3(这通常不是一个有效选择),userNum == websiteNum这个条件几乎总是false,导致程序总是输出“Cannot access, try again.”。
此外,while (alwaysTrue == true)是一个冗余且可能导致无限循环的结构(尽管内部的break语句阻止了无限循环)。正确的做法是直接使用if-else结构进行判断。
解决方案:用户输入的userNum代表的是列表中的序号(从1开始)。要将其转换为列表或数组的索引(从0开始),需要进行userNum - 1的转换。然后,应该检查这个转换后的索引是否在有效范围内,而不是将其与websiteNum的最终值进行比较。
结合上述分析,我们提出以下修正策略:
下面是基于上述策略修正后的代码示例:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 模拟数据源类
class WebsiteData {
private List<String> webList;
private List<String> userNameList;
private List<String> passList;
public WebsiteData() {
webList = new ArrayList<>();
userNameList = new ArrayList<>();
passList = new ArrayList<>();
webList.add("website1.com");
userNameList.add("user1");
passList.add("pass123");
webList.add("website2.org");
userNameList.add("user2");
passList.add("securePass");
webList.add("example.net");
userNameList.add("admin");
passList.add("mySecret");
}
public List<String> getwebList() {
return webList;
}
public List<String> getuserNameList() {
return userNameList;
}
public List<String> getPassList() {
return passList;
}
}
public class PasswordManagerTutorial {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
WebsiteData websites = new WebsiteData(); // 模拟网站数据
// 假设这里是外层循环的开始,例如用户选择“不添加密码”
char yesNo = 'n'; // 模拟用户输入 'n'
while (yesNo == 'n') {
System.out.println("\n--- 现有网站列表 ---");
int websiteNumCounter = 1; // 每次显示列表前重置计数器
for (int i = 0; i < websites.getwebList().size(); i++) {
System.out.println(websiteNumCounter + " - " + websites.getwebList().get(i));
websiteNumCounter++;
}
System.out.println("请输入您想访问的网站编号 (输入0退出):");
int userNum = scnr.nextInt();
if (userNum == 0) {
System.out.println("退出选择模式。");
break; // 退出外层 while 循环
}
// 将用户输入的编号转换为零基索引
int selectedIndex = userNum - 1;
// 验证用户输入的索引是否有效
if (selectedIndex >= 0 && selectedIndex < websites.getwebList().size()) {
System.out.println("\n--- 网站信息 ---");
System.out.println("网站: " + websites.getwebList().get(selectedIndex));
System.out.println("用户名: " + websites.getuserNameList().get(selectedIndex));
System.out.println("密码: " + websites.getPassList().get(selectedIndex));
// 假设显示完信息后,用户可以再次选择或退出
System.out.println("\n是否继续选择网站?(y/n)");
yesNo = scnr.next().charAt(0);
if (yesNo == 'y') {
yesNo = 'n'; // 保持在选择循环中
} else {
break; // 退出外层循环
}
} else {
System.out.println("无效的编号,请重试。");
// 保持 yesNo 为 'n',以便重新显示列表并允许用户再次选择
}
}
scnr.close();
System.out.println("程序结束。");
}
}代码运行示例:
--- 现有网站列表 --- 1 - website1.com 2 - website2.org 3 - example.net 请输入您想访问的网站编号 (输入0退出): 2 --- 网站信息 --- 网站: website2.org 用户名: user2 密码: securePass 是否继续选择网站?(y/n) y --- 现有网站列表 --- 1 - website1.com 2 - website2.org 3 - example.net 请输入您想访问的网站编号 (输入0退出): 5 无效的编号,请重试。 --- 现有网站列表 --- 1 - website1.com 2 - website2.org 3 - example.net 请输入您想访问的网站编号 (输入0退出): 1 --- 网站信息 --- 网站: website1.com 用户名: user1 密码: pass123 是否继续选择网站?(y/n) n 程序结束。
本教程通过一个具体的密码管理器案例,详细讲解了在Java中实现动态编号列表和用户选择时可能遇到的常见问题及其解决方案。核心在于正确地管理列表编号计数器的生命周期(每次显示前重置),以及将用户输入转换为有效的零基索引并进行严格的边界检查。掌握这些基本原则,将有助于您编写出更加健壮、用户友好的交互式应用程序。
以上就是Java中实现动态编号列表与用户选择的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号