5

K&Rの演習1-18に進みます

入力の各行から末尾の空白とタブを削除し、完全に空白の行を削除するプログラムを作成します。

これは私がこれまでに思いついたものです

#include <stdio.h>

#define MAXLINE 1000

int getline(char line[], int maxline);
void copy(char to[], char from[]);

int main () {

    int len;
    char line[MAXLINE];

    while (getline(line, MAXLINE) > 0) {
            printf("%s", line);
    }
    return 0;
}


int getline(char s[], int lim) {
    int c, i, lastNonBlankIndex;
    lastNonBlankIndex = 0;

    for (i=0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {

        if (c != ' ' && c != '\t') {
            lastNonBlankIndex = i + 1;

        } 

        s[i] = c;
    }

    if (i != lastNonBlankIndex) {
        i = lastNonBlankIndex;
        c = '\n';
    }

    if (c == '\n') {
        s[i] = c;   
        ++i;
    }
    s[i] = '\0';
    return i;
}

行に空白またはタブしかない場合に何を返す必要があるかわからなかったため、2番目の部分は難しいように聞こえました。結局のところ、0を返すと、getline()呼び出しが停止します。#defineこれは、などのを設定する必要がある場所でしょうかALL_BLANKS

とにかく、実際の主な質問に対して、これは行から末尾の空白とタブを削除する正しい方法ですか?いくつかの入力を実行しましたが、うまくいったようです。ただし、改行を含むテキストをコピーしてCLに貼り付けると、すべてがつなぎ合わされて表示されます。また、CLに行を入力してEnterキーを押すと、自動的に印刷されます。行の配列を作成し、完了したらループして印刷する必要がありますか?

4

5 に答える 5

5

コードは正しいように見えますが、行を読み取る操作とstdin末尾の空白の行を削除する操作(デカップリング)を分離した方がよいと思います。そうすれば、本から変更されていないものを使用できgetline(コードの再利用)、0を返すときに停止する問題は発生しません。

また、他のソリューションに興味がある場合は、CLC-wikiにK&R2ソリューションのほぼ完全なリストがあります。

#include <stdio.h>
#define MAXLINE 1024

int getline(char s[], int lim);

main()
{
    int i, len;
    char line[MAXLINE];

    while ((len = getline(line, MAXLINE)) > 0) {
        i = len - 2;
        while (i >= 0 && (line[i] == ' ' || line[i] == '\t'))
            --i;
        if (i >= 0) {
            line[i+1] = '\n';
            line[i+2] = '\0';
            printf("%s", line);
        }
    }
    return 0;
}

これは、私が少し前に書いたカテゴリ1のソリューションです。getline本の28ページにある通りです。空白の削除を別の関数に入れる方が良いかもしれませんが、rstripこれは読者の練習問題として残しておきます。

于 2010-08-12T13:05:41.530 に答える
0

あなたの基本的なデザインは健全です。あなたがしたように、あなたがそれを構築したらすぐにストリップされた行を印刷することはより良いです、それであなたのプログラムはファイル全体ではなく一度に1行だけをメモリに保持する必要があります。

コードに小さな問題があります。質問の2番目の部分(「空白行を完全に削除する」)が実装されていません。これは、常に'\n'文字列の最後にaを付けるためです。これは簡単に修正できますが、空白行はファイルの終わりを示していないため、呼び出し元にゼロ以外の値を返す必要があることに注意してください。

于 2010-08-12T13:17:08.697 に答える
0

getlineエラーが発生した場合、またはEOFに達した場合は、-1(通常は負の値)を返す必要があります。次に、ループ条件は、それが何か>= 0を返し、それでも長さ0の行を許可することを確認できます。

for (i=0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {

条件付きループ内に割り当てを含めることはほとんどありません。読みにくいので、それを回避するために10行のコードを追加したいと思います。特に複雑な条件文での使用は控えたいと思います。

int i = 0;

while (i < lim) {
   c = getchar();
   if (c == EOF || c == '\n') {
       break;
   }
   line[i] = (char)c;
   i++;
}
line[i] = '\0'; // Null terminate the string

このコードは一行で読む必要があります。行の読み込みと末尾の空白の削除を分離します。行を読み込んだ後、その長さがわかったので、文字列の終わりから逆方向に簡単に作業して、行をnullで終了した場所の空白を削除できます。基本的に、ストリングを成長させ、成長が終了した後、それを剪定します。

于 2010-08-12T15:22:34.270 に答える
0

これが私がやった方法です。

#include <stdio.h>
#define MAXLINE 1000

#define IN 1
#define OUT 0

int state = OUT;

int getline(char s[], int lim);
void copy(char to[], char from[]);

int main(void)
{
int lenght;
int max = 0;
char line[MAXLINE];
char longest[MAXLINE];

while ((lenght = getline(line, MAXLINE)) > 0)
    if (lenght > max)
    {
        max = lenght;
        copy(longest, line);
    }
if (max > 0)
    printf("\n%s\n", longest);

    return 0;

    }
   int getline(char s[], int lim)
   {
   int i, c;
   for (i = 0; i < lim - 1 && ((c = getchar()) != EOF) && (c != '\n'); i++)
   {


    if (state == IN && c != ' ' && c != '\t')
    {
        s[i] = ' ';
        i++;
        state = OUT;
    }
    if (s[0] == ' ')
    {
        s[0] = '\b';
    }


    s[i] = c;


    if (c == ' ' || c == '\t')
    {
        i--;
        state = IN;
    }
}
if (c == '\n')
{
    s[i] = c;
    i++;
}
s[i] = '\0';

return i;
 }

void copy(char to[], char from[])
{
int i = 0;
while ((to[i] = from[i]) != '\0')
    i++;
}
于 2015-04-22T21:47:10.797 に答える
-1
#include <stdio.h>

#define MAXLINE 1000

size_t getline(char *s,size_t lim)
{
  if( fgets(s,lim,stdin) )
  {
    while( *s && strchr(" \t\n",s[strlen(s)-1]) )
      s[strlen(s)-1]=0;
    return strlen(s);
  }
  return 0;
}

main()
{
    int len;
    char line[MAXLINE];

    while (getline(line,sizeof line)) {
            printf("%s", line);
    }
    return 0;
}
于 2010-08-12T13:41:48.617 に答える