1

このプログラムは、キーとオートマトンの次の部分の両方の情報を保持するツリーの形で非決定性オートマトンを作成することになっています。オートマトンは、テキストのパターンを見つけることです (それよりも複雑ですが、まだ次の部分に進んでいないので、私の質問には十分なはずです)。

方法はわかりませんが、オートマトンを構築するための単純なパターンを実行すると (「AA」は私のパターンです)、「sgte」(次) が null になり、配列の長さ (N [ kN]) は 0 ではありません。理由がわかりません :(

コードは次のとおりです。

public class AFND {

    private boolean estado; // true o false dependiendo de si es final o inicial respectivamente.
    private AFND sgte[];  //arreglo con todos los posibles estados siguientes
    private int N;  //cantidad de posibles estados siguientes
    private char key[]; //key[i] es el caracter con el que se accede a sgte[i] { '-' = e  }
    private int q; //denominador de estado
    private String alfa = "aaabcdefghijklmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZZZ"; //para ahorrarnos errores revisamos indexOf desde la posicion 2 donde sea necesario

    public AFND() {
        estado = true;
        sgte = null;
        N = 0;
        key = null;
        q = 0;
    }

    public AFND(int q) {
        estado = true;
        sgte = null;
        N = 0;
        key = null;
        this.q = q;
    }

    public AFND(String s) {
        if (check(s) == false) {
            U.println("Patrón Invalido.");
            System.exit(0);
        }
        AFND k = Construccion(s, 0);
        estado = k.estado;
        int i = 0;
        sgte = new AFND[k.N];
        key = new char[k.N];
        while (i < k.N) {
            sgte[i] = k.sgte[i];
            key[i] = k.key[i];
            i++;
        }
        N = k.N;
        q = k.q;
    }

    public AFND Construccion(String s, int l) {
        if (s.length() == 0) {
            return new AFND();
        }
        AFND k = new AFND(l);
        k.estado = false;
        k.q = l;
        if (s.charAt(0) == '[') {
            AFND sgte[] = new AFND[5];
            char key[] = new char[5];
            String h = s.substring(1, s.indexOf(']'));
            int i = 0;
            int j = 0;
            int x;
            String L[] = new String[5];
            while (i < 5) {
                L[i] = "";
                while (j < h.length()) {
                    x = alfa.substring(2).indexOf(h.charAt(j));
                    L[i] += alfa.charAt(x + i - 2);
                    j++;
                }
                j = 0;
                L[i] += s.substring(s.indexOf(']') + 1);
                sgte[i] = Construccion(L[i].substring(1), l);
                l++;
                key[i] = L[i].charAt(0);
                i++;
            }
            k.N = 5;
        } else {
            AFND sgte[] = new AFND[1];
            char key[] = new char[1];
            key[0] = s.charAt(0);
            if (s.length() > 1) {
                sgte[0] = Construccion(s.substring(1), l);
            } else {
                sgte[0] = new AFND(l);
            }
            k.N = 1;
            l++;
        }
        int o = 0;
        k.sgte = new AFND[k.N];
        k.key = new char[k.N];
        while (o < k.N) {
            k.sgte[o] = sgte[o];
            k.key[o] = key[o];
            o++;
        }
        return k;
    }

    public boolean estado() {
        return estado;
    }

    public AFND[] sgte() {
        return sgte;
    }

    public int ancho() {
        return N;
    }

    public char[] key() {
        return key;
    }

    public int num() {
        return q;
    }

    public boolean check(String s) {
        int i = 0;
        int j = 0;
        while (i < s.length()) {
            if (j == 0) {
                if (s.charAt(i) == '[') {
                    j = 1;
                } else if (s.charAt(i) == ']') {
                    return false;
                } else if (!Character.isLetter(s.charAt(i))) {
                    return false;
                }
            } else {
                if (s.charAt(i) == ']') {
                    j = 0;
                } else if (s.charAt(i) == '[') {
                    return false;
                } else if (!Character.isLetter(s.charAt(i))) {
                    return false;
                }
            }
            i++;
        }
        return true;
    }
}

そして、実行中のプログラムは次のとおりです。

import java.io.IOException;

public class Tarea2 {

static public void main(String[] args) throws IOException{
    String m=U.readLine("Ingresar Patrón: ");
    AFND patron=new AFND(m);
    U.println("AFND Patron Desplazado: ");
    U.println("");
    U.println("<!--Deus ex Machina-->");
    U.println("<structure>");
    U.println("<type>");
    U.println("fa");
    U.println("</type>");
    U.println("<automaton>");
    imprimirEstados(patron);
    imprimirTransiciones(patron);
    U.println("</automaton>");
    U.println("</structure>");
}

static public void imprimirEstados(AFND m){
    U.println("<state id="+m.num()+" name=q"+m.num()+">");
    U.println("<x>");
    U.println("0.0");
    U.println("</x>");
    U.println("<y>");
    U.println("0.0");
    U.println("</y>");
    U.println("</state>");
    int i=0;
    if(m.ancho()!=0){
        AFND[] s=m.sgte();
        while(i<m.ancho()){
            imprimirEstados(s[i]);
            i++;
            }
        }
    }

static public void imprimirTransiciones(AFND m){
    if(m.ancho()!=0){
        int i=0;
        while(i<m.ancho()){
            U.println("<transition>");
            U.println("<from>");
            U.println(m.num());
            U.println("</from>");
            U.println("<to>");
            U.println(m.sgte()[i].num());
            U.println("</to>");
            U.println("<read>");
            U.println(m.key()[i]);
            U.println("</read>");
            imprimirTransiciones(m.sgte()[i]);
            i++;
        }
    }
}

}

助けてください :(

例外は次のとおりです。

Exception in thread "main" java.lang.NullPointerException
at tarea2cs.AFND.Construccion(AFND.java:104)
at tarea2cs.AFND.Construccion(AFND.java:95)
at tarea2cs.AFND.<init>(AFND.java:48)
at tarea2cs.Tarea2.main(Tarea2.java:9)

104はこの部分です:

        while(o<k.N){ 
        k.sgte[o]=sgte[o];    <=
        k.key[o]=key[o];
        o++;
    }

「if(sgte!=null)」を追加することもできますが、そうすべきでないときにnullになるという問題は解決しません:(

4

3 に答える 3

3

シャドーイングの問題だと思います。インスタンス変数sgteがありますが、いくつかの場所で同じ名前のローカル変数を宣言しています。例えば

   AFND sgte[] = new AFND[5];

これは間違いのように見えます...そして私の推測では次のようになります:

   sgte = new AFND[5];

(あなたは少なくとも別の場所で同じ過ちを犯します。)


また、記述されたコードには重大な保守性の問題があることもコメントする必要があります。説明コメントなしで 1 文字の変数名と省略形 ( とsgteなどAFND) を広く使用すると、他の誰かがこのアプリケーションが何であるかを理解するのが難しくなります。

于 2012-09-29T01:30:05.780 に答える
1

sgte配列を作成しただけで、初期化したことはありません。

private AFND sgte[];  //arreglo con todos los posibles estados siguientes


   public AFND(int q) {
    estado = true;
    sgte = null;
    N = 0;
    key = null;
    this.q = q;
}

ここで0インデックスの要素を取得しようとしています

   while (o < k.N) {
        k.sgte[o] = sgte[o];   //NPE
        k.key[o] = key[o];
        o++;
    }

また、同じ名前のローカル変数を作成しています(とにかく問題ではありません)。ただし、区別するには、インスタンス変数にthis.sgteを使用します。

于 2012-09-29T01:32:15.493 に答える
1

配列を作成しましたが、オブジェクトを作成していません。

 sgte = new AFND[k.N];
 for(int i=0;i<k.N;i++){
   sgte[i]=new AFND();
 }
于 2012-09-29T01:29:38.203 に答える