redis aof文件淺析
redis中的數據持久化有兩種方式:RDB持久化和AOF持久化。RDB相對于AOF來說是一個粗粒度的備份,即RDB可能是一天備份一次,而AOF可能是每秒一次甚至每次寫操作進行一次備份。
redis中的aof(append only file)文件的作用就相當于mysql中的binlog,用于記錄寫操作日志。當redis服務器異常宕機,可以使用該文件對數據進行恢復。進行數據恢復時,redis服務器端會創建一個 fake client(假冒客戶端),即通過fake client來模擬redis客戶端,該fake client讀取aof文件并執行其中的redis command,通過這種方式來模擬redis客戶端對redis服務器的操作(增刪改),從而達到恢復數據的目的。
另外redis是k-v數據庫,數據存儲在內存,當然也會定時持久化。在redis服務關閉時,內存中原先的數據就會丟失,所以在redis每次重新啟動時,需要將持久化的數據恢復到內存中。持久化的數據就是rdb和aof文件,具體采用的方式是根據redis的配置文件而定。
c++中const變量真的不可以修改嗎?
在學c++的時候,看到的大部分的書籍對const關鍵字的介紹都是:const關鍵字修飾的變量的值是不可被修改的。但是事實真是如此嗎?今天做了一個小的實驗,發現const變量是可以被修改的。c++代碼如下:
1 #include <iostream>
2 using namespace std;
3
4 int main()
5 {
6 const int a = 3;
7 int* p = const_cast<int*>(&a);
8 *p = 4;
9 cout << "value of p: " << *p << endl;
10 cout << "value of a: " << a << endl;
11 cout << "address of p: " << p << endl;
12 cout << "address of a: " << &a << endl;
13
14 return 0;
15 }
上面代碼第7行將a的地址賦值給指針p,然后第8行修改p所指向的地址中的值,運行結果如下:
如上所示結果,指針p所指向的地址和變量a的地址相同,但是p所指地址中的值已經發生改變。但是為何變量a對應的地址中的值已經由3變為4,但是a的值確實3呢?
暫時把這個問題擱淺。再來看一下如下的c++代碼:
1 #include <iostream>
2 using namespace std;
3 const int a = 3;
4 int main()
5 {
6 //const int a = 3;
7 int* p = const_cast<int*>(&a);
8 *p = 4;
9 cout << "value of p: " << *p << endl;
10 cout << "value of a: " << a << endl;
11 cout << "address of p: " << p << endl;
12 cout << "address of a: " << &a << endl;
13
14 return 0;
15 }
如上代碼g++編譯通過,在運行時報錯如下:
由此可見,在c++中全局const變量和局部const變量的編譯器處理的方法是不一樣的。查閱資料得知,全局const變量是不分配內存地址的,它編譯器放置在符號表中作為編譯期常量,全局const變量放在只讀數據段中,受到只讀數據段的權限保護,當你修改一個只讀數據段中的內容時,會得到一個運行時錯誤。而局部const變量是放在堆棧之中,因為在內存中有地址,通過修改地址中的值可以達到修改const所指內存中值的目的。
使用crontab自動化拷貝工作
一、 背景
由于開發機上缺少相應的環境,平時我們(特別是像我之類的新人)為了調試方便,往往會直接在測試機上進行開發工作,然后再拷貝到開發機上,提交到svn。然而這樣會存在很多問題,有時候我們明明在測試機上測試正常,提測之后卻出了問題,仔細檢查可能會發現我們拷貝了文件到svn。避免這樣的問題,一是在開發過程中,記錄自己修改創建的文件,但這樣比較繁瑣;二是在開發機上開發,自測時使用測試機進行測試。毫無疑問第二種方法要好一些,但是這樣往往會增加很多繁瑣的拷貝工作,本文就是為了減少這樣的工作而撰寫。
我們首先要在測試機上建立免密碼登陸開發機的信任關系。A為測試機(我的測試機是aaa@bbb.com); B為開發機(我的開發機是ccc@ddd.com);
在A上的命令:
# ssh-keygen -t rsa (機器A上操作,連續三次回車,即在本地生成了公鑰和私鑰,不設置密碼)
# ssh ccc@ddd.com (機器A上操作,ssh登陸機器B時需要輸入密碼)
# mkdir .ssh;chmod 700 .ssh (機器B上操作,如果.ssh目錄存在,則不需要mkdir, 注:必須將.ssh的權限設為700)
# scp ~/.ssh/id_rsa.pub ccc@ddd.com:/home/users/qinlei01/.ssh/id_rsa.pub(機器A上操作,需要輸入密碼)
登陸機器B,在B上的命令:
# touch ~/.ssh/authorized_keys (如果已經存在這個文件, 跳過這條)
# chmod 600 ~/.ssh/authorized_keys (# 注意: 必須將~/.ssh/authorized_keys的權限改為600, 該文件用于保存ssh客戶端生成的公鑰,可以修改服務器的ssh服務端配置文件/etc/ssh/sshd_config來指定其他文件名)
# cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys (將id_rsa.pub的內容追加到 authorized_keys 中, 注意不要用 > ,否則會清空原有的內容,使其他人無法使用原有的密鑰登錄)
回到A機器測試是否能免密碼登陸機器B:
# ssh ccc@ddd.com(不需要密碼, 登錄成功)
=====================================================================
附上A與B互相免密碼登陸的方法:
機器A:192.168.0.106
機器B:192.168.0.107
1、在機器A上執行如下操作
ssh-keygen -d
然后一路回車
cd ~/.ssh
cp id_dsa.pub authorized_keys2
chmod 600 authorized_keys2
2、在B上做如上同樣的操作
3、建立A到B的信任關系(即A免密碼登陸B)
在A中執行(注意需要把文件改名)
scp id_dsa.pub usernameB@192.168.0.107:.ssh/a.pub
在B中的~/.ssh下執行
cat a.pub >> authorized_keys2
此時從A執行ssh到B就不用輸入密碼了
4、建立B到A的信任關系(即B免密碼登陸A)
在B執行
scp id_dsa.pub usernameA@192.168.0.106:.ssh/a.pub
在A執行
cat a.pub >> authorized_keys2
在配置過程需要輸入多次密碼
此時,無論從A到B,還是從B到A,都不需要輸入密碼了
如果出現問題,可以刪除~/.ssh所有文件(連文件夾),然后重新配置
====================================================================
三、建立拷貝文件腳本
1、在機器A某路徑建立拷貝文件腳本(如/home/wiki/xx.sh),在該xx.sh中加入自己需要從開發機上拷貝的文件。例如如下簡單的xx.sh(要將xx.sh設定為可執行,可簡單chmod 777 xx.sh)
scp qinlei01@db-gouyi.db01:/home/users/qinlei01/xxx /home/wiki/xxx
四、 crontab添加任務
1、 在A機器輸入如下命令
# crontab –e (打開crontab的任務列表文件)
2、 輸入如上命令后,vi會打開一個文件(不用管他),在其中輸入如下命令(如果你想每一分鐘執行xx.sh的話)
*/1 * * * * /home/wiki/xx.sh
五、附錄
1、crontab使用:http://vbird.dic.ksu.edu.tw/linux_basic/0430cron.php#crontab
六、完結
到現在你的xx.sh腳本將會每隔一分鐘執行拷貝任務了,這樣你就不需要去關心從開發機拷貝代碼到測試機的繁瑣事務了。如果想即時將開發機上的代碼拷貝到測試機上,只需手動執行xx.sh腳本即可。
xx.sh可以根據你的需要編寫一些高級的邏輯,來判斷文件自上次拷貝之后是否進行了修改,如果沒有修改就跳過拷貝邏輯,來處理復雜的拷貝情況,這里給出 一個實現方案:在開發機上建立一個文件yy.txt,并在開發機上運行一個腳本定時計算需要拷貝的文件的md5值,與之前保存在yy.txt中相應文件的 md5值做比較,如果md5值改變,則寫入另外一個文件zz.txt,然后測試機每隔固定時間從開發機拷貝這個zz.txt文件,這樣測試機就知道哪些文 件發生了改變,只需要拷貝zz.txt中的文件即可,注意zz.txt中的相應文件的md5值需要覆蓋yy.txt中相應文件的md5值,便于下一次比 較。當然如果覺得拷貝zz.txt也不夠快速,可以考慮使用k-v數據庫來存儲。
希望這篇簡單的文檔能對你有所幫助。
如下的html文件,user.html.需要到
https://github.com/douglascrockford/JSON-js/blob/master/json.js 下載json.js
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2 <html>
3 <head>
4 <title> New Document </title>
5 <meta name="Generator" content="EditPlus">
6 <meta name="Author" content="">
7 <meta name="Keywords" content="">
8 <meta name="Description" content="">
9 </head>
10
11 <body>
12 <script>
13 var my_json='{"FBI":{"length":2,"context":[{"name":"rose","age":25},{"name":"qinlei","age":30}]}}'
14 var my_object=eval('('+my_json+')');
15 document.writeln(my_object.FBI.length);
16 for(i=0;i<my_object.FBI.length;++i)
17 {
18
19 document.writeln(my_object.FBI.context[i].name);
20 document.writeln(my_object.FBI.context[i].age);
21
22 }
23
24 </script>
25 <script src="json.js"></script>
26 <script>
27 var my_object={
28 FBI:[
29 {name:"rose",age:"25"},
30 {name:"jack",age:"25"}
31 ],
32 NBA:[
33 {name:"tom",sex:"man"},
34 {name:"jack",sex:"women"}
35 ]
36 };
37 document.writeln(my_object.toJSONString());
38 </script>
39 </body>
40 </html>
41
1.創建版本庫
git init-db,使用該命令會在當前目錄下創建版本庫。生成一個.git的子目錄,該子目錄中會有三個需要重點注意的東東,一個HEAD文件,一個objects子目錄,一個refs子目錄
2.git add,使用該命令將相應文件加入到版本庫文件索引中,或者使用git update-index
3.git status,查看版本庫狀態
4.git commit -m,提交文件到版本庫中
5.git diff,查看當前的工作目錄和版本庫中的差別
6.git branch創建版本分支
7.git checkout ,轉到相應的版本分支
8.git branch -D,刪除版本分支
為了說明c++的聲明順序所導致的作用域問題,考慮如下代碼
1 #include<iostream>
2 //#include <map>
3 //#include <string>
4 using namespace std;
5
6 int a;
7 void first()
8 {
9 a = 1;
10 }
11
12 void second()
13 {
14 int a = 7;
15 first();
16 cout << "second:" << a << endl;
17 }
18
19
20 int main()
21 {
22 a = 2;
23 int num;
24 cin >> num;
25 if (num > 0)
26 {
27 second();
28 }
29 else
30 {
31 first();
32 }
33 cout << a << endl;
34 return 0;
35 }
36
猜想一下上面的代碼輸出的結果是什么?main函數中輸出的結果是1。不論你輸入的num值是正數還是負數結果都是1。為什么會這樣呢?這是因為c++采用的是靜態作用域規則。第9行代碼是關鍵所在。對于c++這種靜態語言而言,第9行代碼實際修改的是全局變量a的值。所以該程序的最終結果會是1。那么動態作用域規則的語言會輸出什么樣的結果呢?那就要根據所輸入的num來決定了。
c++聲明變量的作用就是引進名字符號,表明該變量的作用域,而定義則是給變量分配內存,并且綁定值的過程。對于調用子函數的過程,為了找到子函數中的變量的聲明作用域,編譯器采用了靜態鏈接的方法。對于程序的執行流程,編譯器會維護一個棧,棧中會存儲與相應調用函數對應的幀。編譯器通過棧和幀數據結構來維護程序執行所調用的函數層次流程。要找到一個子函數中的變量聲明域實際上就是在棧中相應幀中尋找該變量的聲明。尋找起點是當前活動幀,而當前活動幀又通過靜態鏈接(相當于指針)與它的父幀相關聯。但是考慮上面的程序,當輸入num大于0時,應該是先調用second,然后調用first,而second中對變量a重新進行了聲明,如果棧中維護的層次是函數調用的層次,則此時first中修改的變量a應該是second中聲明的變量a才是,那么結果輸出應該是2,但是事實并非如此。所以我認為棧中的靜態鏈接所鏈接的不是函數調用的層次,而是聲明的層次。考慮上面的程序,全局變量a和函數first的聲明是在同一層次的,則如果要尋找a中變量的聲明,應該首先查找a所在的那個模塊所對應的幀(姑且認為是全局幀吧,看成有一個全局范圍的函數與之對應),則這時找到的a的聲明應該就是全局變量a。所以如果按照這種分析的話,那么程序的結果就是1了。
以上只是我的猜想,由于最近要忙于考試,沒有時間查閱更多資料,且編譯原理那塊已經幾乎忘得差不多了。如有錯誤請各位指正。
剛查了下我的郵箱,第一封求職郵件是2月24日發給opera的。直到今天已經不知不覺過去了三個多月,發送的簡歷數多達200多封,細數面試的次數也應該有幾十次,幾乎各種類型的企業都有面過。雖然最終還是拿到了比較滿意的offer,但是這個過程是充滿教訓的。
首先,我對自己極度不自信,所以才會采取海投簡歷的方法,以期望以大的面試基數,來獲得面試成功的次數。由于我每天都要投不少簡歷,所以需要在各大求職網上轉悠,浪費了不少原本可以用于打牢專業基礎的時間。雖然獲得了不少面試機會,也增加了不少面試經驗,但是每次面試之后,都沒有對自己存在的本質問題進行思考總結,所以每次進步都很緩慢。
當然這個過程也不是一點收獲也沒有,比如我獲取了大量hr們的聯系方式,并且掌握了一套獲取求職信息的方法。甚至于,我會主動打電話到一些公司的人力部親自問他們是否缺人,而實踐證明這一招還是很不錯的方法。很多機會都不是等來的,而是自己爭取到的。
關于面試我想主要要做好以下幾方面:
1.簡歷。一定要做好自己的簡歷,即使花上幾天也是值得的,面試官的第一印象就是從簡歷開始的吧,而且面試中的很多東西都是跟簡歷相關的。起初我的簡歷做得比較花哨,但是內容不充實,重點不突出,沒有什么亮點,后來再兩個師哥的指點下,做了修改,確實好了很多。當然現在的簡歷還是有很大問題的。一份好的簡歷都要反復修改,并且要經常更新。對于自己應聘的不同崗位,應該要做一份針對性的簡歷,當然不是完全重做,可以在一開始就做一份盡量翔實的簡歷(包括英文簡歷),包含自己的信息,獲獎情況,項目情況,擔任班干部情況(這個外企好像會看重一些,有時會問到一些過去的經歷,特別是對待困難的態度,感覺外企更注重人的綜合素質),然后在此基礎上針對不同企業的不同職位增刪一些內容。這點其實我并沒有做到,這也是做得不到位的地方。
2.面試知識準備
1.專業基礎知識,主要是語言,數據結構,算法,網絡,linux,數據庫......網上都有很多介紹。其中linux和數據庫要是熟練掌握是有加分的,由于我對linux及linux下編程不太熟悉,面試中有被鄙視的感覺,然后就加強了這方面的準備。其實linux和數據庫方面問的都比較淺,就是看看平時有沒有了解過。
2.圍繞自己簡歷內容做準備。這個其實是非常重要的,往往決定性因素可能就在這上面。比如做過數據庫方面的項目的話,可以看看數據庫的范式,數據優化什么的,我就看了一下范式,然后還真派上用場了。針對每個做過的項目可能涉及的知識點復習一下,比如多線程,socket通信,windows通信機制等,根據項目不同做相應準備。另外對個別自己感覺比較重要的且可能被問到的項目(比如近期做過的項目,跟應聘職位相關性很大的項目,跟應聘公司某 些產品相關的項目)重點做準備。這些項目盡量深入進去,如果實在不太記得自己當時是怎么做的,就自己重新思考一下現在該如何去做,并且上網查一些相關資料。
3.面試經驗
4.提問
這個我覺得也是一個可以加分的項。比如深入了解一下應聘公司的某個產品,問問面試官其中的技術實現,然后談談自己的想法。不過要注意度,盡量讓對方說得爽,同時自己也要有點見解。
教訓:
1.海投簡歷,這是個下招
2.沒花太多時間充實自己的基礎知識,而是將時間浪費在了海投簡歷以及面試各種公司上
3.面試過程中,用詞不當,我經常愛用“也許”“可能”“我不太記得了”之類的詞,感覺這樣給人的感覺就是基礎很不牢靠。
4.每次面試的時候沒有向面試官詢問自己面試中存在的不足
5.電話面試太多,其實電話面試有很多劣勢。你看不到面試官的表情變化,沒法察言觀色。建議現場面試,即使跑到北京去也是可以的。
6.簡歷做得不夠好。
7.項目準備不充分,經常被問住,應該多花時間準備項目。
8.電話面試忘記微笑
9.還是基礎不夠扎實,平時編程也不夠,看書也不夠全面,不夠深入。
10.對自己的定位不明,還不知道自己以后要深入的方向,這是最大的悲哀。這方面zyf童鞋,是我的榜樣啊。
待續。。
-----------------------我是低調的分界線------------------
-----------------------投簡歷參考(補充)----------------
目前我曾經聯系過的一部分還需要實習生的公司。具體職位可以使用提供的郵箱百度搜索一下。
**********省略給別人的公司及相關信息
**********
公司還有很多,這個自己平時慢慢找吧,關鍵是主動獲取信息。如果你主動點每天都能投出去10多封郵件的,招人的公司還是非常多的。但是不建議海投簡歷,還是先打好基礎,這樣效率會高一些。海投的話也有效,畢竟雖然面試成功幾率小,但是面試次數多,所以最終也還是會有比較好的結果的。但是這樣很辛苦,還是以打牢基礎為主。
另外附上幾個我常用的招聘信息網站:
1.Hiall
2.應屆生求職網
3.北郵人論壇(這個還是不錯的,上面有不少招聘信息),用游客身份登錄,然后點“信息社會”->兼職實習信息
4.水木清華bbs(基本上跟上面差不多)
5.鯉魚網 實習
6.大街網
平時多關注這些網站上的招聘信息。另外平時要多關注一些IT類的新聞。比如說上面的湯森路透可能大家很少聽過,那是因為你平時關注這方面的信息比較少,你上網查查這個公司就知道了,還是很牛逼的。如果喜歡互聯網行業的話,可以關注一些互聯網的最新動態,還有一些創業公司,有些創業公司發展還是很不錯的,這里提供幾個:五分鐘公司,創新工場的行云、友盟、豌豆夾、魔圖精靈,人民搜索,另外還可以關注一下團購網站,例如高朋,美團。視頻行業:優酷、土豆、百度奇藝,另外騰訊最近投了5億元發展自己的視頻業務,估計最近會有大動作,可以關注一下騰訊視頻的實習招聘,如果官網或者招聘網沒有公布招聘信息,你可以自己主動打電話過去詢問,應該會很缺人。
尋找實習招聘信息:
1.關注上面推薦的招聘信息網站
2.直接打電話到自己想實習的公司。具體方法:進官網,點擊誠聘英才(也可能是其他),一般在網站最下方,具體自己去實踐吧。然后找到公司的聯系方式,注意一般是公司的總機號碼,你是得不到分機號碼的,你撥總機之后,會有提示,比如按0查詢分機號,這個時候會有人接電話,你告訴他你要找實習,讓他幫忙轉接到人力資源部,然后你再詢問人力那邊是否有實習生招聘計劃就行。
3.牡丹園bbs,計算機學院。會有人發布內推消息
----------------我還是低調的分界線------------------
最后,自己終于能基本上在經濟上能獨立了。并給自己說一句遲到的“生日快樂”,跟母親說一句”感謝您“。生日那天恰逢百度筆試,也正好是母親節,都沒過生日。
1.先從redis最初版本開始逐步研究
2.由于最近準備期末考試,所以每天晚上22:00-24:00學習2個小時
1 #include <iostream>
2 #include <vector>
3 #include <algorithm>
4 #define max(a,b) ((a)>(b))?(a):(b)
5 using namespace std;
6 //寫出來之后,嘗試把每一個for循環用for_each來替換。或者將公用的for流程用函數替代
7 struct PrintResult
8 {
9 void operator()(int i)
10 {
11 cout << i << " ";
12 }
13 }printResult;
14
15 struct PrintVecResult
16 {
17 void operator()(vector<int> vec)
18 {
19 for_each(vec.begin(), vec.end(), printResult);
20 cout << endl;
21 }
22 }printVecResult;
23
24 int knapsack(vector<int> &vecWeight, vector<int> &vecValue, int capacity)
25 {
26 int num = vecWeight.size();
27 vector<vector<int> > f(num, vector<int>(capacity, 0));
28 vector<int> result(num, 0);
29
30 int j = 0;
31 int i = 0;
32 for (i = 1; i <= num; ++i)
33 {
34 for (j = 1; j <= capacity; ++j)
35 {
36 if (j >= vecWeight[i])
37 {
38 f[i][j] = max(f[i-1][j], f[i-1][j-vecWeight[i]] + vecValue[i]);
39 }
40 else
41 {
42 f[i][j] = f[i-1][j];
43 }
44 }
45 }
46 //打印f數組表
47 for_each(f.begin(), f.end(), printVecResult);
48
49 //打印背包所能容納的最大價值
50 cout << f[num][capacity] << endl;
51
52 //打印產生最大價值的背包中物品的編號
53
54 for (j = capacity, i = num; i >= 1; --i)
55 {
56 //result[i] = f[i][j] > f[i-1][j] ? 1 : 0;
57 if (f[i][j] > f[i-1][j])
58 {
59 result[i] = 1;
60 j = j - vecWeight[i];
61 }
62 else
63 {
64 result[i] = 0;
65 }
66 }
67
68 for (i = 1; i <= num; ++i)
69 {
70 if (1 == result[i])
71 {
72 cout << i << " ";
73 }
74 }
75 return f[num][capacity] ;
76 }
77
78
79 int main()
80 {
81 int num = 0;
82 int capacity = 0;
83 cin >> num;
84 cin >> capacity;
85
86 vector<int> weight;
87 vector<int> value;
88 weight.push_back(0);
89 value.push_back(0);
90
91 for (int i = 1; i <= num; ++i)
92 {
93 int tempWeight = 0;
94 int tempValue = 0;
95 cin >> tempWeight >> tempValue;
96 weight.push_back(tempWeight);
97 value.push_back(tempValue);
98 }
99
100 knapsack(weight, value, capacity);
101
102 return 0;
103 }
計數排序實現:以學生年齡對學生信息進行排序。
1 #include <iostream>
2 #include <vector>
3 #include <string>
4 #include <algorithm>
5 using namespace std;
6
7 typedef struct StudentInfo
8 {
9 unsigned int age;
10 string name;
11 string major;
12 }StudentInfo;
13
14 struct StudentCount
15 {
16 void operator()(StudentInfo stuInfo)
17 {
18 cout << stuInfo.name << " " << stuInfo.age << stuInfo.major << endl;
19 }
20 }student;
21
22 void Countsort(vector<StudentInfo> &vec, unsigned int nMaxAge)
23 {
24 unsigned int* nCount = (unsigned int*)malloc(sizeof(unsigned int)*nMaxAge);
25 //vector<unsigned int> nCount(nMaxAge, 0);
26 memset(nCount, 0, sizeof(unsigned int)*nMaxAge); //assign 0 to the array nCount
27 vector<StudentInfo>::const_iterator iter = vec.begin();
28
29 //count the number of each age
30 for (; iter != vec.end(); ++iter) //用for_each試一下
31 {
32 ++nCount[iter->age];
33 }
34
35 //確定有多少個數據在當前元素的前面
36 for (int i = 1; i < nMaxAge; ++i)
37 {
38 nCount[i] += nCount[i-1];
39 }
40
41 vector<StudentInfo> StudentSorted;
42 StudentSorted.reserve(vec.size()); //使用reserve預分配空間,這些空間是否有初始值呢?
43 StudentSorted.resize(vec.size());
44 for (int i = 0; i < vec.size(); ++ i)
45 {
46 int index = --nCount[vec[i].age];
47 StudentSorted[index] = vec[i];
48 }
49
50 //將StudentSorted數據復制到vec中。
51 vec.swap(StudentSorted);
52 //for_each(vec.begin(), vec.end(), student);
53 free(nCount);
54 nCount = NULL;
55 }
56 int main()
57 {
58 vector<StudentInfo> vec;
59 //初始化vec中的數據
60 for (int i = 0; i < 20; ++i)
61 {
62 StudentInfo stuInfo = {i%10, "qinlei", "CS"};
63 vec.push_back(stuInfo);
64 }
65
66 //開始排序
67 Countsort(vec, 20);
68 //打印排序后的結果
69 for_each(vec.begin(), vec.end(), student);
70 return 0;
71 }