扫描仪读取用户输入

egmofgnx  于 2021-07-03  发布在  Java
关注(0)|答案(4)|浏览(391)

我对使用java还不熟悉,但我以前对c有一些经验。我遇到的问题是从控制台读取用户输入。
我遇到了“java.util.nosuchelementexception”错误,这部分代码是:

payment = sc.next(); // PromptCustomerPayment function

我有两个获取用户输入的函数:
提示客户数量
提示客户付款
如果我不打电话给promptcustomerqty,那么我就不会得到这个错误,这会让我相信我的扫描仪出了问题。下面是我的完整代码示例。谢谢你的帮助。

public static void main (String[] args) {   

    // Create a customer
    // Future proofing the possabiltiies of multiple customers
    Customer customer = new Customer("Will");

    // Create object for each Product
    // (Name,Code,Description,Price)
    // Initalize Qty at 0
    Product Computer = new Product("Computer","PC1003","Basic Computer",399.99); 
    Product Monitor = new Product("Monitor","MN1003","LCD Monitor",99.99);
    Product Printer = new Product("Printer","PR1003x","Inkjet Printer",54.23);

    // Define internal variables 
    // ## DONT CHANGE 
    ArrayList<Product> ProductList = new ArrayList<Product>(); // List to store Products
    String formatString = "%-15s %-10s %-20s %-10s %-10s %n"; // Default format for output

    // Add objects to list
    ProductList.add(Computer);
    ProductList.add(Monitor);
    ProductList.add(Printer);

    // Ask users for quantities 
    PromptCustomerQty(customer, ProductList);

    // Ask user for payment method
    PromptCustomerPayment(customer);

    // Create the header
    PrintHeader(customer, formatString);

    // Create Body
    PrintBody(ProductList, formatString);   
}

public static void PromptCustomerQty(Customer customer, ArrayList<Product> ProductList) {
    // Initiate a Scanner
    Scanner scan = new Scanner(System.in);

    //****VARIABLES****
    int qty = 0;

    // Greet Customer
    System.out.println("Hello " + customer.getName());

    // Loop through each item and ask for qty desired
    for (Product p : ProductList) {

        do {
        // Ask user for qty
        System.out.println("How many would you like for product: " + p.name);
        System.out.print("> ");

        // Get input and set qty for the object
        qty = scan.nextInt();

        }
        while (qty < 0); // Validation

        p.setQty(qty); // Set qty for object
        qty = 0; // Reset count
    }

    // Cleanup
    scan.close();
}

public static void PromptCustomerPayment (Customer customer) {
    // Initiate Scanner 
    Scanner sc = new Scanner(System.in);

    // Variables
    String payment = "";

    // Prompt User
    do {
    System.out.println("Would you like to pay in full? [Yes/No]");
    System.out.print("> ");

    payment = sc.next();

    } while ((!payment.toLowerCase().equals("yes")) && (!payment.toLowerCase().equals("no")));

    // Check/set result
    if (payment.toLowerCase() == "yes") {
        customer.setPaidInFull(true);
    }
    else {
        customer.setPaidInFull(false);
    }

    // Cleanup
    sc.close(); 
}
pgky5nke

pgky5nke1#

异常的原因已经解释过了,但是建议的解决方案并不是最好的。
您应该创建一个类,该类使用单例模式将扫描器保持为私有的,从而使该扫描器在您的代码中是唯一的。
然后你可以实现你需要的方法或者你可以创建一个getscanner(不推荐),你可以用一个私有的boolean来控制它,比如alreadycolsed。
如果您不知道如何使用单例模式,下面是一个示例:

public class Reader {

    private Scanner reader;
    private static Reader singleton = null;
    private boolean alreadyClosed;

    private Reader() {
        alreadyClosed = false;
        reader = new Scanner(System.in);
    }

    public static Reader getInstance() {
        if(singleton == null) {
            singleton = new Reader();
        }
        return singleton;
    }

    public int nextInt() throws AlreadyClosedException {
        if(!alreadyClosed) {
            return reader.nextInt();
        }
        throw new AlreadyClosedException(); //Custom exception
    }

    public double nextDouble() throws AlreadyClosedException {
        if(!alreadyClosed) {
            return reader.nextDouble();
        }
        throw new AlreadyClosedException();
    }

    public String nextLine() throws AlreadyClosedException {
        if(!alreadyClosed) {
            return reader.nextLine();
        }
        throw new AlreadyClosedException();
    }

