2009-04-10 10 views
10

私は第1言語としてk & rからC言語を学んでいます。この演習が正しい方法で解決されていると思ったら、あなたが思ったほど完全ではないと思います私はCの権利を習っていることを知っています。K&R第1章 - 演習22の解決策、あなたはどう思いますか?

おかげ

/* 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; 
} 
+0

あなた自身の宿題を解決する必要があるかもしれません。 ssignments? –

+1

@Phil:私は彼がやったと思う...またはコードの巨大なブロックが浮かび上がった。 – Shog9

+0

@ Phil、彼らが努力している限り、宿題に尋ねる人々には十分な先例がある。そして、あなたはそれが宿題であることを本当に知っていない、@ SVRは自己教えるかもしれない。これは、ちょうど切り取って宿題の質問をそのまま貼り付けた仲間よりも確かに優れています。 – paxdiablo

答えて

0

明白な問題は、あなたが静的に「配列」を割り当て、それへのアクセス中に、インデックスの制限をチェックしたことがないということです。バッファオーバーフローが起こるのを待っています。実際には、最初のループ内でi変数をリセットすることはありません。そのため、プログラムがどのように動作するのか分かりません。ワードラップを印刷する前に、完全な入力をメモリに保存しているようですね?

提案:2つのループを結合して、完了した各行の出力を印刷します。次に、次の行の配列を再利用することができます。

ああ、より良い変数名といくつかのコメント。私は「DELIM」が何をすべきか分かりません。

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 

のためのいくつかの擬似コードは、それが後半だと私はちょうどベルトを持っていたので、欠陥があるかもしれませんが、それは一般的な考えを示しています - バッファをロードし、の内容をコピー可能なブレークポイントを追跡しながら、バッファをラインバッファにロードします。最後に近づくと、ブレークポイントを使用します。

7

私はrigthトラック上のあなたの確信しているが、読みやすくするためにいくつかのポインタ:あなたは必然的なこと

  • を拒否した場合、変数を適切かつ少なくとも

    • コメント自分のもの
    • 名前は説明を与えますあなたが使用している場合は1行、使用しない場合はいくつかの行があります。 (私見では、常に{使用}ので、それをより読みます)
    • forループの最後でのif文には良い私見ません
    
        if(array[0] != NEWLINE) 
        { 
         printf("%c", array[line]); 
        } 
    
  • +0

    @Mafti:私はあなたの提案に従います。ちょっとエレガントに、私がそれを掛けたかどうかを知るための最初の草案でした。あなたは最後のfor-loopシーケンスについて正しいですが、おそらく私はそのようなものとして書く方が良いでしょう。 ありがとう –

    2

    のように、改善することができます。

    まず、あなたが求めたことはしません。最後の空白は空白の後に出力行の境界より前に置くことになっていました。あなたのプログラムはそれを遠隔操作しようとしていません。(マージン - 5)文字の後に最初の空白を見つけようとしているようです(5文字はどこから来ましたか?しかし、それはnewls変数を使った操作のためにもそうしません。また、次のようになります。

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

    は、ループ全体で決して変化しない条件をチェックするため、間違っている可能性があります。

    そして、少なくとも最後のではなく、固定サイズのバッファにファイル全体を格納する2つの理由により、良いではありません:バッファがあっても、大きなファイル

  • にオーバーフローするためにバインドされ

    • それは決してあふれないでしょう。メモリ内にあるギガバイトのファイルを25文字のチャンクに分割するだけです。

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

    • プロセスをファイルのライン・バイ・ライン(つまり出力ライン)
    • ストア最大出力ラインにあなたがよ文字の
    • 検索を保持するのに十分な大きさのバッファ内の行バッファ内でブレークする
    • それを印刷します(ヒント: '¥0'で文字列を終了してprintf("%s", ...)で印刷できます)。印刷しなかったものをバッファの先頭にコピーしてから、
  • 関連する問題