2016-12-02 66 views
1
import java.io.File; 
    import java.util.HashMap; 
    import java.io.IOException; 
    import java.util.Random; 
    import java.util.Scanner; 
    import java.util.Set; 

    /** 
    * MarkovModel.java Creates an order K Markov model of the supplied source 
    * text. The value of K determines the size of the "kgrams" used to generate 
    * the model. A kgram is a sequence of k consecutive characters in the source 
    * text. 
    * 
    * 
    */ 
    public class MarkovModel { 

    // Map of <kgram, chars following> pairs that stores the Markov model. 
    private HashMap<String, String> model; 
    private String kgram; 
    private int size; 
    private String charAft; 
    private Random kgramChooser; 
    private Random charChooser; 
    private String firstKgram; 
    // add other fields as you need them ... 


    /** 
    * Reads the contents of the file sourceText into a string, then calls 
    * buildModel to construct the order K model. 
    * 
    * DO NOT CHANGE THIS CONSTRUCTOR. 
    * 
    */ 
    public MarkovModel(int K, File sourceText) { 
     model = new HashMap<>(); 
     try { 
     String text = new Scanner(sourceText).useDelimiter("\\Z").next(); 
     buildModel(K, text); 
     } 
     catch (IOException e) { 
     System.out.println("Error loading source text: " + e); 
     } 
    } 


    /** 
    * Calls buildModel to construct the order K model of the string sourceText. 
    * 
    * DO NOT CHANGE THIS CONSTRUCTOR. 
    * 
    */ 
    public MarkovModel(int K, String sourceText) { 
     model = new HashMap<>(); 
     buildModel(K, sourceText); 
    } 


    /** 
    * Builds an order K Markov model of the string sourceText. 
    */ 
    private void buildModel(int K, String sourceText) { 
     if(K < 0 || sourceText.length() < K) { 
     throw new IOException(); 
     } 

     for (int i = 0; i < sourceText.length() - K; i++) { 
     String kgram = sourceText.substring(i, i + K) + ""; 
     String charAfter = model.get(kgram); 
     if (charAfter == null) { 
      charAfter = ""; 
     } 
     char charAft; 
     if (i < sourceText.length() - K) { 
      charAft = sourceText.charAt(i + K); 
     } 

     model.put(kgram, charAfter + charAft); 
     } 

     int size = model.size(); 
     String[] kgram = model.keySet().toArray(new String[0]); 
     String firstKgram = sourceText.substring(0, K); 
     Random kgramChooser = new Random(); 
     Random charChooser = new Random(); 
    } 


     /** Returns the first kgram found in the source text. */ 
    public String getFirstKgram() { 
     return firstKgram; 
    } 


    /** Returns a kgram chosen at random from the source text. */ 
    public String getRandomKgram() { 
     return kgram[kgramChooser.nextInt(size)]; 
    } 


    /** 
    * Returns the set of kgrams in the source text. 
    * 
    * DO NOT CHANGE THIS METHOD. 
    * 
    */ 
    public Set<String> getAllKgrams() { 
     return model.keySet(); 
    } 


    /** 
    * Returns a single character that follows the given kgram in the source 
    * text. This method selects the character according to the probability 
    * distribution of all characters that follow the given kgram in the source 
    * text. 
    */ 
    public char getNextChar(String kgram) { 
     String charAfter = model.get(kgram); 
     if (charAfter == null) { 
     return '\u0000'; 
     } 
     return charAfter.charAt(charChooser.nextInt(charAft.length())); 
    } 


    /** 
    * Returns a string representation of the model. 
    * This is not part of the provided shell for the assignment. 
    * 
    * DO NOT CHANGE THIS METHOD. 
    * 
    */ 
    @Override 
    public String toString() { 
     return model.toString(); 
    } 

    } 

我真的是一个编码业余爱好者,请原谅我可能会使用的术语,但我遇到下面列出的错误。上面的代码来自我一直在处理的任务,但为什么当kgram只是一个字符串数组时出现这个错误?在单独的文件中实例化MarkovModel的最好方法是什么?请不要张贴我只需要理解为什么的答案。了解为什么“需要阵列,但发现字符串”出现错误

