【问题标题】:Splitting string algorithm in JavaJava中的拆分字符串算法
【发布时间】:2013-10-14 18:02:05
【问题描述】:

我正在尝试使以下算法起作用。我想要做的是将给定的字符串拆分为由一系列数字或运算符组成的子字符串。

所以对于这个字符串 = "22+2",我会得到一个数组,其中 [0]="22" [1]="+" 和 [2]="2"。

这是我目前所拥有的,但我得到了一个索引超出范围的异常:

public static void main(String[] args) {
    String string = "114+034556-2";
    int k,a,j;
    k=0;a=0;j=0;
    String[] subStrings= new String[string.length()];

    while(k<string.length()){
        a=k;
        while(((int)string.charAt(k))<=57&&((int)string.charAt(k))>=48){
            k++;}
        subStrings[j]=String.valueOf(string.subSequence(a,k-1)); //exception here

        j++;
        subStrings[j]=String.valueOf(string.charAt(k));
        j++;

   }}

我宁愿被告知我的推理出了什么问题,也不愿被提供替代方案,但我当然会感谢任何形式的帮助。

【问题讨论】:

  • 您希望它适用于所有运营商,而不仅仅是+,对吧?
  • 是的,现在标准“任何不是数字的东西”都可以。
  • 您是对这个特定的算法感兴趣,还是对解析数字和运算符的一般问题感兴趣?也就是说,你会对不同的算法感兴趣吗?
  • 我会的,因为我需要为学校项目做这个,但我也很感兴趣为什么我正在做的事情不起作用(我一遍又一遍地看着它我不明白)。在这两种情况下,任何输入都非常受欢迎。

标签: java string algorithm substring


【解决方案1】:

我故意不直接回答这个问题,因为看起来您正在尝试自己找出解决方案。我还假设您故意不使用 split 或 indexOf 函数,这会使这变得非常简单。

我注意到的一些事情:

  1. 如果输入字符串很长,最好使用 char 数组和字符串生成器,这样可以避免不可变字符串引起的内存问题
  2. 您是否尝试过捕获异常,或打印出导致索引越界问题的 k 值?
  3. 您是否想过当您的字符串终止时会发生什么?例如,当输入字符串为“454”或类似的微不足道的情况时,您是否通过调试器运行此程序?

【讨论】:

  • 我不会说我“有目的地”不使用这么多,因为我很笨,也不知道有更简单的方法可以做到这一点,但是是的,我想知道为什么这个特定的解决方案不起作用。我接受了您关于打印索引的建议,我想我知道现在发生了什么。正如您所说,它必须与结束时发生的事情有关,并且由于我建立的标准,索引会继续运行。我还在想办法,但非常感谢您的意见。
【解决方案2】:

您可以使用正则表达式从使用lookahead and lookbehind assertions 的运算符中拆分数字

String equation = "22+2";
String[] tmp = equation.split("(?=[+\\-/])|(?<=[+\\-/])");
System.out.println(Arrays.toString(tmp));

【讨论】:

    【解决方案3】:

    如果您对解析的一般问题感兴趣,那么我建议您逐个字符地考虑它,并通过一个有限状态机处理每个新字符。 (通常您需要一个不能出现在输入中的终止符,例如 C 字符串中的 \0,但我们可以绕过它。

    在这种情况下,您可能有以下状态:

    1. 初始状态
    2. 刚刚解析了一个数字。
    3. 刚刚解析了一个运算符。

    字符决定状态到状态的转换:

    • 您从状态 1 开始。
    • 数字转换到状态 2。
    • 运算符转换到状态 3。

    可以使用enum 之类的东西来跟踪当前状态,在消耗每个字符后更改状态。

    通过该设置,您只需遍历输入字符串并打开当前状态。

    // this is pseudocode -- does not compile.
    List<String> parse(String inputString) {
        State state = INIT_STATE;
        String curr = "";
        List<String> subStrs = new ArrayList<String>();
        for(Char c : inputString) {
          State next;
          if (isAnumber(c)) {
            next = JUST_NUM;
          } else {
            next = JUST_OP;
          }
    
          if (state == next) {
            // no state change, just add to accumulator:
            acc = acc + c;
          } else {
            // state change, so save and reset the accumulator:
            subStrs.add(acc);
            acc = "";
          }
          // update the state
          state = next;
        }
        return subStrs;
    }
    

    使用这样的结构,您可以更轻松地添加新功能/构造,方法是添加新状态并根据当前状态和传入角色更新行为。例如,您可以添加一个检查以在字符串中出现字母时抛出错误(并包括偏移位置,如果您想跟踪它)。

    【讨论】:

      【解决方案4】:

      如果你的标准只是“任何不是数字的东西”,那么如果你不介意使用并行数组,你可以使用一些简单的正则表达式 -

      String[] operands = string.split("\\D");\\split around anything that is NOT a number
      char[] operators = string.replaceAll("\\d", "").toCharArray();\\replace all numbers with "" and turn into char array.
      

      【讨论】:

      • 你需要转义你的斜线。此外,Character#isDigit 似乎更直接。
      • @Aurand 谢谢,我总是忘记双重转义。
      【解决方案5】:
      String input="22+2-3*212/21+23";
           String number="";
           String op="";
           List<String> numbers=new ArrayList<String>();
           List<String> operators=new ArrayList<String>();
           for(int i=0;i<input.length();i++){
               char c=input.charAt(i);
               if(i==input.length()-1){
                   number+=String.valueOf(c);
                   numbers.add(number);
               }else if(Character.isDigit(c)){
                   number+=String.valueOf(c);
               }else{
                    if(c=='+' || c=='-' || c=='*' ||c=='/'){
                   op=String.valueOf(c);
                   operators.add(op);
                   numbers.add(number);
                   op="";
                   number="";
                   }
               }
           }
           for(String x:numbers){
               System.out.println("number="+x+",");
           }
           for(String x:operators){
               System.out.println("operators="+x+",");
           }
      

      这将是输出 number=22,number=2,number=3,number=212,number=21,number=23,operator=+,operator=-,operator=*,operator=/,operator=+,

      【讨论】:

      • 不。如果c 是一个字母,它永远不会是“+”、“-”等。
      • 这行得通,它提供了一些关于我做错了什么的见解。谢谢。
      • @ermyuriel 我很高兴能帮上忙 ^_^
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 2014-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多