不同类型输入的Java Scanner

4

想象一下以下情景: 我有一个程序,它要求输入一个整数,然后是一个字符串输入。

int age=0;
String name;
Scanner sc = new Scanner(System.in);

System.out.print("Enter Age: ");
age = sc.nextInt();
System.out.print("Enter Name: ");
name= sc.nextLine();

使用上述代码,我没有机会输入名称。因此,通常我将声明两个扫描器对象,如下:

int age=0;
String name;
Scanner sc = new Scanner(System.in);
Scanner sc2 = new Scanner(System.in);    //2nd Scanner object

System.out.print("Enter Age: ");
age = sc.nextInt();
System.out.print("Enter Name: ");
name= sc2.nextLine();                    //Using 2nd Scanner Object

我的问题是:需要声明多个scanner对象来接受不同类型的输入吗?像上面那样做是否正确?

我已经思考这个问题多年了。(在Stack Overflow上有几个问题提到了多个scanner,但他们的问题只用了一个scanner对象,所以今天我问了这个问题。)


阅读您下面的评论,您是否尝试先读取名称,然后再读取年龄? - Frakcool
@Frakcool 如果我们在读取整数之前先读取字符串,那么它就可以工作。 - user3437460
7个回答

6
@skiwi说得对,只需要使用一个Scanner,你已经做得很好了。它不起作用的原因是nextInt()会消耗所有组成整数的字符,但它没有触及到行尾符。因此,当调用nextLine()时,它发现行尾符之前没有任何字符,因此认为输入了一行空白,因此返回一个空字符串。然而,nextLine()确实会消耗掉行尾符,所以在执行name = sc.nextLine();之前先调用sc.nextLine();,就可以解决这个问题了。

3
由于nextInt()不读取用户输入后的换行符'\n',所以您没有机会输入名称,而nextLine()却能够读取。因此,一旦调用name = sc.nextLine();,它会立即读取nextInt()尚未读取的'\n'字符。
如果你要扫描相同的输入源(如System.in),绝对不要创建一个新的Scanner实例——只有在扫描其他文件或其他东西时才更改Scanner。
为了让您的代码工作(仅使用一个Scanner实例),请使用以下代码:
int age = 0;
String name;
Scanner sc = new Scanner(System.in);

System.out.print("Enter Age: ");
age = sc.nextInt();
System.out.print("Enter Name: ");

sc.nextLine(); // "dispose" of the '\n' character
               // so that it is not recorded by the next line

name = sc.nextLine();

// print your findings
System.out.println("------\nAge: " + age + "\nName: " + name);

示例输入/输出:

Enter Age: 17
Enter Name: Michael
------
Age: 17
Name: Michael

2
您应该每个要扫描的对象只使用一个Scanner实例。在这种情况下,您正在从System.in读取,因此同时打开两个扫描仪根本没有意义。
所以您肯定要选择第一种选项,那么问题来了,它有什么问题:
好吧,您要求sc.nextInt(),即整数,而名称很少是整数。您最有可能寻找一个单词的name = sc.next()或者一个完整句子的name = sc.nextLine()(直到按下回车键)。
还要注意,在sc.nextInt()之后,实际上在任何sc.next***()之后,您需要Enter键。

抱歉打错字了,我已经修改过了。问题是,在输入第一个整数后,用户将没有机会输入名称。 - user3437460
问题并不在于我之前的打字错误。当我们使用类似的扫描器对象来扫描不同类型的输入时,问题确实会发生。 - user3437460
1
@user3437460 已更新答案,您输入后按了回车键吗? - skiwi

0

这必须完美地工作。我已经测试过了。

int age=0;
String name;
Scanner sc = new Scanner(System.in);

System.out.print("Enter Age: ");
age = sc.nextInt();
System.out.print("Enter Name: ");
name= sc.nextLine();

嗯,我并不是在寻求代码或解决方案。但当然,多年来,我已经知道应该只存在一个执行相同任务的Scanner对象。 - user3437460

