0

K&Rの「TheCプログラミング言語」を購入し、その中で演習を行うために最善を尽くしています(この本をご存知の場合は、演習1.20です)。

このプログラムは、キーボードから入力を受け取り、タブ文字をTABLENGTHで指定された適切な量のスペースに変換することを目的としています。

コードは以下のとおりです。実行しようとすると、セグメンテーション違反が発生します。

detab.c:

#include <stdio.h>
#define TABLENGTH 8
#define MAXLINE 1000

int getline(char line[], int len);

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

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

}

int getline(char line[], int len)
{
  int i = 0;
  int c;

  for(i = 0; i < (MAXLINE - 1) &&
   ((c = getchar()) != EOF && c != '\n'); i++) {
   // if c is tab, replace with spaces
    if(c == '\t') {
        while((TABLENGTH - (i % TABLENGTH)) != 0) {
            line[i] = ' ';
            i++;
        }
        i--;
        continue;
    }
   }
   line[i] = c;
  }
  if(c == '\n') {
   line[i] = c;
   i++;
  }

  line[i] = '\0';
  return i;
}
4

2 に答える 2

6

古典的な初心者の間違い1A:に収まらないため、を返しgetchar()ます。intEOFchar

また、タブを見つけるとiスペース挿入ループが増加し、次にforループが再び増加iして文字列に奇妙さが残るため、インデックス作成の問題があると思います。これにより、バッファオーバーフローが発生し、クラッシュが発生する可能性があります。

iスペース挿入ループはに対してチェックしないことに注意してくださいMAXLINE

于 2012-06-19T08:56:29.373 に答える
2

への呼び出しprintf

printf("%s");

セグメンテーション違反の原因である可能性があります。charスタック上の任意のデータを、0で終了する配列へのポインタとして解釈しようとします。

'\t'セグメンテーション違反への特定の方法は、 :の場合のループです。

if(c == '\t') {
    while((TABLENGTH - (i % TABLENGTH)) != 0) {
        line[i] = ' ';
        i++;
    }
    i--;
    continue;
}

i >= 0TABLENGTH > 0、は常に持っているので0 <= (i % TABLENGTH) < TABLENGTH、タブに遭遇するたびにline、割り当てられたスペースを超えてスペースを追加する無限ループに入ります。これにより、遅かれ早かれ、プロセスメモリの外部または読み取りにスペースを書き込もうとしたときにセグメンテーション違反が発生します。メモリの一部のみ。簡単ですが、あまりエレガントではありませんが、ループを次のように変更しています。

if (c == '\t') {
    do {
        line[i] = ' ';
        ++i;
    }while(((TABLENGTH - (i % TABLENGTH)) % TABLENGTH) != 0);
    --i;
    continue;
}

別の修正は、別のカウンターまたはswitchフォールスルーを使用することです。

于 2012-06-19T09:04:50.503 に答える