2015-10-22 84 views
0

我想寫一個函數,它將返回無重複數字的數量。到目前爲止,我已經寫了一個函數,它通過char來迭代並收集所有數字,但是當我必須從只有非重複數字的向量中獲取問題時纔會出現問題。

我的代碼:矢量得到沒有重複元素

int norepeat(char *word){ 
    int i = 0; 
    int size = 0; 
    vector<int> tab; 
    while (word[i] != '\0'){ 
     if (word[i] >= '0' && word[i] <= '9') { 
      int num = word[i]; 
      tab.push_back(num); 
      sort(tab.begin(),tab.end()); 
      unique(tab.begin(),tab.end()); 
      size = tab.size(); 
     } 
     ++i; 
    } 
    return size; 
} 

編輯:

幾個例子應該是如何工作的:

norepeat("de32ge2sa3ds1") => 1 
norepeat("defegtdsg") => 0 
norepeat("12341234") => 0 
norepeat("1yle2le49") => 4 
+0

如果我理解正確,您只需要在字符串中只出現一次的數字?那麼你的'std :: unique'應該可以工作。但在while循環之後執行。 – haavee

+0

@haavee完全如您所說。我已經將它移到循環之外,但它仍然不起作用 – Gregy

+0

因爲我錯了:-)'std :: unique'不是你想要的。 – haavee

回答

3

創建地圖的數字的 - >位數計數。

然後通過地圖迭代和計數具有的1

