5

我正在研究 UVa Online Judge 问题集存档,作为练习 Java 的一种方式,以及作为一种练习数据结构和算法的方式。

他们提供了一个示例输入文件,以提交给在线评委作为起点(这是问题 100 的解决方案)。

来自标准输入流(java.lang.System.in)的输入是本网站上任何解决方案的一部分,但我无法理解他们在示例解决方案中给出的从 System.in 读取的实现。输入文件确实可以包含整数、字符串等的任何变体,但是每个解决方案程序都需要从 System.in 读取文本输入的基本行,一次一行。必须有一种更好(更简单、更健壮)的方法来从 Java 中的标准输入流中收集数据,而不是这样:

public static String readLn(int maxLg) {
    byte lin[] = new byte[maxLg];
    int lg = 0, car = -1;
    String line = “”;
    try {
        while (lg < maxLg) {
            car = System.in.read();
            if ((car < 0) || (car == ‘\n’)) {
                break;
            }
            lin[lg++] += car;
        }
    } catch (java.io.IOException e) {
        return (null);
    }
    if  ((car < 0) && (lg == 0)) {
        return (null); // eof
    }
    return (new String(lin, 0, lg));
}   

我对此感到非常惊讶。它看起来像是直接从 K&R 的“C 编程语言”(无论如何都是一本好书)中提取的东西,减去了访问级别修改器和异常处理等。即使我了解实现,它看起来就像是由 C 程序员编写的,并且绕过了大部分 Java 的面向对象特性。难道没有更好的方法来做到这一点,使用 StringTokenizer 类,或者使用 String 的 split 方法或 java.util.regex 包代替吗?

4

1 回答 1

11

您绝对不必一次读取一个字节(您也不需要在 C 中,这就是fgets的用途)。根据您在做什么,您可能会使用BufferedReaderScanner

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

Scanner sc = new Scanner(System.in);

BufferedReader 有一个readLine方法,而 Scanner 有多种有用的方法,包括nextLinenextIntnextDouble等,它们可以为您处理转换。它还有一个基于正则表达式的分隔符,用于读取任意标记。

关于 Java 要理解的一件事是,它在二进制数据(流)和字符数据(读取器和写入器)之间有非常明显的区别。有默认的解码器和编码器(如上所述),但您始终可以灵活地选择编码。

于 2010-06-05T23:46:38.783 回答