【问题标题】:How to tokenize in java without using the java.util tokenizer?如何在不使用 java.util 分词器的情况下在 java 中进行分词?
【发布时间】:2010-10-05 18:02:12
【问题描述】:

将以下内容视为令牌:

  1. +, -, ), (
  2. 字母字符和下划线
  3. 整数

实现1.getToken() - 返回下一个token对应的字符串 2.getTokPos() - 返回当前token在输入字符串中的位置

示例输入:(a+b)-21)
输出: (| a| +| b| )| -| 21| )|

注意:不能使用 java 字符串分词器类

正在进行中 - 成功标记化 +,-,),(。需要弄清楚字符和数字

输出:+|-|+|-|(|(|)|)|)|(| |

【问题讨论】:

  • 即使您可以使用分词器,也要使用拆分。 ;)
  • @Bozho 我实际上更喜欢标记器——我不知道如何让 String.split 返回标记,而且我不信任正则表达式——但我确定它们是否对你来说似乎很自然,那么 string.split 就更有意义了。
  • 有谁明白为什么教育工作者给学生分配做某事的任务,而不是让他们使用盒子里的图书馆?我的意思是 90% 的 Java 知识是知道使用哪个类,而不是知道使用哪个运算符。好吧,它可能与学习基础知识有关,但它仍然违背了规律。
  • @Peter Tillermans 这不仅仅是关于基础知识,它还使学生能够学习基础知识要少得多。像这样的练习可以是查看循环和字符串操作等基本事物的好地方,是的,但它也是使用标记器的事物的一个引导点,例如递归体面解析,然后导致 LL(k)预测解析等进入语言构造。对于那些一开始就没有真正掌握字符串标记的学生来说,所有这些事情似乎都是魔法。
  • @Zoe 我有点知道,但仍然......我做了解析器/解释器的分享,但我看不到实现低级编程如何帮助加深 LL(k) 预测解析的知识。如果您在开始之前没有完全理解它,那么您只是将自己挖得更深,并且在损坏的代码中保持高腰只会导致认知超载和感觉愚蠢,这两者都不会导致更好的理解(尽管它可能会减少傲慢) .我想我见过太多人认为实现功能比阅读提供它的库的 API 更快。

标签: java


【解决方案1】:

java.util tokenizer 是一个已弃用的类。

从 Java 1.4 开始,使用“String.split()”在 Java 中对字符串进行标记要容易得多:

String[] tokens = "(a+b)-21)".split("[+-)(]");

如果是作业,你可能要重新实现一个“拆分”方法:

  • 逐个字符读取字符串
  • 如果字符不是特殊字符,则将其添加到缓冲区中
  • 遇到特殊字符时,将缓冲区内容添加到列表中并清除缓冲区

既然它(可能)是一个家庭作业,我让你实现它。

【讨论】:

  • 我想我理解你的实现。但是,这将给出 a,b,21 而不是 (,a,+,b,),-,21,) 我仍然无法弄清楚...谢谢您的回复
  • 由于用作拆分模式的字符是拆分的分隔符,因此它们不会在结果数组中返回。不幸的是,使用 string.split 将无法真正获得所有内容。如果你分裂任何一个角色,你就会失去他们。如果你在 "" 上拆分,那么 21 就变成了两个标记,这仍然是不对的(实际上你最终会遇到和以前一样的问题,因为你只是将字符串缩减为一个字符数组)。
  • 如果你还需要分隔符,你只需对我的算法做一点修改:“如果字符是特殊字符,将缓冲区内容添加到列表中,添加'特殊字符'作为列表的下一个元素,然后才清除缓冲区”。
【解决方案2】:

Java 允许您使用charAt 方法一一检查字符串中的字符。所以在 for 循环中使用它并检查每个字符。当您遇到一个 TOKEN 时,您将该令牌与管道和您刚刚附加到输出的任何其他字符一起包装。

public static final char PLUS_TOKEN = '+';
// add all tokens as 

public String doStuff(String input)
{
    StringBuilder output = new StringBuilder();
    for (int index = 0; index < input.length(); index++)
    {
        if (input.charAt(index) == PLUS_TOKEN)
        {
            // when you see a token you need to append the pipes (|) around it
            output.append('|');
            output.append(input.charAt(index);
            output.append('|');
        }
        else if () //compare the current character with all tokens
        else
        {
            // just add to new output
            output.append(input.charAt(index);
        }

    }
    return output.toString();
}

【讨论】:

  • 你太棒了。您包含了我的作业所需的公式,现在我拥有所有工具来使它正确。我的教授希望我们自学 Java,所以编写我的第一个程序更难。
  • @Tom - 你所需要的只是朝着正确的方向轻推,我希望它不是太大的轻推。 :)
  • 1.整数常量和字符有语法吗?我还需要将它们定义为令牌。谢谢!!
  • @Tom - 当然有,但你必须自己做这个。提示是查看 Character 类download-llnw.oracle.com/javase/6/docs/api/java/lang/…
【解决方案3】:

如果不是家庭作业,请使用 String.split()。如果是家庭作业,请说出来并标记它,以便我们可以提供适当程度的帮助(我是为你这样做的,以防万一......)。

【讨论】:

  • 这是一个家庭作业,上面写着:你不能使用 jlex 或 java 字符串标记器类。因此,我假设我们可以使用拆分功能。非常感谢您的提示
【解决方案4】:

因为字符串需要以几种不同的方式进行剪切,而不仅仅是在空格或括号上,因此对其中的任何符号使用 String.split 方法都将不起作用。拆分删除用作分隔符的字符。您可以尝试在空字符串上进行拆分,但这不会得到复合符号,例如 21。要正确解析此字符串,您需要有效地实现自己的分词器。试着想想如果你一次只看一个字符的字符串,你怎么能知道你有一个完整的标记。您可能会开始一个收集字符的字符串,直到您确定一个完整的令牌,然后您可以从原始字符中删除字符并返回字符串。从这点开始,你大概可以做一个基本的分词器了。

如果您想学习如何制作一个全强度的分词器,它们中的大多数都是通过创建一个只匹配分词的正则表达式来定义的。

【讨论】:

    猜你喜欢
    • 2022-11-02
    • 1970-01-01
    • 2014-08-28
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    相关资源
    最近更新 更多