簡體   English   中英

std :: string不適用於std :: set

[英]std::string not working with std::set

我正在從C ++ Primer Plus做一個編程問題,請我制作一個模板
該函數返回數組中唯一元素的數量。 我不明白為什么
據我所知,第13行在編譯時會導致錯誤,std :: string的行為類似於數組。

這是我的代碼:

#include <iostream>
#include <set>

template <typename T>
int reduce(T ar[], int n);

int main()
{
    long test[] = {1, 2, 1, 3, 3, 4, 1};
    std::string testStr = "testing";

    std::cout << reduce(test, 6) << std::endl;
    std::cout << reduce(testStr, 7) << std::endl;

    std::cin.get();

    return 0;
}

template <typename T>
int reduce(T ar[], int n)
{
    std::set<T> test;
    for(int i = 0; i < n; i++)
    {
        test.insert(ar[i]);
    }
    return test.size();
}

跟進我的立即反應,即std::string不是數組,這是C ++人員可能會完成您正在尋找的任務的方式。

#include <iterator>
#include <iostream>
#include <set>

// instead of taking an array and length, just take where you want to start and where
// you want to stop.
template <typename TForwardIterator>
int reduce(TForwardIterator iter, TForwardIterator end)
{
    // This is hideous syntax to get the type of object the iterator is describing.
    // For std::string, it is char...for T*, it is T.
    // I apologize for C++, I'm not sure there is a better way to do this.
    typedef typename std::iterator_traits<TForwardIterator>::value_type value_type;
    std::set<value_type> set;

    // instead of forcing the objects to be an array type, use iterators!
    for (; iter != end; ++iter)
        set.insert(*iter);
    return set.size();
}

int main()
{
    long test[] = {1, 2, 1, 3, 3, 4, 1};
    std::string testStr = "testing";

    // begin() and end() are iterators you'll find on all the container types
    std::cout << reduce(testStr.begin(), testStr.end()) << std::endl;
    // pointers are iterators, too!
    std::cout << reduce(test, test + 7) << std::endl;

    return 0;
}

答案很簡單: std::string不是數組。

就可以使用[]運算符訪問元素而言,它的行為就像一個數組,但它與char[]數據類型根本不同。 事實上,該標准甚至不能保證它像數組一樣存儲(連續)。 T[]將僅匹配到的數組,而不匹配可用於類數組的對象。

為了解決這個問題,您有幾種選擇

  1. 您可以調用reduce(teststr.c_str(), 7) ,因為c_str()將返回帶有字符串內容的chararray。
  2. 您可以將reduce重寫為template <typename T, typename U> int reduce(U ar, int n)並將其稱為reduce<long>(test, 6)reduce<char>(testStr, 7) 第二個模板參數是必需的,因為沒有從容器到元素的統一方法(在c ++ 0x /使用編譯器擴展中除外)。
  3. 如果您使用的是c ++ 0x,則可以使用decltype從容器中獲取所包含的元素: template <typename T>int reduce(T ar, int n)std::set<decltype(ar[0])> test; (代碼的其余部分保持不變,並且我似乎在代碼塊部分遇到了麻煩,因此這里只有這兩行。

當然,在c ++中,通常會用迭代器的形式編寫這樣的函數(請參見Travis Gockels的答案),因為這只是一種更靈活且得到更好支持的方式。

您可能會將std :: strings與內置字符數組混淆。 std :: strings不是數組,盡管它們的行為類似於數組(類具有重載的[]運算符)並包含數組(您可以通過c_str()訪問)。

如果將第10行替換為

char testStr[] = "testing";

您的程序將編譯並運行。

或者,您可以嘗試執行以下操作:

#include <iostream>
#include <set>

template <typename T>
int reduce(const T* ar, int n);

int main()
{
    long test[] = {1, 2, 1, 3, 3, 4, 1};
    std::string testStr = "testing";

    std::cout << reduce(test, 7) << std::endl;
    std::cout << reduce(testStr.c_str(), testStr.size()) << std::endl;

    std::cin.get();

    return 0;
}

template <typename T>
int reduce (const T* ar, int n)
{
    std::set<T> test;
    for(int i = 0; i < n; i++)
    {
        test.insert(ar[i]);
    }
    return test.size();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM