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

时间:2015-08-01 13:46:39

标签: java

我在创建一个包含构造函数的学生类时遇到问题,该构造函数采用格式的扫描程序字符串" Brookes 00918 X12 X14 X16 X21"。条件应该是应该有一个学生姓名和学生编号,课程代码应该以" X"开头。在他们不满意的情况下,我抛出了IncorrectFormatExceptions。但是,当我创建一个测试类并输入一个字符串并按下回车键时,例如" abc 123"它通常不会产生输出。

更新:我已将代码更改为使用String数组标记,但现在使用toString()方法使用" 123 abc X12"它给出了一个空指针异常。当我把" 123 abc"在构造函数

更新:现在似乎忘了初始化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;
    }



}

3 个答案:

答案 0 :(得分:1)

最好的方法是做这样的事情:

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

现在您可以测试所有条件:

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

等等;根据您的要求创建学生对象应该相当容易。

答案 1 :(得分:1)

你的程序充满了错误,我会在回答为什么它没有打印任何内容之后列出其中的一些:如果你转储所有线程,你会看到主线程卡在{ {1}},阻止直到下一个令牌可用,并且实际上永远不会离开第一个学生的构造函数

next()

我认为这不是你程序中唯一的错误,所以也许你最好抛弃整个解析并从头开始重启。

  1. 您应该为每个输入流创建完全一个扫描程序对象,而不是为解析对象创建一个
  2. 您应将扫描程序传递给学生构造函数
  3. 你应该将任何算法放在构造函数中:改为创建一个单独的对象
  4. 为简化程序,请引入Parser类

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

    public class Parser { public Parser(Reader in) {} public boolean hasNext() {} public Student next() {} } 内部使解析器处理整行(next()Scanner.hasNextLine)而不是单个令牌,否则您必须定义自定义协议以表示EOR (记录结束)

    处理线条更容易思考,编程和测试。获得完整记录后,您可以使用简单的Scanner.nextLine()对其进行进一步标记,或直接使用正则表达式。

答案 2 :(得分:0)

我没有通过,你的整个代码。但是,我建议您使用StringTokenizersplit函数并将其存储在临时数组中。然后,遍历您的临时数组并验证数据。