2016-09-04 16 views
1

私は、このプログラムが列インデックスで文字列の2次元配列をソートしようとしています。文字列配列のソートC

私はこのようなこの2次元配列初期化:

char *str[ROWS][COLS] = {{"Russia", "Boxing", "Mens", "Gold"}, 
         {"America", "Cycling", "Mens", "Gold"}, 
         {"New Zealand", "Swimming", "Womens", "Silver"}, 
         {"India", "Badminton", "Mens", "Bronze"}}; 

をそして私は、最初の列で国の名前を、この配列をソートしたい場合、それはこのようなものになります。

char *str[ROWS][COLS] = {{"America", "Cycling", "Mens", "Gold"}, 
         {"India", "Badminton", "Mens", "Bronze"}}; 
         {"New Zealand", "Swimming", "Womens", "Silver"}, 
         {"Russia", "Boxing", "Mens", "Gold"}}; 

これは私がこれまで行ってきたことであり、ソート方法を除いてほぼ正しいです。私はそれを実装するのに苦労しています。

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

#define ROWS 4 
#define COLS 4 

void print_array(char *str[][COLS]); 
void sort_array(char *str[][COLS], int nrows, int col); 

int 
main(void) { 
    char *str[ROWS][COLS] = {{"Russia", "Boxing", "Mens", "Gold"}, 
          {"America", "Cycling", "Mens", "Gold"}, 
          {"New Zealand", "Swimming", "Womens", "Silver"}, 
          {"India", "Badminton", "Mens", "Bronze"}}; 
    int col; 

    /* array before sorting */ 
    printf("Before: \n"); 
    print_array(str); 

    /*choosing column index to sort by*/ 
    printf("\nChoose which column index you wish to sort by: "); 
    if (scanf("%d", &col) != 1) { 
     printf("Invalid input\n"); 
     exit(EXIT_FAILURE); 
    } 

    sort_array(str, ROWS, col); 

    /* array after sorting */ 
    printf("\nAfter: \n"); 
    print_array(str); 

return 0; 
} 

void 
print_array(char *str[][COLS]) { 
    int i, j; 

    for (i = 0; i < ROWS; i++) { 
     for (j = 0; j < COLS; j++) { 
      printf("%s ", str[i][j]); 
     } 
     printf("\n"); 
    } 
} 

/*function used for sorting the array */ 
void 
sort_array(char *str[][COLS], int nrows, int col) { 
    int i, j; 
    char *temp; 

    for (i = 0; i < nrows; i++) { 
     for (j = i; j < nrows; j++) { 
      if(strcmp(str[i][col], str[j][col]) > 0) { 
       temp = str[i][col]; 
       str[i][col] = str[j][col]; 
       str[j][col] = temp; 
      } 
     } 
    } 
} 

私の問題は、ソートアルゴリズムが行を入れ替えるのではなく、その列の単なる文字列であることです。私もinsertion sortアルゴリズムを使用しようとしていましたが、文字列の2次元配列で実装する方法がわかりませんでした。

助けを借りれば幸いです。

+3

「の行を交換するが、その列の文字列だけではない」 - そう?ループを書く。 –

+0

ええ、 '挿入ソート'はこれに適していますか? – RoadRunner

+2

'qsort'(標準ライブラリ)を使ってください – BLUEPIXY

答えて

1

行を繰り返します。 2列の列を比較すると、ii + 1となります。必要に応じて、列を繰り返し、2つの行を入れ替えます。スワップがなくなるまで繰り返す。次のように

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

#define ROWS 4 
#define COLS 4 

void print_array(char *str[][COLS]); 
void sort_array(char *str[][COLS], int nrows, int ncols, int col); 

