2017-08-28 25 views
2

私は2-Dの文字配列文字列の並べ替え

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

void swap(char *,char *); 

void main() { 
    char a[20][20]; 
    int Pass = 0, i = 0, j = 0, n; 

    printf("\nHow many elements you want to sort ? >> "); 
    scanf("%d", &n); 
    printf("\n\nEnter the elements to be sorted :\n"); 
    for (i = 0; i < n; i++) 
     scanf("%s", a[i]); 
    for (Pass = 1; Pass < n; Pass++) { 
     for (j = 0; j < n - Pass; j++) 
      if (strcmp(a[j], a[j + 1]) < 0) 
       swap(a[j], a[j + 1]); 
     printf("\n\nPass = %d\n", Pass); 
     for (i = 0; i < n; i++) 
      printf(" %s ", a[i]); 
    } 
} 

void swap(char *a, char *b) { 
    char *t; 
    *t = *a; 
    *a = *b; 
    *b = *t; 
} 

でソートされた文字列を取得するには、次のコードを書かれている。しかし、私はセグメンテーションが発生しないのはなぜ

How many elements you want to sort ? >> 5 
Enter the elements to be sorted : 
1 2 3 4 5 
Pass = 1 
2 3 4 5 1 
Pass = 2 
3 4 5 2 1 
Pass = 3 
4 5 3 2 1 
Pass = 4 
Segmentation fault (core dumped) 

として出力を得ます不具合?

+0

メインは 'int型を返す必要があります' –

+0

あなたの' swap'機能が間違っています。 1) 'char * t; * t = * a; ':初期化されていない変数を使用しています。 2)交換する必要があるのは、ポインタ(または1つの 'char')ではなく配列です。 – BLUEPIXY

+0

時間を節約し、すべてのコンパイラの警告を有効にします。 'char * t; * t = * a; '初期化の前に' t 'が使用されていることを警告する必要があります。 – chux

答えて

1

エントリポイントmain

int main() 

または(引数を持つ)

int main(int argc, char* argv[]) 

として定義されるべきである(私の代わりに文字配列の整数配列を使用する場合、同じコードが正常に動作します)いくつかの値を返すこともあれば返さないこともあります。あなたがundefined behaviorの原因となる初期化されていないポインタにアクセスしているswap機能で


。ポインタを使う必要はありません。プレーンcharを使用してください。また

void swap(char *a,char *b) 
{ 
    char t; 
    t=*a; 
    *a=*b; 
    *b=t; 
} 

バッファオーバーフローを避けるために、あなたは入力バッファから

scanf("%19s",a[i]); 

をスキャンし、スキャンが成功したかどうかを確認するためにどのように多くの文字scanf()を教えてください。

正しい結果が得られるはずです。 Here is fixed code.

+0

C仕様は、UBではなく他の実装が定義されているので、受け入れ可能な 'main()'シグネチャの限られたサンプルに同意しません。 – chux

+0

情報ありがとうございます。誰かが私に「ボイド・メイン」にUBを持っていると言ったとき、それが嘘の中に生きているからです。 –

+2

@FilipKočica 'void main()'のほとんどはとにかく動作します。ここの問題は、明らかに初期化されていないポインタでした。 –

1

あなたはswapメソッドであなたのポインタを台無しにしています。現在、あなたがやっている:

void swap(char *a,char *b) 
{ 
    char *t; 
    *t=*a; 
    *a=*b; 
    *b=*t; 
} 

をトンが初期化されていない文字ポインタであるため、この行*t = *aは、SEGVのための非常に有望な候補であると思われます。私はあなたのコードをgdbで実行し、gdbも同じことを言った:

Reading symbols from a.out...done. 
(gdb) run 
Starting program: /home/rohan/Documents/src/a.out 

How many elements you want to sort ? >> 5 


Enter the elements to be sorted : 
1 2 3 4 5 

Program received signal SIGSEGV, Segmentation fault. 
0x0000555555554a21 in swap (a=0x7fffffffdce0 "1", b=0x7fffffffdcf4 "2") at testBubble.c:26 
26  *t=*a; 
(gdb) 

ポインタ変数としてtは必要ありません。これは単なるスワッピングに必要な一時変数です。だから、私の場合には、セグメンテーションフォールトを固定し、このようなあなたの方法は、変更:

void swap(char *a,char *b) 
{ 
    char t; 
    t=*a; 
    *a=*b; 
    *b=t; 
} 
0

スワップ機能が正しくありません:あなたのケースでセグメンテーションフォールトを:あなたは未定義の動作を引き起こし、初期化されていないポインタtを逆参照されています。

代わりcharとしてtを定義する必要があります。

void swap(char *a, char *b) { 
    char t; 
    t = *a; 
    *a = *b; 
    *b = t; 
} 

しかし、これは単一の文字と言葉のために働くだろう。

void swap(char *a, char *b) { 
    char t[20]; 
    strcpy(t, a); 
    strcpy(a, b); 
    strcpy(b, t); 
} 

と未定義の動作を避けるためにmain機能でいくつかの余分なテストや保護を追加します:、最大19バイトの単語を入れ替え、これを使用するには

int main(void) { 
    char a[20][20]; 
    int Pass = 0, i = 0, j = 0, n; 

    printf("\nHow many elements you want to sort ? >> "); 
    if (scanf("%d", &n) != 1 || n < 0 || n > 20) 
     return 1; 
    printf("\n\nEnter the elements to be sorted :\n"); 
    for (i = 0; i < n; i++) { 
     if (scanf("%19s", a[i]) != 1) 
      return 1; 
    } 
    for (Pass = 1; Pass < n; Pass++) { 
     for (j = 0; j < n - Pass; j++) { 
      if (strcmp(a[j], a[j + 1]) < 0) 
       swap(a[j], a[j + 1]); 
     } 
     printf("\nPass = %d\n", Pass); 
     for (i = 0; i < n; i++) 
      printf(" %s", a[i]); 
     printf("\n"); 
    } 
    return 0; 
} 
関連する問題