int norepeat(char *word){ 
    int i = 0; 
    std::map<char, int> m; 
    while (word[i] != '\0'){ 
     if (isdigit(word[i]) 
     m[word[i]]++; 
     ++i; 
    } 

    int count = 0; 
    for (auto& p : m) 
    { 
     if (p.second == 1) 
     ++count; 
    } 

    return count; 
} 

計數的位數當與不支持C++ 11,for環路可以改變爲一個編譯器的工作:

std::map<char, int>::iterator iter = m.begin(); 
    std::map<char, int>::iterator end = m.end(); 
    for (; iter != end; ++iter) 
    { 
     if (iter->second == 1) 
     ++count; 
    } 
+0

你能用'for'循環解釋部分嗎?因爲我完全不理解它 – Gregy

+1

@Gregy,這是在C++ 11中引入的range-for循環的語法。有關更多詳細信息,請參閱http://en.cppreference.com/w/cpp/language/range-for。 –

0
int norepeat(char *word){ 

int i = 0; 
int size = 0; 
vector<int> tab; 
while (word[i] != '\0'){ 
    if (word[i] >= '0' && word[i] <= '9') { 
     int num = word[i]; 
     tab.push_back(num); 
    } 
    ++i; 
} 

size = std::distance(unique(tab.begin(),tab.end()), tab.end()); 
return size; 

}

+0

它似乎沒有工作,我用'de32ge2sa3ds1'例子檢查它,它返回'4'而不是'1' – Gregy

+0

糟糕!計算距離錯誤的方式。現在修復。 – ravenspoint

+0

我曾嘗試使用'1yle2le49'示例,但它仍然不起作用 – Gregy

2

C++的好處是能夠從C++標準模板庫混合普通老式 - 數據指針和libc函數和算法:(注:使用了一些C++ 11功能)

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include <vector> 
#include <ctype.h> 

using namespace std; 

size_t norepeat(const char* word) { 
    vector<char>   digits; 
    vector<char>::iterator uniq; 

    // Filter the digits 
    copy_if(word, word+strlen(word), back_inserter(digits), ::isdigit); 

    // get the unique ones 
    sort(digits.begin(), digits.end()); 
    uniq = unique(digits.begin(), digits.end()); 

    // return amount 
    size_t uniques = std::distance(digits.begin(), uniq); 
    size_t duplicates = std::distance(uniq, digits.end()); 
    return uniques - duplicates; 
} 

int main(void) { 
    cout << norepeat("hello 123 world 124") << endl; 
    cout << norepeat("hello world") << endl; 
    return 0; 
} 

輸出:

2 
0 

EDIT

只是爲了笑:寫了一個計數輸出迭代器類;它會將複製到其中的值的發生次數計入value - >unsigned int的地圖中。與count_if算法(C++ lambda表達式)的norepeat函數本身只有三個語句組合:一個變量聲明,過濾數字並返回計數的結果:自從我上次回答的基礎上的誤讀

#include <map> 
#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include <ctype.h> 

using namespace std; 

template <typename T> 
struct counter : public iterator<output_iterator_tag, T> { 
    typedef map<T, unsigned int> counter_type; 

    counter(counter_type* ptr) : mapptr(ptr) {} 

    // decorate with dereference and assignment 
    counter<T>& operator=(const T& t) { 
     mapptr->operator[](t)++; 
     return *this; 
    } 
    counter<T>& operator++() { return *this; } 
    counter<T>& operator*() { return *this; } 

    counter_type* mapptr; 
}; 

size_t norepeat(const char* word) { 
    typename counter<char>::counter_type countert; 

    // Filter the digits 
    copy_if(word, word+strlen(word), counter<char>(&countert), ::isdigit); 

    // Count the ones that have a value of one 
    return count_if(countert.begin(), countert.end(), 
        [](const counter<char>::counter_type::value_type& kv) { 
          return kv.second==1; }); 
} 

int main(void) { 
    cout << norepeat("hello 123 world 124") << endl; 
    cout << norepeat("hello world") << endl; 
    return 0; 
} 
+0

在末尾推薦一個可讀性調整:'uniques = std :: distance(digits.begin(),uniq); duplicates = std :: distance(uniq,digits.end()); return uniques - duplicates;'使return的意圖(uniq - digits.begin()) - (digits.end() - uniq);'脫穎而出。 – user4581301

+0

謝謝,這確實更清楚。不掛斷。 – haavee

+0

'uniques - duplicates'對於{1,1,1}爲-1 –

1

問題,這個怎麼樣?

int norepeat(const char *word){ 
    int i = 0; 
    int size = 0; 
    int arr[10] = {0}; // there are only 10 unique possibilities, 
         // so we'll mark them when found 
    while (word[i] != '\0') 
    { 
     if (std::isdigit(word[i])) 
     { 
      int num = word[i] - '0'; // get numeric value of digit to use as index 
      arr[num]++; // count the number of times we've seen this digit 
     } 
     ++i; 
    } 
    for (i = 0; i < 10; i++) 
    { 
     if (arr[i] == 1) // count all element seen only once 
     { 
      size++; 
     } 
    } 
    return size; 
} 

這插科打諢實在有限,因爲它只會爲十進制數字的工作,但有輕微的修改就可以做大寫或小寫字符。隨着std::map ...可能性是無限的!我會在一秒鐘內補充完整性。

編輯

的地圖版本。

int norepeat(const char *word){ 
    int i = 0; 
    int size = 0; 
    std::map<char, int> counts; 

    while (word[i] != '\0') 
    { 
     if (std::isdigit(word[i])) // could use any or no filtering logic here 
     { 
      counts[word[i]]++; 
     } 
     ++i; 
    } 
    for (auto &count: counts) 
    { 
     if (count.second == 1) // count all element seen only once 
     { 
      size++; 
     } 
    } 
    return size; 
} 
+0

更好;它解決了問題!但它是非常C,而不是C++ ;-)我在那裏看到的唯一C++有5個字符長:'std ::'... – haavee

+0

@haavee你不是人,只是說C++的美麗之一是需要時能否掉入排水溝? – user4581301

+0

絕對是!但是這意味着在C風格指針上使用C++算法,並使用'raw'函數指針(比如':: isdigit')作爲這些算法的謂詞。這意味着在編寫或構建包裝對象或函子時根本沒有開銷;即沒有實際的運行時間開銷,但算法的所有類型安全性和已知良好行爲! – haavee