2017-11-03 9 views
2

1つの単語のすべての可能な組み合わせを置換する関数を作成しようとしていますが、プログラムが置換文字列の複製を作成してしまいます。固定文字列が期待通りに機能しない

この私の作業コードです:

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

char arr[5000] = {0}; 
void swap (char *x, char *y); 
void permute(char *ptr, size_t i, size_t n); 

int main(void){ 
    char str[80] = "MICHI"; 
    size_t len = strlen(str); 

    permute(str, 0, len); 
    printf("%s\n", arr); 
    printf("END\n"); 
} 

void swap (char *x, char *y){ 
    char temp; 
    temp = *x; 
    *x = *y; 
    *y = temp; 
} 

void permute(char *ptr, size_t i, size_t n){ 
    size_t j; 
    if (i == n){ 
     strcat (arr, ptr); 
     strcat (arr, "\n"); 
    }else{ 
     for (j = i; j <= n; j++) 
     { 

      swap((ptr + i), (ptr + j)); 
      permute(ptr, i+1, n); 
      swap((ptr + i), (ptr + j)); 
     } 
    } 
} 

そして、ここでは、出力されます。

ABC 
AB 
ACB 
AC 
A 
A 
BAC 
BA 
BCA 
BC 
B 
B 
CBA 
CB 
CAB 
CA 
C 
C 







END 

期待される成果は次のようになります。

ABC 
AB 
ACB 
AC 
A 
BAC 
BA 
BCA 
BC 
B 
CBA 
CB 
CAB 
CA 
c 

プログラムは、重複の多くを作成し、 2つ目のNew Linesも作成します。関数はpermuteで

IMCHI 
IMCH 
IMCIH 
IMCI 
+1

[小さなプログラムをデバッグする方法](https://ericlippert.com/2014/03/05/how- to-debug-small-programs /) – alk

+0

注文には問題がありますか? – klutt

+1

MICHIの2つの「I」のように、入力に重複した文字が含まれている場合は、重複する置換が必要です。あなたが並べ替えると、2つの「私」は異なるエンティティとみなされます。あるいは、組み合わせ(つまり、ユニークな順列)を欲しいだけですか? –

答えて

3

あなたの順列で文字列の終端\0を含めています。

lineの内部状態は次のとおりです。

ABC\0 
AB\0C 
ACB\0 
AC\0B 
A\0CB 
A\0BC 
BAC\0 
BA\0C 
BCA\0 
BC\0A 
B\0AC 
B\0CA 
CBA\0 
CB\0A 
CAB\0 
CA\0B 
C\0AB 
C\0BA 
\0ABC 
\0ACB 
\0BAC 
\0BCA 
\0CAB 
\0CBA 

printf0を終了するまで印刷されます。

修正する方法の1つは、ループの制限を1つ減らし、\0を置換から除外することです。 i番目の文字を除いた部分文字列を作成し、その部分文字列に対してpermuteを呼び出す2番目のループを追加する必要があります。

もう1つの方法は、ブランチが\0を超えたら置換を停止することです。

EDIT:ここ

は順列が前のものと同一である場合に出力を抑制することにより、「並び替え停止」に、第2の提案の実装です。

void permute(char *ptr, size_t i, size_t n){ 
    size_t j; 
    static char prev[80] = ""; 
    if (i == n){ 
     if (strcmp(prev, ptr)) { 
      strcat (arr, ptr); 
      strcat (arr, "\n"); 
      strcpy(prev, ptr); 
     } 
    }else{ 
     for (j = i; j <= n; j++) 
     { 

      swap((ptr + i), (ptr + j)); 
      permute(ptr, i+1, n); 
      swap((ptr + i), (ptr + j)); 
     } 
    } 
} 
+0

はい、私は何とか私の質問から期待される出力が必要です。 – Michi

+0

@Michiこれはうまくいくようです。 1つの文字が複数回出現すると重複が出力されることに注意してください。 –

+0

これは私が必要なものです。今問題がどこにあるのか分かります。 +1。あなたのコードは 'M'を出力しません(入力が' MICHI 'ならば)。しかし私はそれを修正します。 – Michi

2

あなたのループは、文字列のNULバイトが含まれています

はINPUTは、たとえばMICHIのためであれば、私はこのような重複を得ることに気づきました。 j <= nj < nに変更するだけです。このよう :

void permute(char *ptr, size_t i, size_t n){ 
    size_t j; 
    if (i == n){ 
     strcat (arr, ptr); 
     strcat (arr, "\n"); 
    }else{ 
     for (j = i; j < n; j++) 
     { 

      swap((ptr + i), (ptr + j)); 
      permute(ptr, i+1, n); 
      swap((ptr + i), (ptr + j)); 
     } 
    } 
} 
+0

良いスタート。これは、長さnのすべての順列を出力します。より短い部分文字列の順列はどうですか? –

+0

あなたのコードは私の希望する出力を変更します。 [これは私が得るものです](https://pastebin.com/raw/ywcTLSmV)。私の質問からの私の予想される出力をチェックしてください。 – Michi

+0

投稿する前にコードを実行してください。これは動作しません。 – klutt

関連する問題