char s[10][10]をstd::sortでソート

解決


ja  2009-06-18 09:07:24  No: 70365  IP: [192.*.*.*]

2次元配列 char tab[10][10] をstd::sortでソートしたいのですが、
std::sortへの引数の渡し方がわかりません。
どのように書いたらよいでしょうか?

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

bool cmp_strcmp(const char* a, const char* b) {
  return strcmp(a, b) < 0;
}

int main() {
  char tab[10][10];
  int n = 0;
  strcpy(&tab[n++][0], "ab");
  strcpy(&tab[n++][0], "hello");
  strcpy(&tab[n++][0], "abd");

  // sortでソートしたい
  // sort(??, ??, cmp_strcmp) // ??の部分がわかりません

  // 出力
  for (int i = 0; i < n; i++)
    puts(tab[i]);
}

期待する実行結果:
ab
abd
hello

編集 削除
επιστημη  URL  2009-06-18 09:54:03  No: 70366  IP: [192.*.*.*]

うわ、めんどくせー...
↓コレなら楽勝なんですけどねー

#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

bool cmp_strcmp(char *a, char *b) {
  return strcmp(a, b) < 0;
}

int main() {
  char* tab[10];
  int n = 0;
  tab[n++] = strdup("ab");
  tab[n++] = strdup("hello");
  tab[n++] = strdup("abd");

  sort(tab, tab+n, &cmp_strcmp);
  
  // 出力
  for (int i = 0; i < n; i++) {
    puts(tab[i]);
    free(tab[i]);
  }
}

編集 削除
tetrapod  2009-06-18 11:18:12  No: 70367  IP: [192.*.*.*]

std::sort は、ソート対象が代入可能でないと使えない。
一方で単純配列は代入可能でない (int a[10], b[10]; に対して a=b; はできない)
なのでそもそも std::sort で配列自体をソートするってのが不向き。

うーむ誤解を生みかねないので補足しておくほうがよさそうかな:
string の配列や ポインタの配列ならソート可能(ソート対象は string やポインタ)
配列の配列は std::sort 不能(ソート対象が 配列 なので)

編集 削除
επιστημη  URL  2009-06-18 11:24:02  No: 70368  IP: [192.*.*.*]

フォローありがとです > tetrapodさん。

int main() {
  char tab[10][10];
  int n = 0;
  strcpy(&tab[n++][0], "ab");
  strcpy(&tab[n++][0], "hello");
  strcpy(&tab[n++][0], "abd");

  sort(&tab[0], &tab[n], ptr_fun(&cmp_strcmp));
  ...

このコードをVC++9でコンパイルすると:
...\Microsoft Visual Studio 9.0\VC\INCLUDE\algorithm(3133) 
: error C2106: '=' : 左のオペランドが、左辺値になっていません。
...\Microsoft Visual Studio 9.0\VC\INCLUDE\algorithm(3140) 
: error C2106: '=' : 左のオペランドが、左辺値になっていません。

なんてエラーが報告されます。
ソート対象となる要素 char[] に =(代入操作) が適用できないからですね。

編集 削除
ja  2009-06-19 10:43:15  No: 70369  IP: [192.*.*.*]

ありがとうございました。別のデータ構造に変換してからソートするようにします。

編集 削除
επιστημη  URL  2009-06-19 11:35:08  No: 70370  IP: [192.*.*.*]

> 別のデータ構造

ご参考: char tab[10][10] 改め vector<string> に。

#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
  vector<string> tab;
  tab.push_back("ab");
  tab.push_back("hello");
  tab.push_back("abd");

  sort(tab.begin(), tab.end());
  
  // 出力
  for (int i = 0; i < tab.size(); ++i)
    puts(tab[i].c_str());
}

ほら簡単♪

編集 削除
tetrapod  2009-06-19 12:39:03  No: 70371  IP: [192.*.*.*]

既に char[10][10]; でデータを持っていて、そこを修正するつもりはなくて、
でもソートのためだけに vector<string> に変換し、またもとの char[10][10] に戻すくらいなら
素直に qsort してしまえ。

char tab[5][10]; に3つ有効な要素が入っているとしたら
qsort(tab, 3, sizeof(char[10]), tabcompfunc);
でソートできる(データの変換不要)
比較関数 tabcompfunc をどう実装するかはお任せ(宿題)としておこう。

編集 削除
επιστημη  URL  2009-06-19 13:50:58  No: 70372  IP: [192.*.*.*]

> ソートのためだけに vector<string> に変換し、
> またもとの char[10][10] に戻すくらいなら
> 素直に qsort してしまえ。

激しく"ごもっとも"

編集 削除