10

私は第 1 言語として k&r から C を学んでいます。質問したいのですが、この演習が正しい方法で解決されていると思われる場合は、おそらくあなたが望むほど完全ではないことは承知していますが、ビューが欲しかったので、私はCを正しく学んでいることを知っています.

ありがとう

/* Exercise 1-22. Write a program to "fold" long input lines into two or
 * more shorter lines, after the last non-blank character that occurs
 * before then n-th column of input. Make sure your program does something
 * intelligent with very long lines, and if there are no blanks or tabs
 * before the specified column.
 * 
 * ~svr
 *
 * [NOTE: Unfinished, but functional in a generic capacity]
 * Todo:
 * Handling of spaceless lines
 * Handling of lines consisting entirely of whitespace
 */

#include <stdio.h>
#define FOLD 25
#define MAX 200
#define NEWLINE '\n'
#define BLANK ' '
#define DELIM 5
#define TAB '\t'

int
main(void)
{
    int line  = 0, 
        space = 0,
        newls = 0,
            i = 0, 
            c = 0, 
            j = 0;

    char array[MAX] = {0};

    while((c = getchar()) != EOF) {
        ++line;
        if(c == NEWLINE)
            ++newls;
        if((FOLD - line) < DELIM) {
            if(c == BLANK) {
                if(newls > 0) {
                    c = BLANK;
                    newls = 0;
                }
                else
                    c = NEWLINE;
                line = 0;
            }
        }
        array[i++] = c;
    }
    for(line = 0; line < i; line++) {
        if(array[0] == NEWLINE)
            ;
        else
            printf("%c", array[line]);
    }
    return 0;
}
4

4 に答える 4

7

私はあなたが正しい軌道に乗っていると確信していますが、読みやすさのためのいくつかの指針:

  • あなたのものにコメントする
  • 変数に適切な名前を付け、拒否する場合は少なくとも説明を付けてください
  • 結果として、使用する単一行の場合と使用しない場合があります。(私見、読みやすくするために常に {} を使用してください)
  • 次のように、最後の for ループの if ステートメントの方が優れている場合があります。

    if(array[0] != NEWLINE)  
    {   
        printf("%c", array[line]); 
    }
于 2009-04-10T06:45:05.523 に答える
2

それは私見ではありません。

まず、それはあなたが求められたことをしません。出力行境界の前の非空白の後に最後の空白を見つけることになっていました。あなたのプログラムはリモートでそれをしようとさえしません.(margin - 5)文字の後の最初の空白を見つけようと努力しているようです. ただし、 newls 変数を使用した操作のため、それも行われません。また、これ:

for(line = 0; line < i; line++) {
    if(array[0] == NEWLINE)
        ;
    else
        printf("%c", array[line]);
}

ループ全体で決して変化しない条件をチェックするため、おそらく間違っています。

最後になりましたが、ファイル全体を固定サイズのバッファーに格納することは、次の 2 つの理由から適切ではありません。

  • バッファーは、大きなファイルでオーバーフローするようにバインドされています
  • たとえオーバーフローしないとしても、人々はあなたが保管することを好まないでしょう。25文字のチャンクにカットするためだけに、メモリ内のギガバイトのファイル

もう一度やり直して、アルゴリズムを再考し(コーナーケースを含む)、その後でコーディングを開始する必要があると思います。私はあなたをお勧めします:

  • ファイルを行ごとに処理する (出力行を意味する)
  • 最大の出力行を保持するのに十分な大きさのバッファに行を格納します
  • バッファ内でブレークする文字を検索します
  • 次に、それを印刷します(ヒント:文字列を「\ 0」で終了し、で印刷できprintf("%s", ...)ます)、印刷しなかったものをバッファの先頭にコピーし、そこから続行します
于 2009-04-10T10:38:29.847 に答える
0

明らかな問題は、「配列」を静的に割り当て、アクセス中にインデックス制限をチェックしないことです。発生するのを待っているバッファオーバーフロー。実際、最初のループ内でi変数をリセットすることは決してないので、プログラムがどのように機能するかについて少し混乱しています。単語でラップして印刷する前に、入力全体をメモリに保存しているようですか?

したがって、提案:2つのループをマージし、完了した各行の出力を出力します。その後、次の行でアレイを再利用できます。

ああ、そしてより良い変数名といくつかのコメント。「DELIM」が何をするのかわかりません。

于 2009-04-10T05:58:53.793 に答える
0

(テストなしで)動作するように見えますが、少し複雑に見えます。

これが私の最初の考えの擬似コードです

const int MAXLINE = ??  — maximum line length parameter
int chrIdx = 0 — index of the current character being considered 
int cand = -1  — "candidate index",  Set to a potential break character
char linebuf[bufsiz]
int lineIdx = 0 — index into the output line
char buffer[bufsiz]   — a character buffer
read input into buffer
for ix = 0 to bufsiz -1
do     
   if buffer[ix] == ' ' then
      cand = ix
   fi
   linebuf[lineIdx] = buffer[ix]
   lineIdx += 1
   if lineIdx >= MAXLINE then
      linebuf[cand] = NULL — end the string
      print linebuf
      do something to move remnants to front of line (memmove?)
   fi
 od

遅く、ベルトを持っていたので、欠陥があるかもしれませんが、それは一般的な考え方を示しています。バッファをロードし、バッファの内容をラインバッファにコピーして、可能なブレークポイントを追跡します。終わりに近づいたら、ブレークポイントを使用します。

于 2009-04-10T05:59:58.877 に答える