2009-08-27 61 views

答えて

2

私はあなたがすでにC標準ライブラリqsort()機能を知っていると仮定します。最後のパラメータは、あなたがそれに任意の関数を渡すことができることを意味関数ポインタ、ある

void qsort(void *base, 
      size_t nel, 
      size_t width, 
      int (*compar)(const void *, const void *); 

こと。あなたはstrcmp()を使用することができますが、それはASCIIbeticalを与えるでしょう、そして、あなたは特に自然な並べ替えが必要です。その場合

、あなたはかなり簡単に1を書くことができます:

#include <ctype.h> 

int natural(const char *a, const char *b) 
{ 
    if(isalpha(*a) && isalpha(*b)) 
     { 
     // compare two letters 
     } 
    else 
     { 
     if(isalpha(*a)) 
      { 
      // compare a letter to a digit (or other non-letter) 
      } 
     else if(isalpha(*b)) 
      { 
      // compare a digit/non-letter to a letter 
      } 
     else 
      { 
      // compare two digits/non-letters 
      } 
     } 
} 

をお早いだけreturn場合else Sの一部がアップクリアすることができますが、基本的な構造があります。 isalpha()(文字がアルファベットの一部である場合)、isdigit()isspace()などの機能については、ctype.hをチェックしてください。

+0

素敵なアイデアですが、ちょっと単純すぎます。私が書いたり、テストしたりするのを悩ました理由は明らかではありません。 –

+0

"自然"とは何を意味するのか分からず、リンクされた(うまく設計された、完璧な移植性のある)バージョンを無視すると、 –

3

基本的なソート機能は標準C qsort()です。これは比較関数を取るためにパラメータ化されており、比較関数は自然順序付けを行うために書く必要があります。

相互参照の質問には、比較関数のC実装が含まれています。

Googleの検索「natural sort c」は、SourceForgeの実装を示しています。

+0

私はソースfourgeの例を見ました。私は窓にいます。よくテストされ、使用された比較のより多くのために願っています。 –

8

ここには、ジョブを実行する(テスト済みの)比較関数があります。それが唯一の符号なし整数ではなく、符号付き整数または浮動小数点を理解します。

#include <stdlib.h> 
#include <ctype.h> 

/* like strcmp but compare sequences of digits numerically */ 
int strcmpbynum(const char *s1, const char *s2) { 
    for (;;) { 
    if (*s2 == '\0') 
     return *s1 != '\0'; 
    else if (*s1 == '\0') 
     return 1; 
    else if (!(isdigit(*s1) && isdigit(*s2))) { 
     if (*s1 != *s2) 
     return (int)*s1 - (int)*s2; 
     else 
     (++s1, ++s2); 
    } else { 
     char *lim1, *lim2; 
     unsigned long n1 = strtoul(s1, &lim1, 10); 
     unsigned long n2 = strtoul(s2, &lim2, 10); 
     if (n1 > n2) 
     return 1; 
     else if (n1 < n2) 
     return -1; 
     s1 = lim1; 
     s2 = lim2; 
    } 
    } 
} 

あなたは、qsortでそれを使用し、この補助機能を使用する場合:

static int compare(const void *p1, const void *p2) { 
    const char * const *ps1 = p1; 
    const char * const *ps2 = p2; 
    return strcmpbynum(*ps1, *ps2); 
} 

をそして、あなたがのために何かを行うことができますここで

qsort(lines, next, sizeof(lines[0]), compare); 
+1

私は最初の "return 1"は "return -1"でなければならないと思います。 strcmpbynum( ""、 "x")を考えてみましょう。 –

0

もUnicodeをサポートしているのQtのバージョン、です:

int strcmpbynum(const QString& s1, const QString &s2) { 
int i1 = 0; // index in string 
int i2 = 0; 
while (true) { 
    if (s2.length() == i2) // both strings identical or s1 larger than s2 
     return s1.length() == i1 ? 0 : 1; 
    if (s1.length() == i1) return -1; // s1 smaller than s2 

    unsigned short u1 = s1[i1].unicode(); 
    unsigned short u2 = s2[i2].unicode(); 

    if (u1 >= '0' && u1 <= '9' && u2 >= '0' && u2 <= '9') { 
     // parse both numbers completely and compare them 
     quint64 n1 = 0; // the parsed number 
     quint64 n2 = 0; 
     int l1 = 0; // length of the number 
     int l2 = 0; 
     do { 
      ++l1; 
      n1 = n1 * 10 + u1 - '0'; 
      if (++i1 == s1.length()) break; 
      u1 = s1[i1].unicode(); 
     } while (u1 >= '0' && u1 <= '9'); 
     do { 
      ++l2; 
      n2 = n2 * 10 + u2 - '0'; 
      if (++i2 == s2.length()) break; 
      u2 = s2[i2].unicode(); 
     } while (u2 >= '0' && u2 <= '9'); 
     // compare two numbers 
     if (n1 < n2) return -1; 
     if (n1 > n2) return 1; 
     // only accept identical numbers if they also have the same length 
     // (same number of leading zeros) 
     if (l1 < l2) return -1; 
     if (l1 > l2) return 1; 
    } else { 
     // compare digit with non-digit or two non-digits 
     if (u1 < u2) return -1; 
     if (u1 > u2) return 1; 
     ++i1; 
     ++i2; 
    } 
} 

}

関連する問題