iT邦幫忙

0

C++ 排序使用lambda表示式

請教各位大神了 謝謝
這支程式我使用了STL的array

這支程式中有一個struct 內容有一個string型態的學號
題目想要根據學號來排序學生資料 學號由小到大
以下是我的程式
學號假設沒有英文且只有數字
在排序過程我用std::stoi()將string 換成 int
但過程中出了一點問題 希望可以告訴小弟原因 謝謝

[Error] no match for call to '(main()::<lambda(Student, Student)>) (std::array<Student, 3ull>&, std::array<Student, 3ull>&)'

#include <iostream>
#include <cstdlib>
#include <array>
#include <string>
#include <algorithm>
struct Student {
	int mid_score;
	int final_score;
	int usual_grade;
	std::string number;
	std::string name;
};
bool operator<(Student x, Student y) {
	int a = std::stoi(x.number);
	int b = std::stoi(y.number);
	if(a < b) {
		return true;
	}else {
		return false;
	}
}
void show(const std::array<Student, 3> &);
int main() {
	std::array<Student, 3> studentArr;
	std::array<Student, 3>::iterator iter;
	for(iter = studentArr.begin(); iter != studentArr.end(); ++iter) {
		std::getline(std::cin, iter->name);
		std::getline(std::cin, iter->number);
		(std::cin >> iter->mid_score >> iter->final_score >> iter->usual_grade).clear();
		std::cin.ignore();
	}
    std::sort(studentArr.begin(), studentArr.end(), [](Student x, Student y){return x < y;});
    show(studentArr);
	system("pause");
	return 0;
}
void show(const std::array<Student, 3> &studentArr) {
	std::array<Student, 3>::const_iterator const_iter;
	for(const_iter = studentArr.begin(); const_iter != studentArr.end(); ++const_iter) {
		std::cout << const_iter->name << '\n' << const_iter->number << '\n'\
		          << const_iter->mid_score << '\n' << const_iter->final_score << '\n' << const_iter->usual_grade << std::endl;
	}
}

將 std::sort(&studentArr, &studentArr + 3 [](Student x, Student y){return x < y;});
換成
std::sort(studentArr.begin(), studentArr.end(), [](Student x, Student y){return x < y;});
後即可編譯成功
但仍然不懂原理 再請各位大神解惑了 謝謝

2 個回答

1
小魚
iT邦大師 1 級 ‧ 2019-05-13 08:12:21
最佳解答

begin() 等是 iterator 而不是 Student的指標.

請問你的意思是說,sort的begin, end應該丟iterator而不是Array的指標嗎

小魚 iT邦大師 1 級 ‧ 2019-05-13 22:12:19 檢舉

C++是屬於強型別的語言,
只能帶入指定的類別,
(不討論template)
如果不是指定的類別,
基本上在編譯的時候就會出錯.
帶入函式的參數跟指定(=)都是這樣,
譬如說不允許 string = int,
也就是以下的情況是不允許的,
在編譯階段就會報錯.

string str = "";
int num = 1;
str = num;

十分感謝!

3
fysh711426
iT邦研究生 3 級 ‧ 2019-05-14 20:59:42

我將 Student 換成 int 來說明原因

//先宣告一個陣列
array<int, 5> arr;

//接下來看下列三個例子有何不同
printf("%d\n", &arr);      //6422260
printf("%d\n", &arr+3);    //6422320
printf("%d\n", &arr[3]);   //6422272

//有沒有發現 2 和 3 的地址是不同的
//這是因為 &arr+3 的意思是
//從 &arr 的位置開始,加上 3 個 array<int, 5> arr 大小的空間
//一個 int 的大小是 4,等於 6422260 + 5 x 3 x 4 = 6422320

//而 &arr[3] 的意思是
//取陣列 arr[3] 的地址,6422260 + 3 x 4 = 6422272  <--這才是我們要的

接下來看 sort 函數

sort(&arr, &arr + 3, [](int x, int y){return x < y;});
//看一下型態
//有沒有發現第 1 和 2 個參數的型態和 lambda 需要的 x, y 型態不同
(std::array<...> *, std::array<...> *, lambda []bool (int x, int y)->bool)

//那 iterator 為什麼可以?
sort(arr.begin(), arr.end(), [](int x, int y){return x < y;});

//iterator 其實是一個指向 int 的指標,型態和 lambda 需要的參數一樣
(int *, int *, lambda []bool (int x, int y)->bool)
//所以其實 sort 函數是可以接受指標的

//那該如何調整呢?
//我們把地址取法改成和上面例子一樣就可以了
sort(&arr[0], &arr[5], [](int x, int y){return x < y;});
//型態
(int *, int *, lambda []bool (int x, int y)->bool)

//再補充一個 vector 的例子
vector<int> v;
sort(v.begin(), v.end(), [](int x, int y){return x < y;});

//v.begin() 的型態是 vector<...>::iterator
//不是 int 那 vector 為什麼可以呢?
(std::vector<...>::iterator, std::vector<...>::iterator, lambda []bool (int x, int y)->bool)

//我們通常把 vector<...>::iterator 稱為 Smart Pointer (智慧型指標)
//就是一個經過封裝的指標類型,雖然不是指標,卻可以像指標一樣使用

//可以像指標一樣使用 * 對 iterator 取值,x 的型態等於 int
vector<int>::iterator it;
auto x = *it;

//所以 sort 函數才能接受除了指標以外
//vector<...>::iterator 這種型態的 Smart Pointer

範例

#include <iostream>
#include <cstdlib>
#include <array>
#include <string>
#include <algorithm>

using namespace std;

int main() 
{
    array<int, 5> arr;
    arr[0] = 4;
    arr[1] = 2;
    arr[2] = 1;
    arr[3] = 3;
    arr[4] = 5;
    
    printf("%d\n", &arr);
    printf("%d\n", &arr+3);
    printf("%d\n", &arr[3]);

    sort(&arr[0], &arr[5], [](int x, int y){return x < y;});

    for(int i=0; i<5; i++)
    {
        printf("%d\n", arr[i]);
    }

	system("pause");
	return 0;
}

結果

6422260
6422320
6422272
1
2
3
4
5
看更多先前的回應...收起先前的回應...

謝謝大大...

這篇真的很仔細,對我真的很有幫助,讓我釐清這些觀念

謝謝您願意那麼仔細的指出我的問題/images/emoticon/emoticon41.gif

fysh711426 iT邦研究生 3 級 ‧ 2019-05-15 14:47:44 檢舉

大家互相學習,我昨天也研究了好久,C++ 的 typedef 和 template 好深奧阿~
/images/emoticon/emoticon12.gif

我要發表回答

立即登入回答