2013-11-28 95 views
0

我想写一个程序在Java中使用递归解压缩RLE语句,但我不断得到堆栈溢出错误,我不知道为什么。递归Java RLE解压缩方法[stackoverflow错误]

这里是我写迄今:

public class StringRec 
{ 
    public static void main (String args[]){ 

     System.out.println(decompress("wed4d")); 
    } 
    //Version 0.1 
    public static String decompress(String compressedText) 
    { String cText = compressedText; 
     StringBuffer newString = new StringBuffer(); 

     int i = 0; 

     if (cText==""){return newString.toString();} 

     if(!cText.isEmpty()){ 

      if(Character.isLetter(cText.charAt(i))){ 
       newString.append(cText.charAt(i)); 

       cText = cText.substring(1,cText.length()); 

       return decompress(cText); 
       //remove first letter, return new modified string with removed first letter to decompress. 
      } 
      if(Character.isDigit(cText.charAt(i))){ 
       int c = cText.charAt(i)-'0'; 

       if (c==0){ 
        cText = cText.substring(2,cText.length());} 

        return decompress(cText); 
        //delete c and the letter after it and send new modified string to decompress. 
        } 

       }else { 
        newString.append(cText.charAt(i+1)); 
        int c = cText.charAt(i); 
        c--; 
        String num = ""+c; 
        cText = cText.replaceFirst(num, Character.toString(cText.charAt(i))); 

        return decompress(cText); 
        //appends character after number to newString, decrements the number and returns 
        //the new modified string to decompress with the first number decremented by one 
        } 
     return newString.toString(); 

    } 
} 

我对递归基本情况是一个空字符串,如果字符串以字母开头的那封信被添加到StringBuffer的newString只有一次,即第一从字符串序列中删除原始字符串的字母,并将新字符串传递给解压缩;如果它以零的数字开始,则删除字符串的前两个字符,并将新字符串传递给解压缩。

如果它是一个大于0的数字[else],那么它前面的字母将被添加到stringbuffer newString中,并且该数字会递减并替换字符串开始处的数字,并将新字符串[与原始第一个字符编号 - 1]解压缩。

+0

字符串有多长? Java不支持无限递归;递归算法只有在不太复杂时才有效。 – user2357112

+0

不知道堆栈溢出,但每次递归调用'decompress'时,递归例程都会创建一个** new **'newString'。例程的新调用将**不附加到旧调用使用的相同'newString'。你的递归方法可能需要把'newString'作为它自身传递的参数,然后在第一次调用递归例程之前,外部的非递归例程将需要初始化它。 – ajb

+0

你有没有尝试在调试器中逐句通过你的代码?这和几个很好的'System.out.println'记录调用将帮助你找出为什么你的递归没有达到基本情况并导致错误... – Krease

回答

1

我相信无限递归,因为发生这种情况:

int c = cText.charAt(i); 
c--; 
String num = ""+c; 
cText = cText.replaceFirst(num, Character.toString(cText.charAt(i))); 

如果字符是1,然后c将是65岁,性格'1'的ASCII值。然后num将被设置为字符串"64",如果字符串中没有"64",则该方法会一直使用相同的字符串继续调用自身。声明cchar应该解决该问题。另外,请注意replaceFirst表示要搜索与第一个参数匹配的模式,并用第二个参数替换它。你可能会倒退。另外,请参阅我上面关于newString的评论。

编辑:回答您的评论:使用StringBuffer是好的。你不能做的是每个decompress都创建一个new StringBuffer,因为那时每次都会调用decompress一个新的StringBuffer就会被创建出来,这不是你想要的。如果decompress需要StringBuffer newString参数,每个decompress自称为它传递newString作为参数时,那么每decompress通话将指向相同StringBuffer,因为它是一个对象的引用。

,我想你暗示了另一种方法,由于decompress返回String,则每次decompress调用它本身可以使用函数的结果(现在你的代码只是把它扔了),也许串联该函数返回新的字符串。我认为你可以使这种方法奏效,但我没有彻底研究它。

+0

谢谢,我修复了它,并会发布更新的代码。你可以进一步扩展newString和递归例程吗?我会怎么做呢?我可以改变它,让字符串缓冲区是一个正常的字符串,我连接它。 – CameronCarter

+0

@ user3003741看我的编辑。 – ajb