2015-04-02 19 views
1

我有的拿着串像C++排序 - 之後的正常信件

BB 
aA 
12 
b 
AA 
& 
[ 
** 
1 

使用與C默認排序()一個字符串矢量特殊字符++我給這個排序列表

& 
** 
1 
12 
AA 
BB 
[ 
aA 
b 

取而代之的是,我需要按正常的ASCII順序排列正常字母A, a, B, b....,其次是「特殊」字符,如0-9, *, [, , ~, !....

我真的不知道如何去改變矢量排序的方式,以確保它是按順序排列的。謝謝。

+6

'sort'有一個可選的第三個參數 - 比較謂語。編寫你自己的,實現你想要的任何比較,傳遞給'sort'。 – 2015-04-02 02:15:54

+0

你需要提供比較.... – Jagannath 2015-04-02 02:16:20

回答

2

另一個未經測試的解決方案。

如果我錯過了的情況下,我敢肯定有人會指出來,但這裏有雲:

#include <iostream> 
#include <algorithm> 
#include <string> 
#include <cctype> 
#include <vector> 
#include <iterator> 

using namespace std; 

int main() { 
    std::vector <std::string> StringVect = { "BB", "aA", "12", "b", "AA", "&", "[", "**", "1" }; 

    std::sort(StringVect.begin(), StringVect.end(), [] 
     (const std::string& s1, const std::string& s2) 
    { 
     if (s1.empty() || s2.empty()) 
      return s1 < s2; 

     // a convenience array        
     bool ac[] = { isalpha(s1[0]), isalpha(s2[0]), 
         isdigit(s1[0]), isdigit(s2[0]), 
         !isalnum(s1[0]), !isalnum(s2[0]) }; 

     // If both strings start with the same type, then return 
     // s1 < s2 
     if ((ac[0] && ac[1]) || // if both alpha strings 
      (ac[2] && ac[3]) || // if both digit strings 
      (ac[4] && ac[5])) // if both non-alphanumeric strings 
      return s1 < s2; 

     // if first string is alpha, or second string is not alphanumeric 
     // the strings are in order, else they are not 
     return (ac[0] || ac[5]); 
    }); 
    copy(StringVect.begin(), StringVect.end(), ostream_iterator<string>(cout, "\n")); 
} 

基本上,條件這樣說:

1)字符串如果一個人被空,則返回S1 < S2

2)如果兩個字符串以相同的字符類型啓動,只返回S1 < S2

3)如果第一個字符串以字母開始,或者如果第二個字符串不是字母數字,則字符串按順序排列並返回true,否則返回false。這裏的技巧是認識到步驟2)消除了兩個字符串的所有組合都是相同類型的,所以我們在步驟3)階段的檢查變得簡化了。

活生生的例子:http://ideone.com/jxxhIY

編輯:

如果你檢查區分大小寫的字符串,那麼你需要更改代碼,並添加不區分大小寫的檢查。我不會添加代碼,因爲有多種方法,既有各自的優缺點,也有做大小寫不敏感的比較。

#include <iostream> 
#include <algorithm> 
#include <string> 
#include <cctype> 
#include <vector> 
#include <iterator> 

using namespace std; 

int main() { 
    std::vector <std::string> StringVect = { "BB", "aA", "12", "b", "AA", "&", "[", "**", "1" }; 

    std::sort(StringVect.begin(), StringVect.end(), [] 
     (const std::string& s1, const std::string& s2) 
    { 
     if (s1.empty() || s2.empty()) 
      return s1 < s2; 

     // a convenience array        
     bool ac[] = { isalpha(s1[0]), isalpha(s2[0]), 
         isdigit(s1[0]), isdigit(s2[0]), 
         !isalnum(s1[0]), !isalnum(s2[0]) }; 

     // If both strings start with the same type, then return 
     // s1 < s2 
     if ((ac[2] && ac[3]) || (ac[4] && ac[5])) 
      return s1 < s2; 

     // case insensitive 
     if (ac[0] && ac[1]) // both strings are alpha 
      return myCaseInsensitiveComp(s1, s2); //returns true if s1 < s2, false otherwise 

     // if first string is alpha, or second string is not alphanumeric 
     // the strings are in order, else they are not 
     return (ac[0] || ac[5]); 
    }); 
    copy(StringVect.begin(), StringVect.end(), ostream_iterator<string>(cout, "\n")); 
} 

