2013-03-24 24 views
0
for (i = 0; i < t; i++) 
{ 
    values.clear(); 

    scanf("%d %d %d", &values[0], &values[1], &values[2]); 
    printf("%d %d %d\n", values[0], values[1], values[2]); 
    sort(values.begin(), values.end()); 
    printf("%d %d %d\n", values[0], values[1], values[2]); 

    printf("Case %d: %d\n", i + 1, values[1]); 
} 

我有那個小片段。我輸入「1200 1500 1800」,它應該給我中間值 - 1500.但是,它輸出1200,最小的值。我使用的是STL的sort()對vector進行排序,然後打印值爲[1]的中間值。STL整理不起作用

但是,sort()似乎並沒有工作,打印的矢量前後是一樣的東西。

我宣佈我的矢量:

vector<int> values (3); 

我試着用vector<int> values;申報,然後push_back(0)三次了。

我想知道爲什麼它不工作的第一種方式,但。

回答

5
values.clear(); 

這會清除values,以便它不再包含任何元素。嘗試訪問任何元素將導致未定義的行爲,std::sort將簡單地對空序列進行排序。

a.clear()定義其中a是一個序列容器是:

銷燬在a所有元素。使指向a的元素的所有引用,指針和迭代器失效,並可能使過去最終的迭代器失效。
a.empty()返回true

6

你的程序有未定義行爲

爲了解決這個問題,只是刪除這一行:

values.clear(); 

上述行所做的,其實是擦除從矢量所有元素。然後,該行:

scanf("%d %d %d", &values[0], &values[1], &values[2]); 
        ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^ 

將嘗試訪問不存在的元素。與關聯容器的operator []不同,向量的operator []不會創建任何新元素。因此,表達式values[0],values[1]values[2]都是嘗試訪問不存在的元素。

每表的C++ 11標準的101:

表達a[n]

返回類型:參考; const_reference恆定a

操作語義*(a.begin() + n)

這意味着通過這樣做:

values[0] 

你實際上是這樣:

*(values.begin() + 0) 

此處調用values.begin()會返回數組中第一個元素的迭代器。由於在矢量沒有元件(第23.2.1/6),以values.begin()呼叫相當於一個呼叫到values.end()

begin()返回迭代參照在容器中的第一個元素。 end()返回一個迭代器,其中 是容器的過去最終值。如果容器是空的,則begin() == end();

因此,values[0]你的情況實際上是相同的:

*(values.end() + 0) 

這又相當於此:

*(values.end()) 

換句話說,你訪問一個迭代器,指向容器中最後一個元素之外的位置。這是未定義的行爲,當然也適用於values[1]values[2]

0

當您清除vector時,您將大小設置爲0. scanf行通常不會崩潰,因爲vector通常會預先分配一些存儲讀取值的存儲空間。結果是當你撥打sort時,begin()end()將是平等的。

您可以嘗試將值讀入臨時值或在讀取值之前調用resize(3)

0

您試圖用values.clear();清除實際存在的元素實際上是將它們完全從矢量中刪除。這會使begin()end()相等,從而導致排序無效(以及您將各個元素的地址置爲未定義行爲的輸入)。

我想你真正想要做的是確保有沒有在向量的元素太多,所以不是clear使用resizevalues.resize(3)這將有去除多餘的元素或增加的大小的影響如果它目前較小,則向量爲三。

1

我覺得<算法>頭__median功能更容易。

med = __median(a, b, c); 
+1

你的意思是'std :: nth_element'。標準庫的(標準部分)沒有像'__median'這樣的函數。 – ipc 2013-03-24 14:28:23