int 
main(void) { 
    char *str[ROWS][COLS] = {{"Russia", "Boxing", "Mens", "Gold"}, 
          {"America", "Cycling", "Mens", "Gold"}, 
          {"New Zealand", "Swimming", "Womens", "Silver"}, 
          {"India", "Badminton", "Mens", "Bronze"}}; 
    int col; 
    int result = 0; 
    int clean = 0; 
    /* array before sorting */ 
    printf("Before: \n"); 
    print_array(str); 

    /*choosing column index to sort by*/ 
    do { 
     printf("\nChoose which column index you wish to sort by 0 to %d: ", COLS - 1); 
     if ((result = scanf("%d", &col)) != 1) { 
      printf("Invalid input\n"); 
      if (result == EOF) { 
       fprintf (stderr, "problem getting input\n"); 
       exit(EXIT_FAILURE); 
      } 
      //clean input stream 
      while ((clean = getchar()) != '\n' && clean != EOF) {} 
     } 
    } while (result != 1 || col < 0 || col >= COLS); 

    sort_array(str, ROWS, COLS, col); 

    /* array after sorting */ 
    printf("\nAfter: \n"); 
    print_array(str); 
    return 0; 
} 

void 
print_array(char *str[][COLS]) { 
    int i, j; 

    for (i = 0; i < ROWS; i++) { 
     for (j = 0; j < COLS; j++) { 
      printf("%s ", str[i][j]); 
     } 
     printf("\n"); 
    } 
} 

/*function used for sorting the array */ 
void 
sort_array(char *str[][COLS], int nrows, int ncols, int col) { 
    int i = 0, j = 0, swap = 0; 
    char *temp; 

    do { 
     swap = 0; 
     for (i = 0; i < nrows - 1; i++) {//iterate through rows 
      if (strcmp(str[i][col], str[i + 1][col]) > 0) {//compare col for row i and i+1 
       for (j = 0; j < ncols; j++) {//iterate through cols and swap rows 
        temp = str[i][j]; 
        str[i][j] = str[i + 1][j]; 
        str[i + 1][j] = temp; 
       } 
       swap = 1; 
      } 
     } 
    } while (swap);//loop until no swaps 
} 
+0

非常に@ user3121023ありがとうございます、これは、バブルソートアルゴリズムを思い出させます。コマンドライン引数に基づいて列の並べ替えを行う方法はありますか? './myprogram 2 0 RoadRunner

+1

バブルソートについては何も素晴らしいことではありません。また、選択ソートは効率的であり、概念的に簡単です(「ソートされていない要素を見つけてソートされた要素に追加する」、「ソートされていない要素がなくなるまで繰り返す」)。 – Arkku

+0

ありがとう@ user3121023、今私はちょうど './myprogram 2 0 3 RoadRunner

1

C11ので、あなたはそれを行うことができます:

qsortを使用して
int compare_col(const void *a, const void *b, void *ctx) { 
    int col = *(int*)ctx; 
    return strcmp(((char**)a)[col], ((char**)b)[col]); 
} 

/*function used for sorting the array */ 
void sort_array(char *str[][COLS], int nrows, int col) { 
    qsort_s(str, nrows, sizeof(char*)*COLS, compare_col, &col); 
} 
+0

私は 'qsort_s'が附属書Kにしかないと考えています。したがって、C11に準拠したすべての実装でも必ずしもサポートされているわけではありません...コンパレータの3番目の引数は、 – Arkku

+1

一方、冗長性を避けるために 'sizeof(char *)* COLS'の代わりに' sizeof(* str) 'を使用し、型が変更されるとエラーが発生する可能性があります。 – Arkku

2

は、あなたはソートする要素のうちの2つに引数ポインタとして取っコンパレータ機能を必要としています。この場合、ソートされる要素は2D配列の行全体です。ソート列を変更する必要がある場合は、変数をグローバルに保持する必要があります(そうしないと、各列ごとに異なるコンパイラーを作成する必要があります)。

static int sort_column = 0; 

static int compare_rows(const void *a, const void *b) { 
    return strcmp(((const char **)a)[sort_column], ((const char **)b)[sort_column]); 
} 

その後、あなたは、単に引数として使用するアレイおよびコンパレータ機能でqsortを呼び出す:

qsort(str, ROWS, sizeof(*str), (compare_rows));