MarkovModel.java:104: error: array required, but String found return 
     return kgram[kgramChooser.nextInt(size)]; 
+4

您至少有三个变量(两个局部变量和一个属性),它们具有不同的类型,但名为'kgram'。这很混乱。作为@macmoonshine的 – clemens

+0

已经说过你有几个变量叫'kgram'。这会抛出错误。它应该工作,如果你使用每个变量的唯一名称 – XtremeBaumer

+0

你可以把行号码 –

回答

0

在代码中,你有一个潜在的NullPointerException潜伏指日可待在这一部分:

if(K < 0 || sourceText.length() < K) { 
    throw new IOException(); 
} 

如果参数sourceText提供什么为文字空?你得到导致NPE的null.length()。

此代码是不必要的:

for (int i = 0; i < sourceText.length() - K; i++) { 

因此这种情况不能用在你的代码中出现:

if (i < sourceText.length() - K) { 
     charAft = sourceText.charAt(i + K); 
} 

,因为它是由评估表达式中的for循环已经覆盖。

对于那些不掌握String[] kgram = model.keySet().toArray(new String[0]);部分读者,阅读this

你有一个getter法

public String getFirstKgram() { 
    return firstKgram; 
} 

它返回firstKgram值,但在方法:

private void buildModel(int K, String sourceText) 

你不设置这个firstKgram价值可言。这是期望的行为?

我不能确定参考在吸气剂的方法的数据类型kgramChooser:

public String getRandomKgram() { 
    return kgram[kgramChooser.nextInt(size)]; 
} 

因为在所提供的码块未指定的数据类型是。猜测kgramChooser.nextInt(size)做什么是不可能的,没有适当的代码供我们审查。

你可能有buildModel(int K, String sourceText)方法与对象的成员字段String[] kgramString firstKgramRandom kgramChooserRandom charChooser内混合了本地数据类型。如果是这种情况,请删除每行开始处的数据类型,以便引用对象成员字段。

因此,该代码:

String[] kgram = model.keySet().toArray(new String[0]); 
String firstKgram = sourceText.substring(0, K); 
Random kgramChooser = new Random(); 
Random charChooser = new Random(); 

更改此代码:

kgram = model.keySet().toArray(new String[0]); 
firstKgram = sourceText.substring(0, K); 
kgramChooser = new Random(); 
charChooser = new Random(); 

假设被引用的数据类型实际上是您的对象内成员字段。

UPDATE:

在buildModel添加一个额外的空指针检查()方法,像这样:

private void buildModel(int K, String sourceText) { 
    if (sourceText == null) throw new NullPointerException("sourceText parameter is NULL literal"); 

    if(K < 0 || sourceText.length() < K) { 
    throw new IOException(); 
    } 

    ... 

在构造MarkovModel(int K, File sourceText),改变模型的实例为:

public MarkovModel(int K, File sourceText) { 
     model = new HashMap<String, String>(); 

你不必这样做,但它肯定是更好的编程,因为你在构造函数中有完整的概览Map实际上保存为obj的内容学分。

还要将私有成员字段model从HashMap更改为Map,因为您应该始终对接口进行编程,而不是执行。 这样:

HashMap<String, String> model; 

变成了: “有效的Java,第二版” 由Joshua布洛赫:

Map<String, String> model; 

您可以通过阅读一本精彩的书叫做提高你的编程技巧。

这将节省你在计算器上这里尴尬的时刻;)

如果你按照上面提到的我的指示,你会发现你的解决方案,您正在寻找。

顺便说一句:不要忘记upvote并选择最适合您的问题的答案。

祝你好运!

+0

我添加了完整的代码,并感谢您提供详细的回复。 – CAW

1

很可能你在你的班级中有一个名为kgram的字符串字段。在你的buildModel方法中,你有一个局部变量kgram这是一个字符串数组。但是在getRandomKgram方法中,您不会引用该变量,那么请参阅您班级的kgram字段。

+0

我确实在类中声明了'kgram'作为字符串。所以你说重命名字符串数组来解决问题? – CAW

相关问题