2016-08-06 11 views
0

私は、1文字のテキスト文字列の引数を128文字以下の任意の数だけ使用するプログラムを作成しようとしています。プログラムはstdinからstdoutにテキストをコピーしますが、入力に表示されている単語のいずれかが "CENSORED"という単語に置き換えられます。このコードがセグメンテーションフォールトを与えているのはなぜですか?

例:

Said Hamlet to Ophelia, 
I'll draw a sketch of thee, 
What kind of pencil shall I use? 
2B or not 2B? 

プログラムは、この実行する必要があります:

./censor Ophelia < poem.txt 
Said Hamlet to CENSORED, 
I'll draw a sketch of thee, 
What kind of pencil shall I use? 
2B or not 2B? 

をここに私のコードです:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
int main(int argc, char *argv[]) 
{ 
    char lines[200][200]; 
    int numLines=0,i,j; 
    int nbytes = 128; 
    int bytes_read=0; 
    char *my_string; 
    char * pch; 
    //reading from stdin 
    while(stdin) 
    { 
    my_string=(char *) malloc (nbytes + 1); 
    bytes_read = getline (&my_string, &nbytes, stdin); 
    strcpy(lines[numLines++],my_string); 
    } 

    //scanning and replacing specified words by "CENSORED" 
    for(i=0;i<argc;i++) 
    { 
     for(j=0;j<numLines;j++) 
     { 
      pch = strstr (lines[j],argv[i]); 
      strncpy (pch,"CENSORED",8); 
     } 
    } 
    //display the result in output screen 
    for(j=0;j<numLines;j++) 
     { 
      printf("\n%s",lines[i]); 
     } 

} 

問題がある 私はpoem.txtと呼ばれるこのファイルを持っていますこれがセグメンテーション違反を与えているが、私は間違いを特定できません。

+0

http://ericlippert.com/2014/03/05/how-to- debug-small-programs/ – Biffen

+0

'argc'と' argv'の定義を見てください。ところで、あなたはsegフォルトが発生した場所を詳しく述べるべきです –

+1

'while(stdin)'あなたはそれが何をすると思いますか? 'stdin'はいつまでも0になるのですか? – artm

答えて

2

ヒットしたヒットが長くても短くても適切に上書きされているわけではありません。端末に上書きされる可能性があります(セグメンテーションフォールトにつながる可能性があります。\0)。また、各行に対してそれぞれのコマンドラインワードを1回だけチェックするので、ダブルヒットを逃したように見えます。最後に、すべての行を格納することでこれをより複雑にしました。行は他の行に影響を与えません。そうそう

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

#define REPLACEMENT "CENSORED" 
#define BUFFER_SIZE (1024) 

int main(int argc, char *argv[]) 
{ 
    ssize_t bytes_read; 
    char *s, *line = malloc(BUFFER_SIZE); 
    size_t nbytes = BUFFER_SIZE, replacement_length = strlen(REPLACEMENT); 

    // read from stdin 
    while ((bytes_read = getline(&line, &nbytes, stdin)) != -1) 
    { 
     // scanning and replacing specified words 
     for (int i = 1; i < argc; i++) 
     { 
      while ((s = strstr(line, argv[i])) != NULL) 
      { 
       size_t search_length = strlen(argv[i]); 
       size_t tail_length = strlen(s + search_length); 

       (void) memmove(s + replacement_length, s + search_length, tail_length + 1); 
       (void) memcpy(s, REPLACEMENT, replacement_length); 
      } 
     } 

     // display the result in output screen 
     (void) fputs(line, stdout); 
    } 

    free(line); 
} 

、あなたはあなたをmallocで確保するもの無料に忘れてしまった:

はここで、より詳細な置換コードと全体的な単純化されたアプローチです。そして、あなたは

例...あなたの目標の一つとして、プログラムの名前を探している

> ./a.out pencil 2B < poem.txt 
Said Hamlet to Ophelia, 
I'll draw a sketch of thee, 
What kind of CENSORED shall I use? 
CENSORED or not CENSORED? 
+0

'line'の' REPLACEMENT'による 'argv [i]'の置き換えが 'getline'の' line'のデフォルト割り当てを超えないようにして、 'line'の終わりを超えて書くことをどうやって保証しますか? (たとえば、 '' '115' 'chars' 2B ''で' 2B'を 'CENSORED'に置き換えた場合、' 120バイトの '' line'のデフォルト割り当ての終わりを '5'で上書きします)[** GNU glibc iogetdelim.c **](https://sourceware.org/git/?p=glibc.git;a=blob;f=libio/iogetdelim.c;h=50fda58e6832d23391d26d3c64c7b66b11d304c3;hb=release/2.23/masterを参照してください。 ) –

+0

ありがとう@DavidC.Rankin、それは完全なものだった。 Cが私を作ることを嬉しく思うもの。私は、この問題のために推定されたOPのサイズの5倍の静的バッファを割り当てて、最小限のバンデッドを配置しました。一口。 – cdlane

+0

私はあなたの答えが好きです、それは私の目を引く唯一のものでした。よくやった。 (また、各行の長さ+置換によって生じる違いをチェックし、 'getline'で' 'n ''の値を超えるとtmpバッファを割り当てることもできます)。 '' getline'に) –

関連する問題