1

時間を節約し、解析済みファイル内の各トークンを手動でテストしたくありませんが、クラスのskip(String)メソッドを正しく使用する方法がわかりません。java.util.Scanner

質問を言い換えると、以下の両方のテストに合格するにはどうすればよいですか?

import java.io.StringReader;
import java.util.Scanner;
import junit.framework.Assert;
import org.junit.Test;

public class ScannerTest {

    static private final String text = "FUNCTION_BLOCK Unnamed_project\n\tVAR_INPUT\n\t\tUnnamed_variable1 : REAL;\n\tEND_VAR\nEND_FUNCTION_BLOCK"; 

    @Test
    public void scannerSkipTest() {

        Scanner sc = new Scanner(new StringReader(text));
        sc.skip("(?i)FUNCTION_BLOCK");
        String blockName = sc.next();
        assert sc.hasNext("(?i)VAR_INPUT");         // added test
        sc.skip("(?i)VAR_INPUT");                               // line of failure
        String variableName = sc.next();
        sc.skip(":");
        String type = sc.next();
        sc.skip("(?i)END_VAR");
        sc.skip("(?i)END_FUNCTION_BLOCK");

        assert "Unnamed_project".equals(blockName);
        assert "Unnamed_variable1".equals(variableName);
        assert "REAL".equals(type);
    }

    @Test
    public void scannerWithoutSkipTest() {
        Scanner sc = new Scanner(new StringReader(text));
        String skipped = sc.next();
        assert "FUNCTION_BLOCK".equalsIgnoreCase(skipped);
        String blockName = sc.next();
        skipped = sc.next();
        assert "VAR_INPUT".equalsIgnoreCase(skipped);
        String variableName = sc.next();
        skipped = sc.next();
        assert ":".equalsIgnoreCase(skipped);
        String type = sc.next();
        skipped = sc.next();
        assert "END_VAR".equalsIgnoreCase(skipped);
        skipped = sc.next();
        assert "END_FUNCTION_BLOCK".equalsIgnoreCase(skipped);

        assert "Unnamed_project".equals(blockName);
        assert "Unnamed_variable1".equals(variableName);
        assert "REAL".equals(type);
    }
}

ヒントやヒントをいただければ幸いです。

4

2 に答える 2

2

Tuto、試した後に私の回答を編集してくれてありがとう。あなたが書いたものを取り上げて、上部の説明を書き直します。

基本的に、 でトークンをスキップするskip()場合は、最初に空白をスキップする必要があります。対照的に、next()メソッドはこれを自動的に行います。

javadoc から:

next() メソッドと hasNext() メソッド、およびそれらのプリミティブ型のコンパニオン メソッド (nextInt() や hasNextInt() など) は、最初に区切り文字パターンに一致する入力をスキップしてから、次のトークンを返そうとします。

したがって、を使用sc.skip(WHITESPACE + "abc")すると、空白をスキップしてから token をスキップできますabc。結果は次のようになります。

public class ScannerTest {

    static private final String text = "FUNCTION_BLOCK Unnamed_project\n\tVAR_INPUT\n\t\tUnnamed_variable1 : REAL;\n\tEND_VAR\nEND_FUNCTION_BLOCK";
    public static final String WHITESPACE = "[ \\n\\t]+";

    @Test
    public void scannerSkipTest() {

        Scanner sc = new Scanner(new StringReader(text));
        sc.useDelimiter(WHITESPACE);
        sc.skip("FUNCTION_BLOCK");
        String blockName = sc.next();
        sc.skip(WHITESPACE + "VAR_INPUT");
        String variableName = sc.next();
        sc.skip(WHITESPACE + ":");
        String typeWithSemiColon = sc.next();
        sc.skip(WHITESPACE + "END_VAR");
        sc.skip(WHITESPACE + "END_FUNCTION_BLOCK");

        assert "Unnamed_project".equals(blockName);
        assert "Unnamed_variable1".equals(variableName);
        assert "REAL;".equals(typeWithSemiColon);
    }
}

セミコロンは実際には空白ではないため、スキャナーはまだ分割さREALれないことに注意してください;-私はあなたが理解するための演習としてそれを残します:)

于 2013-06-22T11:27:19.743 に答える
0

参考までに、元の質問に対するよりクリーンなソリューションを投稿し、vikingsteve によって公開されたセミコロンの課題を解決しています。

これが修正されたテスト方法です。

ノート:

  • \bオプションのスペースで囲まれた区切り文字
  • キーワードをスキップするnext代わりにメソッドを使用するskip

@Test
public void scannerSkipTest() {

    Scanner sc = new Scanner(new StringReader(text));
    sc.useDelimiter("\\s*\\b\\s*|\\s+");

    sc.next("(?i)FUNCTION_BLOCK");
    String blockName = sc.next();
    sc.next("(?i)VAR_INPUT");
    String variableName = sc.next();
    sc.next(":");
    String type = sc.next();
    sc.next(";");
    sc.next("(?i)END_VAR");
    sc.next("(?i)END_FUNCTION_BLOCK");

    assert "Unnamed_project".equals(blockName);
    assert "Unnamed_variable1".equals(variableName);
    assert "REAL".equals(type);

    sc.close();
}
于 2013-06-23T11:24:48.687 に答える