2016-11-04 14 views
3

私は、2つの文字列を取り、それらの編集距離行列を埋め込むプログラムを作成しようとしています。私をひっくり返しているのは、2番目の文字列入力の場合、2番目の入力をスキップしていることです。私はgetch()でバッファをクリアしようとしましたが、うまくいきませんでした。私もscanf()に切り替えることを試みましたが、その結果いくつかのクラッシュが発生しました。助けてください!編集距離行列

コード:fgets

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

int min(int a, int b, int c){ 
    if(a > b && a > c) 
     return a; 
    else if(b > a && b > c) 
     return b; 
    else 
     return c; 
} 

int main(){ 

    // allocate size for strings 
    int i, j; 
    char *input1 = (char*)malloc(sizeof(char)*100); 
    char *input2 = (char*)malloc(sizeof(char)*100); 

    // ask for input 
    printf("Enter the first string: "); 
    fgets(input1, sizeof(input1), stdin); 
    printf("\nEnter the second string: "); 
    fgets(input2, sizeof(input2), stdin); 

    // make matrix 
    int len1 = sizeof(input1), len2 = sizeof(input2); 
    int c[len1 + 1][len2 + 1]; 

    // set up input 2 length 
    for(i = 0; i < len2 + 1; i++){ 
     c[0][i] = i; 
    } 

    // set up input 1 length 
    for(i = 0; i < len1 + 1; i++){ 
     c[i][0] = i; 
    } 

    // fill in the rest of the matrix 
    for(i = 1; i < len1; i++){ 
     for(j = 1; j < len2; j++){ 
      if(input1[i] == input2[j]) // if the first letters are equal make the diagonal equal to the last 
       c[i][j] = c[i - 1][j - 1]; 
      else 
       c[i][j] = 1 + min(c[i - 1][j - 1], c[i - 1][j], c[i][j - 1]); 
     } 
    } 

    // print the matrix 
    printf("\n"); 
    for(j = 0; j < len2; j++){ 
     for(i = 0; i < len1; i++){ 
      printf("| %d", c[i][j]); 
     } 
     printf("\n"); 
    } 

    return 1; 
} 
+1

「\ n」はウル第二のfgetsは、2行目をつかむことができない理由は、まだバッファに残っている、つまり入力の。 – Mox

+2

代わりにchar1 [100]を使ってみましたか? – brijs

+1

sizeof(input1)の使用が間違っていると、u100が返されず、代わりにuaのサイズが1になります。 – Mox

答えて

1

スティック。他の人が指摘したように

、でもlen1len2が間違っている設定する際sizeofを使用して、fgets正しいの内部sizeofを行い、その変更、で、代わりにchar *input1 = malloc(...)

char input1[100]を使用しかし。有効な文字が10文字であっても(残りの文字は未定義/ランダム)、の全体のバッファを100に処理します。

実際に有効な長さを得るには、strlenと改行が必要です。

ここで変更されたコードは、[無償スタイルのクリーンアップをご容赦ください]です。

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

int 
min(int a, int b, int c) 
{ 
    if (a > b && a > c) 
     return a; 
    if (b > a && b > c) 
     return b; 
    return c; 
} 

int 
main(void) 
{ 

    // allocate size for strings 
    int i; 
    int j; 
    char input1[100]; 
    char input2[100]; 

    // ask for input 
    printf("Enter the first string: "); 
    fgets(input1, sizeof(input1), stdin); 
    int len1 = strlen(input1); 
    if (input1[len1 - 1] == '\n') { 
     input1[len1 - 1] = 0; 
     --len1; 
    } 

    printf("\nEnter the second string: "); 
    fgets(input2, sizeof(input2), stdin); 
    int len2 = strlen(input2); 
    if (input2[len2 - 1] == '\n') { 
     input2[len2 - 1] = 0; 
     --len2; 
    } 

    // make matrix 
    int c[len1 + 1][len2 + 1]; 

    // set up input 2 length 
    for (i = 0; i < len2 + 1; i++) { 
     c[0][i] = i; 
    } 

    // set up input 1 length 
    for (i = 0; i < len1 + 1; i++) { 
     c[i][0] = i; 
    } 

    // fill in the rest of the matrix 
    for (i = 1; i < len1; i++) { 
     for (j = 1; j < len2; j++) { 
      // if the 1st letters are equal make the diagonal equal to the last 
      if (input1[i] == input2[j]) 
       c[i][j] = c[i - 1][j - 1]; 
      else 
       c[i][j] = 1 + min(c[i - 1][j - 1], c[i - 1][j], c[i][j - 1]); 
     } 
    } 

    // print the matrix 
    printf("\n"); 
    for (j = 0; j < len2; j++) { 
     for (i = 0; i < len1; i++) { 
      printf("| %d", c[i][j]); 
     } 
     printf("\n"); 
    } 

    return 1; 
} 

UPDATE:私はあなたが何を意味するか見

オーケー甘いです!私がmallocを使用しようとしていた理由は、100x100の空白のサイズを印刷しなければならない行列を作らないようにするためでした。固定サイズinput1又はmalloc EDどれかで