0
为什么这段代码没有起作用?
package Programs;
import java.util.Scanner;
public class LibraryManagement {
    Scanner s = new Scanner(System.in);
    String Sname, Bname, Bauthor;
    int Sid,Sclass,Bid;
    void StudInfo()
    {
    
    System.out.print("Enter the Student Id: ");
    Sid=s.nextInt();
    
    System.out.print("Enter the Student name: ");
    Sname=s.nextLine();
    
    System.out.print("Enter the Student Class: ");
    Sclass=s.nextInt();
    
    System.out.println("Student detail is saved:  \n Id : "+ Sid + " Name : "+ Sname+ " Class : ");
    
    }
    public static void main(String[] args) {
          LibraryManagement obj= new LibraryManagement();
          obj.StudInfo();
        }
    
    }

输出为:
输入学生ID:10
输入学生姓名:输入学生班级:


1
被接受的答案提到,您需要在.readInt()之后读取一次.readLine()以消耗数字字符串后面的换行符。您在此处发布的代码存在问题,即它从未等待用户输入学生姓名,正如您在下面展示的输出中所示。如果可以的话,我建议删除这个答案。 - ramrunner
如果你有一个新问题,请通过点击提问按钮来提问。如果它有助于提供上下文,请包含此问题的链接。- 来自审核 - Cray

0

你也可以使用:

name = sc.next();

0

你可以通过进一步的例子理解这个。单个扫描器类无法声明为接收不同数据类型的输入。因此,在进行Java输入时要具体说明。如果您要输入多个字符串,则需要为其创建一个特定的扫描器类;如果您要输入多个整数,则需要为其创建一个特定的扫描器类,它取决于不同的数据类型;如果您要输入字符,则也需要为其创建一个特定的扫描器类。这将帮助我们减少编写更多的代码,例如,如果您要输入10个整数,则为其创建一个特定的扫描器类,并使用这些单个扫描器类名称来处理这10个输入,从而减少编写每个整数输入的9行额外代码,如果您要输入10个字符串,则需要为其创建一个特定的扫描器类;如果您要输入10个字符,则需要为其创建一个特定的扫描器类,以此类推...... :) 这将减少为每种类型的输入编写代码。

代码

    import java.util.*;
    import java.lang.*;
    import java.io.*;

    public class arraylistExample {
        public static void main(String[]args){
            // This is a common scanner class for string type of inputs 
            Scanner stringcommonforall=new Scanner(System.in);
            // This is a common scanner class for integer type of inputs 
            Scanner intcommonforall=new Scanner(System.in);
            int size;
            int pos=0;
            boolean findornot=false;
            String found;
            ArrayList<String> name=new ArrayList<String>();
            System.out.print("Enter the size of the ArrayList >> ");
            size=intcommonforall.nextInt();
            // when your are using one scanner for all types of input then you will get the error 
            for(int i=0;i<size;i++){
                System.out.print(">> ");
                name.add(stringcommonforall.nextLine());
            }
            System.out.print("Enter the element you want to search inside the arraylist >> ");
            found=stringcommonforall.nextLine();
            for(String i:name){
                if(i.equals(found)){
                    findornot=true;
                    pos=name.indexOf(found);
                    break;
                }
            }
            if(findornot==true){
                System.out.println("The elements inside he arraylist >> "+name);
                System.out.println("The element >> "+found+" is found at the positioin >> "+pos);
            }
            else{
                System.out.println("The elements inside he arraylist >> "+name);
                System.out.println("The element >> "+found+" is not found inside the arraylist ");
            }
        }
    }

输出

    Enter the size of the arraylist >> 5
    >> lorem ipsum
    >> xyz
    >> zyx 1
    >> june
    >> done
    Enter the element you want to search inside the arraylist >> done
    The elements inside he arraylist >> [lorem ipsum, xyz, zyx 1, june, done]
    The element >> done is found at the positioin >> 4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接