【问题标题】:How do I use BufferedReader to put lines in an ArrayList and then execute them?如何使用 BufferedReader 将行放入 ArrayList 然后执行它们?
【发布时间】:2018-08-16 02:20:03
【问题描述】:

我正在尝试编写一个程序,该程序将执行并从文件中生成简化的编程语言语句的输出。文件中有几行将给出诸如 variable = expression、PRINT variable、GOTO 'x line'、IF variable IS value THEN .... 等语句。一行写着 END 是最后一行,应该停止程序。

我使用空格作为分隔符,并且知道我需要使用 BufferedReader 和 tokenizer 来拆分这些行。我正在努力解决的是如何存储所有这些语句/变量,一旦它们被拆分?并行 ArrayLists 会是一个好方法吗?如何分别读取每个变量和表达式并对其进行评估?这是我目前所拥有的:

public void processProgram() {
    String fileName = getFileName();
    if(fileName != null)
        processProgram();
    String line = null;
    ArrayList<String> name = new ArrayList<String>();
    ArrayList<Integer> value = new ArrayList<Integer>();
    try (BufferedReader br = new BufferedReader(new FileReader(getFileName())))
    {

        while((line = br.readLine()) != null){
            name.add(line);
        }
    }  catch (IOException e) {
        e.printStackTrace();
    } 

    StringTokenizer tok = new StringTokenizer(line);
    while (tok.hasMoreTokens()) {
        String token = tok.nextToken(" ");

    }


}

我是一个初学者,所以任何方向都会很棒。

【问题讨论】:

  • 你必须使用 BufferedReader 吗?
  • 不,不一定!

标签: java arraylist bufferedreader filereader tokenize


【解决方案1】:

用于解析指令的 Java 8 流

使用这样的代码:

Files.lines(Paths.get("Test.txt"))
                .map(p -> p.toUpperCase())
                .collect(Collectors.toList());

您可以获取文件中的所有行,对其进行转换(在此示例中,我只是将字符串设置为大写,您可能希望将它们转换为可用指令,但是您将它们存储在内部),然后将生成的项目存储到一个可以使用的列表。

处理列表中的项目

您需要一个指令指针,然后根据该点的指令,您可以跟随下一条指令、跳转到另一点或终止执行。

【讨论】:

    【解决方案2】:

    一种简单的方法是进行如下设置:

    List<String> lines; // from the file
    int currentIndex;   // the "instruction pointer"
    

    您可以使用 Map&lt;String, Double&gt; vars; 之类的东西来存储变量。(请参阅 Map tutorial。)

    然后有一个类似这样的方法:

    // (returns the next line)
    int executeCurrentLine() {
        String line = lines.get(currentIndex);
    
        if (line.startsWith("GOTO")) {
            return Integer.parseInt(line.substring(4).trim());
        } else if (line.startsWith("PRINT")) {
            String name = line.substring(5).trim();
            System.out.println(vars.get(name));
        } else {
            // and so on
        }
        return currentIndex + 1;
    }
    

    然后你做这样的事情:

    while (currentIndex < lines.size()) {
        currentIndex = executeCurrentLine();
    }
    

    当然有很多方法可以让它变得更复杂,但我希望这能给你一些想法,让你了解如何开始处理这样的事情。

    编辑:对上述简单方案的一项改进是创建一个抽象类:

    abstract class Command {
        // where Context is some object that lets
        // the command e.g. access variables
        abstract void execute(Context context);
    }
    
    // and for example
    class GoToCommand extends Command {
        final int lineNumber;
        GoToCommand(String line) {
            lineNumber = Integer.parseInt(line.substring("GOTO".length()).trim());
        }
        @Override
        void execute(Context context) {
            context.setCurrentLine(lineNumber);
        }
    }
    

    然后,您将解析List&lt;String&gt; 行并创建List&lt;Command&gt;,而不是同时进行解析和评估。这会让你以一种有意义的方式拆分程序逻辑。

    【讨论】:

    • 谢谢!但是使用 Map,例如 HashMap,您不必使用对象而不是 int 吗?
    • 您将使用盒装类型Integer 而不是int。自动装箱教程涵盖了这一点:docs.oracle.com/javase/tutorial/java/data/autoboxing.html。另外,我编辑了我的答案以添加其他内容。
    猜你喜欢
    • 2015-06-25
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    相关资源
    最近更新 更多