簡體   English   中英

壓縮類錯誤 - 線程“main”中的異常 java.lang.StringIndexOutOfBoundsException:字符串索引超出范圍:-1

[英]Compression class error - Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1

我為客戶端服務器 TCP 數據連接創建了這個簡單的壓縮類,對我來說一切都很好,沒有構建錯誤,但是我遇到了一個無法糾正的運行時錯誤。 我得到的錯誤是線程“main”中的異常 java.lang.StringIndexOutOfBoundsException: String index out of range: -1。

代碼:

import java.io.Serializable;
import java.util.ArrayList;

public class CompressedMessage implements Serializable
{   // this instance variable will store the original, compressed and decompressed message
    private String message;

    public CompressedMessage(String message)
    {   
        // begin by coding this method first - initialise instance variable message with the original message
        this.message = message;
    }

    public String getMessage()
    {   
        return this.message;

    }

    private boolean punctuationChar(String str)
    {   
        // Hint: check if the last character in the string is a punctuation
        int length = str.length();
        str = str.substring(length -2,length-1);

        if(str.equals(",") || str.equals("!") || str.equals(".") || str.equals("?"))
        {
            return true;
        }
        else
        {
            return false;
        }

    }

    private String getWord(String str)
    {   // Hint: if last character in string is punctuation then remove 

    if(punctuationChar(str)== true)
    {
        //remove punctuation of last char
        str = str.substring(0,str.length()-1);
    }

        return str;
    }


    public void compress()
    {   /* read through section 3 of the practical 5 document 
           to get you started. This is called by the server, 
           have a look at the server code where it is called */ 
        ArrayList<String> newMessage = new ArrayList<String>();


        String[] words = message.split(" ");  

        for (String word : words)  
        {  
            getWord(word);
            //if word has already appeared replace with position of previous word
            if(newMessage.contains(word))
            {
                String str = Integer.toString(newMessage.indexOf(word));
                str = str + " ";
                newMessage.add(str);
            }
            else
            {
                word = word + "";
                newMessage.add(word);
            }

         //if word had a punctuation at the end add it back in
         //System.out.println(word);  
        }  

            this.message = newMessage.toString();
            System.out.println("****************COMPRESSING*****************");
            System.out.println(newMessage);

    }

    public void decompress()
    {   /* read through section 3 of the practical 5 document 
           to get you started. This is called by the client,
           have a look at the client code where it is called */
           ArrayList<String> decompMessage = new ArrayList<String>();

           String[] words = message.split(" ");


           for (String word : words)  
        {  
            getWord(word);

            if(word.substring(0,1).matches("[0-9]"))
            {
              int num = Integer.parseInt(word);
              decompMessage.add(decompMessage.get(num));

            }
            else
            {
                decompMessage.add(word);
            }
        }

        this.message = decompMessage.toString();
        System.out.println("****************DECOMPRESSING*****************");
            System.out.println(decompMessage);  

    }
}

錯誤:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.substring(String.java:1952)
    at CompressedMessage.punctuationChar(CompressedMessage.java:24)
    at CompressedMessage.getWord(CompressedMessage.java:40)
    at CompressedMessage.compress(CompressedMessage.java:61)
    at P5_Server.waitForData(P5_Server.java:72)
    at P5_Server.main(P5_Server.java:159)

我曾嘗試更改基於 length() 計算字符串的方式,但並沒有減少錯誤。

誰能看到我做錯了什么?

如果strlength 0 (空字符串)或length 1呢? 在那種情況下str = str.substring(length -2,length-1); 將導致異常。

在執行子字符串之前,您需要進行長度檢查:

    if(length > 1){
        str = str.substring(length-2,length-1);
    }

由於您只想獲得一個角色,我認為您可以簡單地執行以下操作:

    if(length > 1){
        str = String.valueOf(str.charAt(length-2))
    }

請確保str不為空,否則也要進行空處理。

發生這種情況是因為您將空字符串傳遞給punctuationChar

哦,由於您只使用 str 中的最后一個字符,因此將其轉換為字符可能會更容易。

嘗試這個:

private boolean punctuationChar(String str) {
       if (str.length() > 0) {
           char lastChar = str.charAt(lastChar.length() - 1);

           // Returns true if the character is anything other than a letter, digit or space
           return !(Character.isLetterOrDigit(lastChar)) || Character.isWhitespace(lastChar);
       }
       else {
           return false;
       }
   }
}

我在這里使用 isLetterOrDigit,然后反轉結果。 因此,對於末尾包含 AZ、az 或 0-9 以外的任何字符串的任何字符串,此方法將返回 true。 我也將空格計算為不是標點符號。

如果 Oracle 考慮過放入“isPunctuation”方法,這會更容易!

Java 中的 Character 類非常適合這樣的檢查,下次您做類似​​的事情時絕對值得一看。 http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Character.html

您可以更輕松地檢查標點符號:

private boolean punctuationChar(String str) {   
    if (str != null && str.length() > 0) {
        char c = str.charAt(str.length()-1);
        return c == '.' || c =='?'||c==',' || c =='!';
    } else {
        return false;
    }
}

一般來說,盡量避免字符串操作,因為它們很慢。 如果您需要處理子字符串或字符串索引,請始終確保為空字符串、空字符串或短字符串做好准備

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM