0

私のデータ構造プロジェクトの目標は、アーティスト、タイトル、歌詞が明確にマークされた10000を超える曲を含む提供されたファイルを読み込むことであり、各曲は1つの二重引用符で囲まれた行で区切られています。このコードを記述してテキストファイルを解析しました。実行時間は3秒弱で
、422K行のテキストを読み取り、
Songオブジェクトを作成してそのSong
をArrayListに追加します。

私が書いた解析コードは次のとおりです。

if (songSource.canRead()) {  //checks to see if file is valid to read
    readIn= new Scanner(songSource);
    while (readIn.hasNextLine()) {
 do {
     readToken= readIn.nextLine();

             if (readToken.startsWith("ARTIST=\"")) {
  artist= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("TITLE=\"")) {
  title= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("LYRICS=\"")) {
  lyrics= readToken.split("\"")[1];
      } else {
  lyrics+= "\n"+readToken;
      }//end individual song if block
 } while (!readToken.startsWith("\"")); //end inner while loop

    songList.add(new Song(artist, title, lyrics));

    }//end while not EOF 
} //end if file can be read 

私はこのプロジェクトのコードについてアルゴリズム入門教授と話していましたが、彼は、他の人から提供されたデータの不整合を許容するために、コードをより防御的にするように努めるべきだと述べました。もともと私はArtist、Title、Lyricsフィールドの間にif / elseブロックを使用していましたが、彼の提案により、シーケンシャルifステートメントに変更しました。このコード例を使用して彼の主張を理解することはできますが、入力の不整合を許容することについて、どうすればより防御的になることができますか?

4

6 に答える 6

4

たとえば、次のように置き換えます。

artist= readToken.split("\"")[1];

String[] parts = readToken.split("\"");
if(parts.length >= 2) artist = parts[1];
else continue;

その他の変更には次のものが含まれます。

  1. ローカル変数をリセットします (最初の曲の後にアーティストが指定されていない場合に、曲の間違ったアーティストを誤って取得しないようにします)。
  2. 一部のデータが欠落している場合の対処方法を決定します - それでも曲を曲リストに追加しますか?
于 2010-09-21T01:50:11.677 に答える
2

現実の世界では、データの整合性に関していくつかの保証が行われています。ユーザー入力 (標準入力またはファイルから) を処理する場合、注意が必要な問題をユーザーに通知するためのプロジェクト定義のパラダイムがあります。

たとえば、コードをコンパイルするコンパイラまたはスクリプトを実行するシェルが矛盾に遭遇した場合、停止して矛盾を含む行を出力し、その下に "^" 記号を使用して問題の場所を示す 2 行目を表示することがあります。

1. すべての行にすべてのフィールドが含まれていることが保証されています
か?
2. フィールドの順序は保証されていますか?

それらが入力契約の条件であり、違反している場合は、その行を無視/報告する必要があります。それらが入力の条件でない場合は、それを処理する必要があります..現在は処理していません。

于 2010-09-21T01:53:41.087 に答える
2

入力が完全であると想定しています。アプリケーションの現在のセットアップ方法を見ると、アルゴリズムの簡単な読み取りに基づいて、データは次のようになります

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"

しかし、場合を考えてみましょう

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"
ARTIST="Peter"
LYRICS="Sing Song All night long"
"

アルゴリズムに基づいて、次の特徴を持つ 2 つの曲ができました。

songList = { Song("JOHN", "HELLO WORLD", "Sing Song All night long"),
             Song("Peter", "HELLO WORLD", "Sing Song All night long") }

現在のアルゴリズムでは、アーティストとタイトルが公開されており、定義されていなくても 2 曲目に表示されます。3 つの変数をリセットする必要があります。

あなたのelseでは、完全な行を歌詞にダンプしているだけです。すでに歌詞を引き出していたら、それを上書きしています。テストケース

 ARTIST="John"
 LYRICS="Sing Song All night long"
 TILET="HELLO WORLD"
 "

このレコードをエラー状態にすることを検討してください。そのため、バッチ読み取りが完了すると、エラー レポートを生成して修正できます。

また、アーティストが読み込まれた後にのみ EOF を考慮します。アーティストの読み込み中に EOF が発生し、ファイルが " で終わらない場合はどうなりますか。そこで例外が発生します。do/while に、hasNextLine の別のチェックを追加します。 ()

于 2010-09-21T02:05:45.723 に答える
1

ジェイソンには欠けているものがいくつかあります。

if/else は問題なく、ロジックは変更されないと思います。ただし、変数のスコープはできる限り制限する必要があります。while ループ内でアーティスト、タイトルなどを宣言すると、それらは null (または何でも) に初期化されるため、エントリにアーティストが含まれていない場合、最後のエントリの値は取得されません。

また、タイトル、アーティストなどに引用が含まれている場合はどうなりますか? それはどのように処理されますか?複数行に見える歌詞はどうですか?

不明なフィールドがある場合はどうなりますか? スペルミスの可能性がありますか? 正しくないように見える歌詞の最後に追加されます。LYRICS フィールドが見つかったら、追加する必要があります。歌詞が null の場合、"null" で始まります。

于 2010-09-21T02:01:18.973 に答える
0

例外を処理します(スキャナーが無効な文字に対してInputMismatchExceptionをスローする可能性があると思います)。

do { } while (...)ファイルの形式が正しくなく、ファイルの終わりに達した場合、canは無限にループする可能性があるようです。

空になることを妨げるものはありませんartisttitle

于 2010-09-21T02:33:07.640 に答える
0

対処できるいくつかの問題を次に示します。

  • あなたのコードは、(たとえば) "ARTIST" の前に空白がないこと、"=" 記号の周りに空白がないことなどを前提としています。

  • あなたのコードは、キーワードがすべて大文字であることを前提としています。誰かが小文字または大/小文字混合を使用できます。

  • あなたのコードは、で始まらない行keyword=\"は曲の歌詞の続きであると想定しています。しかし、ユーザーが入力した場合はどうなるARTOST="Sting"でしょうか? または、ユーザーがアーティスト名に 2 行を使用しようとした場合はどうなるでしょうか。

最後に、この場合の「else if」を「if」に置き換えたことが、コードの堅牢性に違いをもたらしたとは確信していませ

于 2010-09-21T02:00:24.230 に答える