【问题标题】:Using the Scanner class to read a scanner string使用 Scanner 类读取扫描仪字符串
【发布时间】:2015-08-01 13:46:39
【问题描述】:

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

更新:我已将代码更改为使用字符串数组标记,但是现在使用使用“123 abc X12”的 toString() 方法会给出空指针异常。当我在构造函数中放入“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;
    }



}

【问题讨论】:

    标签: java


    【解决方案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");
    

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

    【讨论】:

    • 您好,感谢您的回复,我决定使用您将字符放入字符串数组标记的方法,但是现在我似乎得到了 NullPointerException。关于我在哪里得到异常,你有什么建议可以给我吗?
    • 这意味着您正在使用一个具有空值的对象。你没有初始化它。
    • 你可以更明确一点,试着告诉我们你哪里有这个错误。
    • 是的,对不起,我修好了,我忘了初始化课程数组列表。谢谢
    【解决方案2】:

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

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

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

    1. 您应该为每个输入流准确地创建 一个 Scanner 对象,而不是为已解析对象创建一个
    2. 您应该将扫描仪传递给 Student 构造函数
    3. 您应该将任何算法放在构造函数中:改为创建一个单独的对象

    为了简化你的程序,引入一个 Parser 类

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

    next() 内部,让解析器处理整行(Scanner.hasNextLineScanner.nextLine())而不是单个标记,否则您必须定义一个自定义协议来表示 EOR(记录结束)

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

    【讨论】:

    • 您好,感谢您的回复,您提出的观点很有帮助,问题是特别要求我包含一个将扫描仪作为参数的构造函数。如果我被要求这样做,你会建议我做什么?
    • 好吧,你可以使用相同的 Parser 类并直接使用 Scanner 而不是 Reader
    【解决方案3】:

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

    【讨论】:

    • 您好,感谢您的回复,我确实使用了 split 函数并遍历了一个数组,但是它似乎得到了一个空指针异常。关于我在哪里得到异常的任何想法?
    • 我忘记将arrayList初始化为一个新的List对象,解决了问题
    猜你喜欢
    • 2017-01-10
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    相关资源
    最近更新 更多