同樣,myCaseInsensitiveComp是存根,你應該與實現這一目標的一個功能練習I.對於一個鏈接,看到這一點:

Case insensitive string comparison in C++

+0

最近我已經瞭解,但現在它打印這個錯誤的順序'AA BB aA' – uniwolk 2015-04-02 03:27:36

+0

所以你想基於不區分大小寫的排序嗎?你沒有在你的問題中提到這一點。 – PaulMcKenzie 2015-04-02 03:30:14

+0

請注意,大寫字母出現在ASCII對比序列中的所有小寫字母之前,這就是您看到這種情況的原因。如果兩個字符串都以字母字符開頭,則需要添加的內容是一種比較不區分大小寫的方法。現在,它使用'std :: string'的char_traits來做比較。看到這個鏈接的替代品:http://stackoverflow.com/questions/11635/case-insensitive-string-comparison-in-c – PaulMcKenzie 2015-04-02 03:55:05

2

您可以指定自己的函數來比較要使用的排序值。

bool myfunction(std::string a, std::string b){ ... } 

std::sort(data.begin(), data.end(), myfunction); 

使用myfunction您可以指定所需的訂單。以下是有關排序的更多信息:

http://www.cplusplus.com/reference/algorithm/sort/

1

無論如何,你需要實現自己的比較邏輯它,並與sort使用它。

(1)你可以給一個比較函數對象sort,並實現自己的比較(小於)在它的邏輯,如:

struct my_comparison { 
    bool operator()(const string &a, const string &b) { 
     // implement the less than logic here 
    } 
} 

然後:

sort(v.begin(), v.end(), my_comparison()); 

參考:http://en.cppreference.com/w/cpp/algorithm/sort

(2)你可以實現你自己的char_traits<char>做出特殊的string,它使用特殊的比較兒子邏輯。如:

struct my_char_traits : public char_traits<char> 
       // just inherit all the other functions 
       // that we don't need to replace 
{ 
    static bool eq(char c1, char c2) { 
     // implement the comparison logic here 
    } 
    static bool lt(char c1, char c2) 
     // implement the comparison logic here 
    } 
    static int compare(const char* s1, const char* s2, size_t n) 
     // implement the comparison logic here 
    } 
}; 

然後:

typedef basic_string<char, my_char_traits> my_string; 
vector<my_string> v; 
// ... 
sort(v.begin(), v.end()); 

參考:http://en.cppreference.com/w/cpp/string/char_traits

1

免責聲明:未經測試的代碼。

下面是一個應該工作的比較函數的實現。解決方案的關鍵是將數值重新編碼到數組中,這些數值對應於您要在比較函數中更改其順序的字符。

void initializeEncoding(char encoding[]) 
{ 
    for (int i = 0; i < 256; ++i) 
    { 
     encoding[i] = i; 
    } 

    // Now re-encode for letters, numbers, and other special characters. 
    // The control characters end at 31. 32 == ' ', the space character. 

    int nextIndex = 32; 

    // Re-encode the uppercase letters. 
    for (int c = 'A'; c <= 'Z'; ++c, ++nextIndex) 
    { 
     encoding[c] = nextIndex; 
    } 

    // Re-encode the lowercase letters. 
    for (int c = 'a'; c <= 'z'; ++c, ++nextIndex) 
    { 
     encoding[c] = nextIndex; 
    } 

    // Re-encode the numbers. 
    for (int c = '0'; c <= '9'; ++c, ++nextIndex) 
    { 
     encoding[c] = nextIndex; 
    } 

    // Re-encode the special chracters. 
    char const* specialChars = " !\"#$%&'()*+,-./:;<=>?[\\]^_`{|}~"; 
    for (char* cp = specialChars; *cp != '\0'; ++cp, ++nextIndex) 
    { 
     encoding[*cp] = nextIndex; 
    } 
} 

bool mycompare(char const* s1, char const* s2) 
{ 
    static char encoding[256]; 
    static bool initialized = false; 
    if (!initialized) 
    { 
     initializeEncoding(encoding); 
     initialized = true; 
    } 

    for (; *s1 != '\0' && *s2 != '\0'; ++s1, ++s2) 
    { 
     if (encoding[*s1] != encoding[*s2]) 
     { 
     break; 
     } 
    } 

    return ((encoding[*s1] - encoding[*s2]) < 0); 
} 

bool mycompare(std::string const& s1, std::string const& s2) 
{ 
    return mycompare(s1.c_str(), s2.c_str()); 
}