0

私は課題を完了しました (はい、それはプログラミングのクラスのためです) が、残念ながら、可能な限り最も効率的な方法でそれを進めていませんでした。これは基本的に uniq プログラムであり、ファイル内の隣接する行を比較し、繰り返される行のコピーを 1 つだけ出力します。いくつかのメモ: printUniq() は、さまざまなフラグを考慮した独自の関数です。readline() は、malloc と realloc を使用して任意の長さの行を char * バッファーに読み込む別の関数です。以下が気になる部分です。

if(prevline != NULL)
{
  while(thisline != NULL)
  {
     while(thisline != NULL && strcmp(prevline, thisline) == 0)
     {
        count++;
        free(prevline);
        prevline = thisline;
        thisline = readline(stream);
     }
     printUniq(prevline, cflag, dflag, uflag, count);
     count = 1;
     free(prevline);
     if (thisline != NULL)
     {
        prevline = thisline;
        if((thisline = readline(stream)) == NULL)
        {
           printUniq(prevline, cflag, dflag, uflag, count);
        }
     }  
  }

このプログラムを構成するより良い方法はありますか? ループで thisline の NULL を 3 回チェックする必要がありません。外側の while ループの最初の NULL チェックが必要であり、最後の行が重複している場合に備えて、ネストされた while の次のチェックが必要です。free の呼び出し後の次のチェックでは、基本的に、thisline が null であるために「重複ループ」が終了したかどうかをチェックし、そうでない場合は、プログラムが別の行を取得できるようにします。次に、次のチェックはファイルの最後の行に対してのみ行われます。これが存在しない場合、 readline が null を返す (ファイルにそれ以上の行がない) と、ループが終了し、prevline が出力されないためです。

とにかく、どんな助けでも大歓迎です。

4

3 に答える 3

2

コードをより管理しやすくするため、ファイルを 1 か所だけで読み取ることをお勧めします。たぶん、このようなものがうまくいくかもしれません:

prevline = NULL;
count = 1;
while ((thisline = readline(stream)) != NULL) // will stay in the loop for as long as it reads from file
{
    if (prevline == NULL)
    { // this is the first read from file
         prevline = thisline;
         continue;

    }

    if (strcmp(thisline, prevline) == 0)
    {
         count++;
    } else // found a different line
         if (count > 1) // but after I already counted several identical
         {    // so I will print the line
                printUniq(prevline, cflag, dflag, uflag, count);
                count = 1;
         }
    free(prevline);
    prevline = thisline;
}
if (count > 1) and (prevline != NULL)
{
     printUniq(prevline, cflag, dflag, uflag, count);
}
free(prevline);
于 2012-04-07T21:42:14.647 に答える
1

ループの条件としてを使用し、一度に1(thisLine = readline()) != NULL行だけ読み取ると、ファイルの最後でループが停止し、thisLine が有効な場合にのみループの本体に入ることができます。

ループ外で prevLine を読み取るか、ループ内で前の行を処理しないかのいずれかです。

if ((thisLine = readline()) != NULL) {
    char* prevLine = thisLine;                // got one line
    while ((thisLine = readline()) != NULL) {
       if (strcmp(...) == 0) {
           ...
       } else {
           ...
       }
       ...
    }
    ... deal with prev_line, no need for if because it *must* have been read.
}

prevLine = NULL;
while ((thisLine = readline()) != NULL) {
    if (prevLine == NULL) { // first line?
       ...
    } else if (strcmp(...) == 0) {
       ...
    } else {
       ...
    }
       ...
    prev_line = this_line
}
if (prev_line != NULL) {
   ...
} else {          // only one line in the file?
   ...
}

ループの外側の 1 行を処理すると、最初のアプローチがより簡単になります。その流れは私には非常に明確に思えます。1行ありますか?セカンドラインはありますか?さて、ユニークさには意味があります...

2 番目のアプローチでは、ループ内で 1 行を処理するということは、保守開発者がすべての入力行の最初の行のテストを確認することを意味します。

ファイルの最後の 2 行以上が繰り返される可能性があり、その場合は printUnique も呼び出す必要があるため、ループの後のコードが必要です。

また、1行のファイルロジックはループの後にあり(これはあまり明確ではありませんが、IMHO)、mreロジックが必要になります。このロジックは、プログラムがカウント付きの すべてuniqの行を印刷するなどの他の機能をエミュレートすることを意図している場合に必要です。

2 番目のアプローチの明らかな利点は、ファイルを 1 か所で読み取ることであり、これは一般的に優れた方法です。私見ですが、readline が適切に記述されていれば、大した問題ではありません。

要約: 最初のアプローチは必要なロジックが少なく、イベントの順序がより明示的であるため、理解しやすいです。2 番目はファイルを 1 か所で読み取りますが、最後の繰り返しグループをループの外で処理する必要があるため、さらに長くなります。またuniq、一般的にプログラムされている場合は、より論理的です。

注: これらのフローはどちらも機能します。

于 2012-04-07T21:15:49.537 に答える
0

Mihai による提案は、while ループの代わりに for() ループを使用することでさらに簡素化でき、continue ステートメント (ほとんど) を使用することで、ネストされた条件と重複したロジックを回避できます。

dupstate = 0; uniqcount = 0; totdup = 0; linenum = 0;
for (prevline=NULL; thisline=readline(stream); free(prevline),prevline=thisline) {
{
    linenum++;
    if (!prevline || strcmp(thisline, prevline))
    {
         uniqcount++; dupstate = 0;
         printUniq(thisline, cflag, dflag, uflag, uniqcount);
         continue;
    }
    totdup++;

    if (!dupstate++) /* only the first dup is reported */
    {    
         printDup(thisline, cflag, dflag, uflag, totdup); 
    }
 }

 free(prevline);
于 2012-04-08T11:48:06.607 に答える