fgetsのみ入力サイズにそれを充填するには、[必要に応じて、第二引数にクリップ】入力されました。しかし、ではなく、は、バッファの残りの部分をのいずれかで埋め込みます.(たとえば、右側のスペース)。内容 doは、入力から読み込まれた最後のcharの後のEOS [end-of-string]文字[バイナリ0x00]を追加します[通常は改行です]。したがって

、入力文字列がある場合:abcdef\n、[strlenから得られる]の長さは7であり、入力が[7] 0x00であろう、そしてinput1[99]スルーinput1[8]は不定/ランダム/予測不可能な値とないスペースを有することになります。

改行文字は非常に有用ではないので、後で処理する前に切り捨てられることがよくあります。たとえば、小さなフレーズの編集距離を計算するときはあまり関係ありません。

strlen()を使用すると、配列内の文字数がカウントされるだけですか、それともすべての空白も含まれますか?

私は前述したように、fgets最後ないパッドの文字列をして、そう、心配することはありません。それはあなたが望む/期待することをするでしょう。

strlenは、[ではなく、EOSターミネータ文字(すなわちゼロ)を含むまでの文字列をカウントします。これらの文字の一部が空白になる場合、はでカウントされます。これは私たちが望むものです。

は、以下フレーズのいずれか2つの間の編集距離計算検討:各場合において

quick brown fox jumped over the lazy dogs 
the quick brown fox jumped over lazy dogs 
quick brown fox jumps over the lazy dog 

を、我々はstrlenの長さの計算に[内部/埋め込み]スペースを含めるなので、フレーズの編集距離を計算するのに完全に有効です。


mallocのための有効な使い方があります:データの量がスタックに収まるように大きすぎるとき。ほとんどのシステムにはデフォルトの制限があります(例えば、Linuxでは8 MBです)。

たちは、[ファイルから読み込む] 2つの章のための編集距離を計算して、我々は(例えば)を持っているだろうと仮定します。

char input1[50000]; 
char input2[50000]; 

上記収まるだろうが、cマトリックスは、スタックオーバーフローを引き起こします:

int c[50000][50000]; 

50000 * 50000 * 4(約9.3 GB)です。

したがって、このすべてのデータを収めるには、ヒープにデータを割り当てる必要があります。 をcにすることは可能ですが、2D行列アクセスを維持するには、関数を作成してcへのポインタを渡す必要があります。

だから、ここ任意の大きなサイズの入力を受け取り修正版です:

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

#define sysfault(_fmt...) \ 
    do { \ 
     fprintf(stderr,_fmt); \ 
     exit(1); \ 
    } while (0) 

#define C(y,x)  c[((y) * (len2 + 1)) + (x)] 

long 
min(long a, long b, long c) 
{ 
    if (a > b && a > c) 
     return a; 
    if (b > a && b > c) 
     return b; 
    return c; 
} 

char * 
input(const char *prompt,long *lenp,const char *file) 
{ 
    FILE *fp; 
    char *lhs; 
    int chr; 
    long siz; 
    long len; 

    if (file != NULL) 
     fp = fopen(file,"r"); 
    else { 
     fp = stdin; 
     printf("Enter %s string: ",prompt); 
     fflush(stdout); 
    } 

    lhs = NULL; 
    siz = 0; 
    len = 0; 

    while (1) { 
     chr = fgetc(fp); 
     if (chr == EOF) 
      break; 

     if ((chr == '\n') && (file == NULL)) 
      break; 

     // grow the character array 
     if ((len + 1) >= siz) { 
      siz += 100; 
      lhs = realloc(lhs,siz); 
      if (lhs == NULL) 
       sysfault("input: realloc failure -- %s\n",strerror(errno)); 
     } 

     lhs[len] = chr; 
     len += 1; 
    } 

    if (file != NULL) 
     fclose(fp); 

    if (lhs == NULL) 
     sysfault("input: premature EOF\n"); 

    // add the EOS 
    lhs[len] = 0; 

    // return the length to the caller 
    *lenp = len; 

    return lhs; 
} 

int 
main(int argc,char **argv) 
{ 
    long i; 
    long j; 
    char *input1; 
    long len1; 
    char *input2; 
    long len2; 
    long *c; 

    --argc; 
    ++argv; 

    switch (argc) { 
    case 2: 
     input1 = input("first",&len1,argv[0]); 
     input2 = input("second",&len2,argv[1]); 
     break; 
    default: 
     input1 = input("first",&len1,NULL); 
     input2 = input("second",&len2,NULL); 
     break; 
    } 

    // make matrix 
    c = malloc(sizeof(*c) * (len1 + 1) * (len2 + 1)); 
    if (c == NULL) 
     sysfault("main: malloc failure -- %s\n",strerror(errno)); 

    // set up input 2 length 
    for (i = 0; i < len2 + 1; i++) { 
     C(0,i) = i; 
    } 

    // set up input 1 length 
    for (i = 0; i < len1 + 1; i++) { 
     C(i,0) = i; 
    } 

    // fill in the rest of the matrix 
    for (i = 1; i < len1; i++) { 
     for (j = 1; j < len2; j++) { 
      // if the 1st letters are equal make the diagonal equal to the last 
      if (input1[i] == input2[j]) 
       C(i,j) = C(i - 1,j - 1); 
      else 
       C(i,j) = 1 + min(C(i - 1,j - 1), C(i - 1,j), C(i,j - 1)); 
     } 
    } 

    // print the matrix 
    printf("\n"); 
    for (j = 0; j < len2; j++) { 
     for (i = 0; i < len1; i++) { 
      printf("| %ld", C(i,j)); 
     } 
     printf("\n"); 
    } 

    return 1; 
} 
関連する問題