    public void close() {
        alreadyClosed = true;
        reader.close();
    }   
}
r1zk6ea1

r1zk6ea12#

您需要移除扫描仪的闭合线: scan.close(); 这件事以前发生在我身上,这就是原因。

lqfhib0f

lqfhib0f3#

这真的让我困惑了一段时间,但这就是我最终发现的。
当你打电话的时候, sc.close() 在第一种方法中,它不仅关闭您的扫描仪,而且关闭您的计算机 System.in 输入流也是。您可以通过在第二个方法的顶部打印其状态来验证它,如下所示:

System.out.println(System.in.available());

所以,现在当你重新示例化时, Scanner 在第二种方法中,它找不到任何打开的 System.in 流,因此例外。
我怀疑是否有办法重新开放 System.in 因为: public void close() throws IOException --> Closes this input stream and releases any system resources associated with this stream. The general contract of close is that it closes the input stream. A closed stream cannot perform input operations and**cannot be reopened.** 解决你问题的唯一好办法就是启动 Scanner 在main方法中,将其作为参数传递给两个方法,然后在main方法中再次关闭它,例如: main 方法相关代码块:

Scanner scanner = new Scanner(System.in);  

// Ask users for quantities 
PromptCustomerQty(customer, ProductList, scanner );

// Ask user for payment method
PromptCustomerPayment(customer, scanner );

//close the scanner 
scanner.close();

您的方法:

public static void PromptCustomerQty(Customer customer, 
                             ArrayList<Product> ProductList, Scanner scanner) {

    // no more scanner instantiation
    ...
    // no more scanner close
 }

 public static void PromptCustomerPayment (Customer customer, Scanner sc) {

    // no more scanner instantiation
    ...
    // no more scanner close
 }

希望这能给你一些关于失败的见解和可能的解决办法。

ui7jx7zq

ui7jx7zq4#

问题是
当扫描仪关闭时,如果输入源实现可关闭接口,它将关闭输入源。
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/scanner.html
因此 scan.close() 关闭 System.in .
你可以把它修好
Scanner scan static 不要在promptcustomerqty中关闭它。下面的代码起作用。

public static void main (String[] args) {   

// Create a customer
// Future proofing the possabiltiies of multiple customers
Customer customer = new Customer("Will");

// Create object for each Product
// (Name,Code,Description,Price)
// Initalize Qty at 0
Product Computer = new Product("Computer","PC1003","Basic Computer",399.99); 
Product Monitor = new Product("Monitor","MN1003","LCD Monitor",99.99);
Product Printer = new Product("Printer","PR1003x","Inkjet Printer",54.23);

// Define internal variables 
// ## DONT CHANGE 
ArrayList<Product> ProductList = new ArrayList<Product>(); // List to store Products
String formatString = "%-15s %-10s %-20s %-10s %-10s %n"; // Default format for output

// Add objects to list
ProductList.add(Computer);
ProductList.add(Monitor);
ProductList.add(Printer);

// Ask users for quantities 
PromptCustomerQty(customer, ProductList);

// Ask user for payment method
PromptCustomerPayment(customer);

// Create the header
PrintHeader(customer, formatString);

// Create Body
PrintBody(ProductList, formatString);   
}

static Scanner scan;

public static void PromptCustomerQty(Customer customer, ArrayList<Product> ProductList)               {
// Initiate a Scanner
scan = new Scanner(System.in);

//****VARIABLES****
int qty = 0;

// Greet Customer
System.out.println("Hello " + customer.getName());

// Loop through each item and ask for qty desired
for (Product p : ProductList) {

    do {
    // Ask user for qty
    System.out.println("How many would you like for product: " + p.name);
    System.out.print("> ");

    // Get input and set qty for the object
    qty = scan.nextInt();

    }
    while (qty < 0); // Validation

    p.setQty(qty); // Set qty for object
    qty = 0; // Reset count
}

// Cleanup

}

public static void PromptCustomerPayment (Customer customer) {
// Variables
String payment = "";

// Prompt User
do {
System.out.println("Would you like to pay in full? [Yes/No]");
System.out.print("> ");

payment = scan.next();

} while ((!payment.toLowerCase().equals("yes")) && (!payment.toLowerCase().equals("no")));

// Check/set result
if (payment.toLowerCase() == "yes") {
    customer.setPaidInFull(true);
}
else {
    customer.setPaidInFull(false);
}
}

顺便说一句,你不应该用 == 对于字符串比较,使用 .equals 相反。

相关问题