2016-03-21 98 views
0

我正在解決一個字符串數組排序非冗餘排列的問題。例如,如果輸入的字符串是"8aC",那麼輸出應該是像{"Ca8","C8a", "aC8", "a8C", "8Ca", "9aC"}那樣的順序。我選擇了C++數據結構集,因爲每次將字符串插入std:set時,set都會自動排序並消除冗餘。輸出很好。C++ std :: set <string>字母數字自定義比較器

但我想排序設置在不同於默認字母數字排序順序的不同字母順序。我想定製設置訂單優先級的比較器,如:upper case> lower case > digit

我試圖自定義比較器,但它非常令人沮喪。 如何自定義設置的排序順序?這是我的代碼。

set<string, StringCompare> setl; 
for (i = 0; i < f; i++) 
{ 
    setl.insert(p[i]); //p is String Array. it has the information of permutation of String. 
} 
for (set<string>::iterator iter = setl.begin(); iter != setl.end(); ++iter) 
     cout << *iter << endl; //printing set items. it works fine. 

struct StringCompare 
{ 
    bool operator() (const std::string s_left, const std::string s_right) 
    { 
     /*I want to use my character comparison function in here, but have no idea about that. 
      I'm not sure about that this is the right way to customize comparator either.*/ 
    } 
}; 

int compare_char(const char x, const char y) 
{ 
    if (char_type(x) == char_type(y)) 
    { 
     return ((int) x < (int) y) ? 1 : 0 ; 
    } 
    else return (char_type(x) > char_type(y)) ? 1 : 0; 
} 

int char_type(const char x) 
{ 
    int ascii = (int)x; 
    if (ascii >= 48 && ascii <= 57) // digit 
    { 
     return 1; 
    } 
    else if (ascii >= 97 && ascii <= 122) // lowercase 
    { 
     return 2; 
    } 
    else if (ascii >= 48 && ascii <= 57) // uppercase 
    { 
     return 3; 
    } 
    else 
    { 
     return 0; 
    } 
} 
+1

不要硬編碼ASCII碼。 'x> ='0''比'ascii> = whatever_is_ascii_code_for_zero'讀得更乾淨(不會被打擾查看它)。但是'isdigit(x)'比任何一個都好。 –

回答

1

你是幾乎沒有,但你應該字典序比較的字符串。 我大致上對你的代碼添加了一些小的改動。

int char_type(const char x) 
{ 
    if (isupper(x)) 
    { 
     // upper case has the highest priority 
     return 0; 
    } 

    if (islower(x)) 
    { 
     return 1; 
    } 

    if (isdigit(x)) 
    { 
     // digit has the lowest priority 
     return 2; 
    } 

    // something else 
    return 3; 
} 

bool compare_char(const char x, const char y) 
{ 
    if (char_type(x) == char_type(y)) 
    { 
     // same type so that we are going to compare characters 
     return (x < y); 
    } 
    else 
    { 
     // different types 
     return char_type(x) < char_type(y); 
    } 
} 

struct StringCompare 
{ 
    bool operator() (const std::string& s_left, const std::string& s_right) 
    { 
     std::string::const_iterator iteLeft = s_left.begin(); 
     std::string::const_iterator iteRight = s_right.begin(); 

     // we are going to compare each character in strings 
     while (iteLeft != s_left.end() && iteRight != s_right.end()) 
     { 
      if (compare_char(*iteLeft, *iteRight)) 
      { 
       return true; 
      } 

      if (compare_char(*iteRight, *iteLeft)) 
      { 
       return false; 
      } 

      ++iteLeft; 
      ++iteRight; 
     } 

     // either of strings reached the end. 
     if (s_left.length() < s_right.length()) 
     { 
      return true; 
     } 

     // otherwise. 
     return false; 
    } 
}; 
+0

你的解決方案是我想要的。謝謝你的幫助 – JunsungChoi

1

你的比較結果是正確的。我會變成參數通過這個簡單的實現爲const裁判這樣

bool operator() (const std::string &s_left, const std::string &s_right) 

,並開始:

return s_left < s_right 

這將給默認行爲,並給你信心,你是在正確的軌道上。 然後開始比較兩個字符串的長度之間較短的一個字符與for循環。你可以通過簡單的操作符[](例如s_left [i])獲得字符串字符串。

0

你幾乎已經擁有了你所擁有的東西。

在你的比較仿函數中,給出了兩個std::string s。你需要做的是找到兩個字符串不同的第一個位置。爲此,您可以使用標準庫中的std::mismatch。這將返回充滿指向前兩個元素是不同的迭代器std::pair

auto iterators = std::mismatch(std::begin(s_left), std::end(s_left), 
           std::begin(s_right), std::end(s_right)); 

現在,你可以取消引用兩個迭代,我們一直在考慮讓人物:

char c_left = *iterators.first; 
char c_right = *iterators.second; 

你可以通過這兩個字符到你的compare_char函數,它應該都可以工作:-)

+0

std :: mismatch非常有趣。感謝您的幫助 – JunsungChoi

0

不絕對確定這一點,但你可能能夠使用枚舉類對你的優勢或數組,並選擇從ce讀取某些指數,你曾經喜歡過。

您可以使用一個枚舉類來定義您希望輸出數據的順序,以及另一個包含要輸出數據的順序,然後可以設置一個循環,以便將值分配給輸出中的一個循環排列方式!

namespace CustomeType 
{ 
    enum Outs { Ca8= 0,C8a, aC8, a8C, 8Ca, 9aC }; 
    enum Order{1 = 0 , 2, 3 , 4 , 5}; 
    void PlayCard(Outs input) 
    { 
     if (input == Ca8) // Enumerator is visible without qualification 
     { 
      string[] permuted; 
      permuted[0] = Outs[0]; 
      permuted[1] = Outs[1]; 
      permuted[2] = Outs[2]; 
      permuted[3] = Outs[3]; 
      permuted[4] = Outs[4]; 
     }// else use a different order 
    else if (input == Ca8) // this might be much better 
    { 
     string[] permuted; 
     for(int i = 0; i<LessThanOutputLength; i++) 
     { 
       //use order 1 to assign values from Outs 
     } 
    } 
    } 
} 
0

這應該工作:

bool operator() (const std::string s_left, const std::string s_right) 
    { 
     for(int i = 0;i < s_left.size();i++){ 
      if(isupper(s_left[i])){ 
       if(isupper(s_right[i])) return s_left[i] < s_right[i]; 
       else if(islower(s_right[i]) || isdigit(s_right[i]))return true; 
      } 
      else if(islower(s_left[i])){ 
       if(islower(s_right[i])) return s_left[i] < s_right[i]; 
       else if(isdigit(s_right[i])) return true; 
       else if(isupper(s_right[i])) return false; 
      } 
      else if(isdigit(s_left[i])){ 
       if(isdigit(s_right[i])) return s_left[i] < s_right[i]; 
       else if(islower(s_right[i]) || isupper(s_right[i])) return false; 
      } 
     } 
    } 
+0

這是問題的最佳代碼。謝謝你的幫助。 – JunsungChoi

相關問題