简体   繁体   English

使用Scanner类读取扫描仪字符串

[英]Using the Scanner class to read a scanner string

I have a problem creating a student class which contains a constructor which takes a Scanner string of a format "Brookes 00918 X12 X14 X16 X21". 我在创建一个包含构造函数的学生类时遇到问题,该构造函数采用格式为“ Brookes 00918 X12 X14 X16 X21”的Scanner字符串。 The conditions should be that there should be a student name and student number and the course codes should start with an "X". 条件是必须有一个学生姓名和学生编号,并且课程代码应以“ X”开头。 I have thrown IncorrectFormatExceptions in the case that they are not satisfied. 如果不满意,我抛出了IncorrectFormatExceptions However when I create a test class and enter a string and press enter , for example "abc 123" it doesn't produce an output which is usually the case. 但是,当我创建一个测试类并输入一个字符串并按Enter时,例如“ abc 123”,它通常不会产生输出。

Update: I've changed the code to use a String array tokens however now with the toString() method using "123 abc X12" it gives a Null Pointer Exception. 更新:我已经更改了代码以使用String数组标记,但是现在使用toString()方法并使用“ 123 abc X12”,它给出了一个空指针异常。 It works when I put "123 abc" in the constructor 当我在构造函数中输入“ 123 abc”时,它可以工作

Update:Seems to work now forgot to initialize the arrayList 更新:似乎现在可以工作了,但忘记了初始化arrayList

    import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


public class Student extends UniversityPerson{
    private String studentNumber="";
    private List<String> courses=new ArrayList<String>();
    private String studentName="";

    public int checkNoofletters(char[] chararray){
        int noofletters=0;
        for (char c:chararray){
            if (Character.isLetter(c)){
                noofletters++;
            }
        }
        return noofletters;
    }
    public String courseListinStr(){
        String stringo="";
        for (String c:courses){
            stringo+=c;
            stringo+=" ";
        }
        return stringo;
    }

    public Student(Scanner scanner) throws IncorrectFormatException{
        int studentNumberCount=0;
        int studentNameCount=0;

        Scanner s=scanner;
        String input=s.nextLine();
        String[] tokens=input.split("\\s");

        for (int i=0; i<tokens.length; i++){
            char[] chars=tokens[i].toCharArray();

            if (checkNoofletters(chars)==chars.length){//if the number of letters is equal to the character length
                if (studentNameCount==1){throw new IncorrectFormatException("Can only have 1 student name");}
                studentNameCount++;
                this.studentName=tokens[i];
                continue;
            }
            if (tokens[i].matches("[0-9]+")){//add to the studentNumbers list
                if (studentNumberCount==1){throw new IncorrectFormatException("Can only have 1 student number");}
                studentNumberCount++;
                this.studentNumber=tokens[i];

                continue;
                }

            if (!tokens[i].startsWith("X")){
                throw new IncorrectFormatException("Course code must start with an 'X'");
            }

            System.out.println(tokens[i]);
            courses.add(tokens[i]);

        } 

        if (studentNumber=="" || studentName==""){
            throw new IncorrectFormatException("Must have 1 student Number and Student Name");
        }

    }


    @Override
    public String toString() {
        //return String.format("%s %s", studentName,courseListinStr());
        return String.format("Student: %s %s", studentName,studentNumber);
    }

    @Override
    public boolean equals(Object o) {
        // TODO Auto-generated method stub
        return false;
    }



}

The best way would be to do something like this: 最好的方法是做这样的事情:

Scanner s=scanner;
String input = s.nextLine();
String[] tokens=input.split("\\s");

Now you can test all your conditions: 现在您可以测试所有条件:

if (tokens.size() < yourNumber) throw new Exception("add here");
if (tokens[2].charAt(0)!='X') throw new Exception("add here");

and so on; 等等; it should be rather easy to create your Student Object based on your requirements. 根据您的需求创建学生对象应该相当容易。

Your program is full of errors and I'll list some of them after answering why it doesn't print anything: if you dump all threads you'll see that the main thread is stuck at next() , which blocks until next token is available, and effectively never leaves the constructor of the first student 您的程序中充满了错误,在回答为什么不输出任何内容之后,我将列出其中的一些错误:如果转储所有线程,则会看到主线程停留在next() ,直到下一个标记被阻塞为止可用,并且实际上永远不会离开第一个学生的构造函数

if (s.hasNextInt()){
  studentNumbers.add(s.nextInt());
  s.next();
  continue;  // <--------- this line
}

I think this is not the only error in your program, so maybe you'd better throw the entire parsing away and restart from scratch. 我认为这不是程序中的唯一错误,所以也许您最好扔掉整个解析过程并从头开始。

  1. You should create exactly one Scanner object for each input stream, not one for parsed object 您应该为每个输入流只创建一个 Scanner对象,而不是为解析对象创建一个 Scanner对象
  2. You should not pass the scanner to the Student constructor 应该扫描器传递给学生的构造
  3. You should not put any algorithm in a constructor: make a separate object instead 应该把任何算法在构造函数:让一个单独的对象,而不是

To simplify your program introduce a Parser class 为了简化您的程序,请引入一个Parser类

public class Parser {
  public Parser(Reader in) {}
  public boolean hasNext() {}
  public Student next() {}
}

and inside next() make the parser deal with entire lines ( Scanner.hasNextLine and Scanner.nextLine() ) instead of individual tokens, otherwise you'll have to define a custom protocol to mean EOR (end of record) 然后在next()内部使解析器处理整行( Scanner.hasNextLineScanner.nextLine() )而不是单独的标记,否则必须定义一个自定义协议来表示EOR(记录结束)

Dealing with lines is easier to think about, program and test. 处理线路更容易考虑,编程和测试。 Once you have the full record, you can further tokenize it with a simple String.split() , or directly use regular expressions. 拥有完整记录后,您可以使用简单的String.split()进一步标记它,或直接使用正则表达式。

I didn't go through, your whole code. 我没看完整您的代码。 But, I would suggest you to use StringTokenizer or split function and store it in temp array. 但是,我建议您使用StringTokenizersplit函数并将其存储在temp数组中。 Then, traverse through your temp array and validate the data. 然后,遍历您的临时数组并验证数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM