22個涵蓋C++面向過程、面向對象、泛型的Hello World的經典實例:
接上文:
16 STL向量版
17 鍊表篇
18 函數對象與自定義查找算法
19 自定義查找算法及泛化
20 標準庫查找算法
21 成績管理系統2(標準庫排序算法)
22 STL文件篇
//-----------------------------------------------------------------------------
#if 0 // 16 STL向量版
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Person
{
public:
Person()
{
cout << "請輸入姓名:";
getline(cin, name);
cout << "請輸入年齡:";
cin >> age;
}
virtual ~Person()
{
}
string GetName() const
{
return name;
}
int GetAge() const
{
return age;
}
private:
string name;
int age;
};
struct Beauty : public Person
{
public:
Beauty ()
{
cout << "請輸入國籍:";
cin.sync();
getline(cin, nationality);
cout << "請輸入三圍數據(胸、腰、臀),數據以空格隔開,回車確認:";
cin >> bust >> waist >> hips;
cout << "請輸入自我介紹內容:";
cin.sync();
getline(cin, introduction);
}
string GetNationality() const
{
return nationality;
}
int GetBust() const
{
return bust;
}
int GetWaist() const
{
return waist;
}
int GetHips() const
{
return hips;
}
void Introduction() const
{
cout << introduction << endl;
}
private:
std::string nationality; // 國籍
int bust; // 胸圍
int waist; // 腰圍
int hips; // 臀圍
std::string introduction; // 自我介紹內容
};
//美女管理類
struct BeautiesManager
{
public:
void Input(); // 輸入新的美女
void Find() const; // 按姓名查找美女
void Count() const // 顯示當前美女總數
{
cout << "當前美女個數:" << beauties.size() << endl;
}
void Introduction() const; // 所有美女依次自我介紹
void Clear(); // 清空當前所有美女
private:
vector<Beauty> beauties; // 向量------------------------------------------
};
void BeautiesManager::Input()
{
Beauty b;
beauties.push_back(b);
}
void BeautiesManager::Find() const
{
cout << "請輸入要查找的美女姓名:";
string name;
getline(cin, name);
int found = 0;
for (unsigned int i=0; i<beauties.size(); ++i)
{
if (beauties[i].GetName() == name)
{
++found;
cout << "找到啦!該美女的索引是: " << i << endl;
cout << "姓名:" << beauties[i].GetName() << endl
<< "年齡:" << beauties[i].GetAge() << endl
<< "國籍:" << beauties[i].GetNationality() << endl
<< "三圍:" << beauties[i].GetBust() << ", "
<< beauties[i].GetWaist() << ", " << beauties[i].GetHips() << endl;
}
}
cout << "共找到:" << found << "位名為:" << name << "的美女!" << endl;
}
void BeautiesManager::Introduction() const
{
for (unsigned int i=0; i<beauties.size(); ++i)
{
cout << "現在出場的是:" << beauties[i].GetName() << endl;
beauties[i].Introduction();
}
}
void BeautiesManager::Clear()
{
cout << "您確認要清除所有美女數據嗎?該操作不可恢復! (y/n):";
char c;
cin >> c;
cin.sync();
if (c == 'y')
{
beauties.clear();
cout << "數據已清除!" << endl;
}
}
// 顯示主菜單:
int ShowMenu()
{
cout << "請選擇:" << endl;
cout << "1 美女信息錄入" << endl
<< "2 美女信息查找" << endl
<< "3 檢查美女總數" << endl
<< "4 美女出場自我介紹" << endl
<< "5 清空全部美女數據" << endl
<< endl
<< "6 關於本程序" << endl
<< "7 退出" << endl;
int sel = 0;
cin >> sel;
cin.sync();
return sel;
}
void About()
{
cout << "《XXX國際美女大賽信息管理系統 Ver 1.0》" << endl
<< "作者:丁小明 Copyright 2008~???" << endl;
}
int main()
{
enum {sel_input = 1, sel_find, sel_count, sel_introduction, sel_clear, sel_about, sel_exit};
cout << "XXX國際美女大賽歡迎您!" << endl;
BeautiesManager bm;
while(true)
{
int sel = ShowMenu();
if ( sel_input == sel)
{
bm.Input();
}
else if (sel_find == sel)
{
bm.Find();
}
else if (sel_count == sel)
{
bm.Count();
}
else if (sel_introduction == sel)
{
bm.Introduction();
}
else if (sel_clear == sel)
{
bm.Clear();
}
else if (sel_about == sel)
{
About();
}
else if (sel_exit == sel)
{
break;
}
else // 什麼也不是?
{
if (cin.fail ())
{
cin.clear(); // 清除cin當前可能處於錯誤狀態,需清除
cin.sync();
}
cout << "選擇有誤,請重選。" << endl;
}
}
system("pause");
return 0;
}
#endif
//-----------------------------------------------------------------------------
#if 0 // 鍊表熱身
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lst;
lst.push_front(10);
lst.push_front(20);
lst.push_back(8);
lst.push_back(9);
lst.pop_front();
lst.pop_back();
lst.clear();
lst.push_back(1);
lst.push_back(2);
int a = lst.front();
cout << a << endl;
int b = lst.back();
cout << b << endl;
int count = lst.size();
cout << count << endl;
cout << lst.empty() << endl;
lst.clear();
cout << lst.empty() << endl;
lst.push_back(1);
lst.push_back(2);
list<int>::iterator iter = lst.begin();
a = *iter;
cout << a << endl;
*iter = 1000;
cout << *iter << endl;
cout << a << endl;
b = *iter;
cout << b << endl;
/*
lst<int>::iterator iter2 = lst.end();
int a = *iter2; // 災難發生
*iter2 = 100; // 災難發生
*/
lst.clear();
lst.push_back(10);
lst.push_back(100);
iter = lst.begin();
++iter; // iter前進1步,指向第二個元素
lst.insert(iter, 1); // 在第二個元素的位置上,插入新元素
iter = lst.begin();
++iter;
lst.erase(iter);
list<int>::const_iterator c_iter = lst.begin(); // 此時調用的是常量版
a = *c_iter; // 正確
cout << a << endl;
//*c_iter = 1000; // 錯誤!c_iter是只讀版疊代器,不允許修改它綁定的元素
for (list<int>::const_iterator c_iter2 = lst.begin();
c_iter2 != lst.end();
++c_iter2)
{
cout << *c_iter2 << endl;
}
/*
for (list<int>::const_reverse_iterator c_iter3 = lst.rbegin();
c_iter3 != lst.rend();
++c_iter3)
{
cout << *c_iter3 << endl;
}
*/
system("pause");
return 0;
}
#endif
//-----------------------------------------------------------------------------
#if 0 // 17 鍊表篇
#include <iostream>
#include <list>
#include <vector>
#include <string>
using namespace std;
struct Student // 學生
{
unsigned int number; // 學號
string name;
};
struct Score // 成績
{
unsigned int number; // 學號
float mark; // 分數
};
// 以上兩個結構是為了減少耦合度,通過學號建立關係。
struct StudentScoreManager // 學生成績管理類
{
public:
void InputStudents();
void InputScores();
void OutputScores() const;
private:
vector<Student> students;
list<Score> scores;
};
void StudentScoreManager::InputStudents()
{
unsigned int number = 1; // 學號從1開始
while(true)
{
cout << "請輸入" << number << "號學生姓名(輸入x表示結束):";
string name;
getline(cin, name);
if (name == "x")
{
break;
}
Student student;
student.number = number;
student.name = name;
students.push_back(student);
++number;
}
}
void StudentScoreManager::InputScores()
{
while(true)
{
unsigned int number;
cout << "請輸入學號(輸入0表示結束):";
cin >> number;
if (number == 0)
{
break;
}
if (number > students.size()) // 簡單判斷學號是否正確:
{
cout << "錯誤:學號必須位於: 1 ~ " << students.size() << " 之間。" << endl;
continue;
}
float mark;
cout << "請輸入該學員成績:";
cin >> mark;
Score score;
score.number = number;
score.mark = mark;
scores.push_back(score);
}
}
void StudentScoreManager::OutputScores() const
{
for (unsigned int i=0; i<students.size(); ++i)
{
unsigned int number = students[i].number; // 學號
cout << "學號:" << number << endl;
cout << "姓名:" << students[i].name << endl;
// 查找成績:
bool found = false;
for (list<Score>::const_iterator iter = scores.begin();
iter != scores.end();
++iter)
{
if (iter->number == number)
{
found = true; // 找到了
cout << "成績:" << iter->mark << endl;
break;
}
}
if (found == false) // 沒找到??
{
cout << "成績:" << "查無成績。" << endl;
}
}
}
int main()
{
StudentScoreManager ssm;
ssm.InputStudents();
ssm.InputScores();
ssm.OutputScores();
system("pause");
return 0;
}
/*
請輸入1號學生姓名(輸入x表示結束):wwu
請輸入2號學生姓名(輸入x表示結束):fwu
請輸入3號學生姓名(輸入x表示結束):x
請輸入學號(輸入0表示結束):1
請輸入該學員成績:11
請輸入學號(輸入0表示結束):2
請輸入該學員成績:22
請輸入學號(輸入0表示結束):0
學號:1
姓名:wwu
成績:11
學號:2
姓名:fwu
成績:22
*/
#endif
//-----------------------------------------------------------------------------
#if 0 // 18 函數對象與自定義查找算法
// cin輸入分數時有點問題,在線可以運行:https://www.onlinegdb.com/
#include <iostream>
#include <list>
#include <vector>
#include <string>
using namespace std;
struct Student // 學生
{
unsigned int number; // 學號
string name;
};
struct Score // 成績
{
unsigned int number; // 學號
float mark; // 分數
};
struct StudentScoreManager // 學生成績管理類
{
public:
void InputStudents();
void InputScores();
void OutputScores() const;
private:
vector<Student> students;
list<Score> scores;
};
void StudentScoreManager::InputStudents()
{
unsigned int number = 1; // 學號從1開始
while(true)
{
cout << "請輸入" << number << "號學生姓名(輸入x表示結束):";
string name;
getline(cin, name);
//cin.ignore(32767,'\n');
//cin.clear(); //此處用cin.clear()流標誌復位
//cin.sync();
if (name == "x")
{
break;
}
Student student;
student.number = number;
student.name = name;
students.push_back(student);
++number;
}
}
struct CompareByNumber_Equal
{
unsigned int number; // 學號
bool operator () (unsigned int current_number) const //函數對象---------
{
return current_number == number;
}
};
// 自定義查找算法------------------------------------
list<Score>::iterator find (list<Score> scores, CompareByNumber_Equal cmp)
{
for (list<Score>::iterator iter = scores.begin();
iter != scores.end();
++iter)
{
if (cmp(iter->number))
{
return iter;
}
}
return scores.end();
}
void StudentScoreManager::InputScores()
{
while(true)
{
unsigned int number;
cout << "請輸入學號(輸入0表示結束):";
cin >> number;
if (number == 0)
{
break;
}
// 簡單判斷學號是否正確:
if (number > students.size())
{
cout << "錯誤:學號必須位於: 1 ~ " << students.size() << " 之間。" << endl;
continue;
}
float mark;
cout << "請輸入該學員成績:";
cin >> mark;
//scanf("%f",&mark);
//cin.ignore(32767,'\n');
//cin.clear(); //此處用cin.clear()流標誌復位
//cin.sync();
Score score;
score.number = number;
score.mark = mark;
scores.push_back(score);
}
}
void StudentScoreManager::OutputScores() const
{
for (unsigned int i=0; i<students.size(); ++i)
{
unsigned int number = students[i].number; //學號
cout << "學號:" << number << endl;
cout << "姓名:" << students[i].name << endl;
// 查找成績:
CompareByNumber_Equal cmp;
cmp.number = number;
list<Score>::const_iterator iter = find(scores, cmp);
if (iter != scores.end())
{
cout << "成績:" << iter->mark << endl;
}
else // 沒找到
{
cout << "成績:" << "查無成績。" << endl;
}
}
}
int main()
{
StudentScoreManager ssm;
ssm.InputStudents();
ssm.InputScores();
ssm.OutputScores();
system("pause");
return 0;
}
/*
請輸入1號學生姓名(輸入x表示結束):wwu
請輸入2號學生姓名(輸入x表示結束):wwf
請輸入3號學生姓名(輸入x表示結束):x
請輸入學號(輸入0表示結束):1
請輸入該學員成績:11
請輸入學號(輸入0表示結束):2
請輸入該學員成績:22
請輸入學號(輸入0表示結束):0
學號:1
姓名:wwu
成績:11
學號:2
姓名:wwf
成績:22
sh: 1: pause: not found
*/
#endif
//-----------------------------------------------------------------------------
#if 0 // 19 自定義查找算法及泛化
#include <iostream>
#include <list>
#include <vector>
#include <string>
using namespace std;
struct Student // 學生
{
unsigned int number; // 學號
string name;
};
struct Score // 成績
{
unsigned int number; // 學號
float mark; // 分數
};
struct StudentScoreManager // 學生成績管理類
{
public:
void InputStudents();
void InputScores();
void OutputScores() const;
private:
vector<Student> students;
list<Score> scores;
};
void StudentScoreManager::InputStudents()
{
unsigned int number = 1; // 學號從1開始
while(true)
{
cout << "請輸入" << number << "號學生姓名(輸入x表示結束):";
string name;
getline(cin, name);
if (name == "x")
{
break;
}
Student student;
student.number = number;
student.name = name;
students.push_back(student);
++number;
}
}
struct CompareByNumber_Equal
{
unsigned int number; // 學號
bool operator () (unsigned int current_number) const
{
return current_number == number;
}
};
//將 find 「泛化」,讓它可以針對不同容器,以及不同的容器元素,都可以作查找
template <typename T>
T find (T beg, T end, CompareByNumber_Equal cmp)
{
for (T iter = beg; iter != end; ++iter)
{
if (cmp (iter->number))
{
return iter;
}
}
return end;
}
void StudentScoreManager::InputScores()
{
while(true)
{
unsigned int number;
cout << "請輸入學號(輸入0表示結束):";
cin >> number;
if (number == 0)
{
break;
}
// 簡單判斷學號是否正確:
if (number > students.size())
{
cout << "錯誤:學號必須位於: 1 ~ " << students.size() << " 之間。" << endl;
continue;
}
float mark;
cout << "請輸入該學員成績:";
cin >> mark;
Score score;
score.number = number;
score.mark = mark;
scores.push_back(score);
}
}
void StudentScoreManager::OutputScores() const
{
for (unsigned int i=0; i<students.size(); ++i)
{
unsigned int number = students[i].number; //學號
cout << "學號:" << number << endl;
cout << "姓名:" << students[i].name << endl;
// 查找成績:
CompareByNumber_Equal cmp;
cmp.number = number;
list<Score>::const_iterator iter = find(scores.begin(), scores.end(), cmp);
if (iter != scores.end())
{
cout << "成績:" << iter->mark << endl;
}
else // 沒找到
{
cout << "成績:" << "查無成績。" << endl;
}
}
}
int main()
{
StudentScoreManager ssm;
ssm.InputStudents();
ssm.InputScores();
ssm.OutputScores();
system("pause");
return 0;
}
/*
請輸入1號學生姓名(輸入x表示結束):wwu
請輸入2號學生姓名(輸入x表示結束):wwf
請輸入3號學生姓名(輸入x表示結束):x
請輸入學號(輸入0表示結束):1
請輸入該學員成績:11
請輸入學號(輸入0表示結束):2
請輸入該學員成績:22
請輸入學號(輸入0表示結束):0
學號:1
姓名:wwu
成績:11
學號:2
姓名:wwf
成績:22
*/
#endif
//-----------------------------------------------------------------------------
#if 0 // 20 標準庫查找算法
#include <iostream>
#include <list>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct Student
{
unsigned int number; // 學號
string name;
};
struct Score // 成績
{
unsigned int number; // 學號
float mark; // 分數
};
struct StudentScoreManager // 學生成績管理類
{
public:
void InputStudents();
void InputScores();
void OutputScores() const;
private:
vector<Student> students;
list<Score> scores;
};
void StudentScoreManager::InputStudents()
{
unsigned int number = 1; // 學號從1開始
while(true)
{
cout << "請輸入" << number << "號學生姓名(輸入x表示結束):";
string name;
getline(cin, name);
if (name == "x")
{
break;
}
Student student;
student.number = number;
student.name = name;
students.push_back(student);
++number;
}
}
struct CompareByNumber_Equal
{
unsigned int number; // 學號
bool operator () (Score const & current_score) const // 函數對象
{
return (current_score.number == number);
}
};
void StudentScoreManager::InputScores()
{
while(true)
{
unsigned int number;
cout << "請輸入學號(輸入0表示結束):";
cin >> number;
if (number == 0)
{
break;
}
//簡單判斷學號是否正確:
if (number > students.size())
{
cout << "錯誤:學號必須位於: 1 ~ " << students.size() << " 之間。" << endl;
continue;
}
float mark;
cout << "請輸入該學員成績:";
cin >> mark;
Score score;
score.number = number;
score.mark = mark;
scores.push_back(score);
}
}
void StudentScoreManager::OutputScores() const
{
for (unsigned int i=0; i<students.size(); ++i)
{
unsigned int number = students[i].number; //學號
cout << "學號:" << number << endl;
cout << "姓名:" << students[i].name << endl;
// 查找成績:
CompareByNumber_Equal cmp;
cmp.number = number;
// STL 查找函數
list<Score>::const_iterator iter = find_if(scores.begin(), scores.end(), cmp);
if (iter != scores.end())
{
cout << "成績:" << iter->mark << endl;
}
else // 沒找到
{
cout << "成績:" << "查無成績。" << endl;
}
}
}
int main()
{
StudentScoreManager ssm;
ssm.InputStudents();
ssm.InputScores();
ssm.OutputScores();
system("pause");
return 0;
}
#endif
//-----------------------------------------------------------------------------
#if 0 // 21 成績管理系統2(標準庫排序算法)
// scores.sort(cmp)有點問題,在線OK:https://www.onlinegdb.com/
// cannot convert parameter 1 from 'struct CompareByMarkBigger'
// to 'struct std::greater<struct Score>
#include <iostream>
#include <list>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct Student // 學生
{
unsigned int number; // 學號
string name; // 姓名
};
struct Score // 成績
{
unsigned int number; // 學號
float mark; // 分數
};
struct StudentScoreManager // 學生成績管理類
{
public:
void InputStudents(); // 錄入學生基本信息(錄入前自動清空原有數據)
void InputScores(); // 錄入成績(錄入前不清空原有數據)
void ClearScores(); // 清空成績數據
void OutputScoresByNumber() const; // 以學號次序,輸出每個學生信息,包括成績
void OutputScoresByMark() const; // 以分數排名,輸出每個成績,包括學生基本信息
void FindStudentByNumber() const; // 通過學號,查找學生,顯示姓名,學號,成績
void FindStudentByName() const; // 通過姓名,查找學生,顯示姓名,學號,成績
private:
// 內部調用的函數:
// 給定一個學號,在scores中查找,並輸出其分數
void FindScoreByNumber(unsigned int number) const;
vector<Student> students;
list<Score> scores;
};
// 檢查是否輸入有誤,如有,則清除出錯狀態,並返回「真」.
bool CheckInputFail()
{
if (cin.fail ()) // 檢查 cin是不是出錯了?
{
// 出錯了...
cin.clear(); // 清除cin當前可能處於錯誤狀態
cin.sync(); // 再清除當前所有未處理的輸入
cout << "輸入有誤,請重新處理。" << endl;
return true;
}
return false;
}
// 輸入學生成績
void StudentScoreManager::InputStudents()
{
// 檢查是否已經有數據:
if (students.empty() == false)
{
cout << "確信要重新錄入學生基本信息嗎?(y/n)";
char c;
cin >> c;
if (c != 'y')
{
return;
}
cin.sync(); // 吃掉回車鍵.
}
// 因為允許用戶重新錄入,所以現在需要清除原有數據
students.clear();
unsigned int number = 1; // 學號從1開始
while(true)
{
cout << "請輸入學生姓名(輸入x表示結束), " << number << "號:";
string name;
getline(cin, name);
if (name == "x")
{
break;
}
Student student;
student.number = number;
student.name = name;
students.push_back(student);
++number;
}
}
// 比較器:比較姓名是否相等
// 用於在students中查找指定姓名的學生
struct CompareByName4Find
{
bool operator () (Student student) const
{
return student.name == name;
}
// 待查找的姓名
string name;
};
// 比較器:比較成績中的學號是否相等
// 用於在 scores中查找指定學號的成績
struct CompareByNumber_Equal4Find
{
bool operator () (Score s) const
{
return (s.number == number);
}
unsigned int number;
};
// 內部調用的函數:
// 給定一個學號,在scores中查找,並輸出其分數
void StudentScoreManager::FindScoreByNumber(unsigned int number) const
{
CompareByNumber_Equal4Find cbne;
cbne.number = number;
list<Score>::const_iterator itScore = find_if(scores.begin(), scores.end(), cbne);
if (itScore == scores.end())
{
// 找不到成績:
cout << ",成績:查無成績。";
}
else
{
// 查到成績了,顯示:
cout << ",成績:" << itScore->mark;
}
}
// 通過學號查到詳細信息
void StudentScoreManager::FindStudentByNumber() const
{
cout << "請輸入要查找的學號:";
unsigned int number;
cin >> number;
// 用戶輸入非數字字符時,此時檢查出錯誤
if (CheckInputFail())
{
return;
}
// 檢查是不是在合法範圍內的學號:
unsigned int maxNumber = students.size();
if (number > maxNumber)
{
cout << "學號只允許在 1~" << maxNumber << " 之間!" << endl;
return;
}
cout << "學號:" << number;
cout << ",姓名:" << students[number - 1].name;
// 繼續查:用學號查分數:
FindScoreByNumber(number);
cout << endl;
}
// 通過姓名查找到學生基本信息,然後再通過學號找到學生成績。
// 逐步顯示查到的結果。如果有多個同名學生,則全部輸出。
void StudentScoreManager::FindStudentByName() const
{
cout << "請輸入待查找的學員姓名:";
string name;
getline(cin, name);
CompareByName4Find cmp;
cmp.name = name;
int foundCount = 0; // 已經查找到幾個人了?
vector<Student>::const_iterator beg = students.begin(); // 從哪裡查起
while(true)
{
// 查找學生,注意查找範圍為: beg ~ students.end()
beg = find_if(beg, students.end(), cmp);
if (beg == students.end())
{
break; // 找不到人了...結束循環
}
// 查到該學生了...
++foundCount; // 找到的人數加1。
// 顯示學生基本信息:
cout << "姓名:" << name;
cout << ",學號:" << beg->number;
// 繼續查:用學號查分數:
FindScoreByNumber(beg->number);
cout << endl;
// 重要:將beg前進到下一個位置,
// 意思是:下次查找時,將從當前找到的那學生的下一個位置開始找起
beg++;
}
cout << "總共查到" << foundCount << "位學生,名為:" << name << endl;
}
// 根據學號的次序輸出學生成績,沒有成績的學員,顯示「查無成績」
void StudentScoreManager::OutputScoresByNumber() const
{
for (unsigned int i=0; i<students.size(); ++i)
{
unsigned int number = students[i].number; // 學號
cout << "學號:" << number;
cout << ",姓名:" << students[i].name;
// 查找成績:
CompareByNumber_Equal4Find cmp;
cmp.number = number;
list<Score>::const_iterator iter = find_if(scores.begin(), scores.end(), cmp);
if (iter != scores.end())
{
cout << ",成績:" << iter->mark << endl;
}
else // 沒找到
{
cout << ",成績:" << "查無成績。" << endl;
}
}
}
// 比較器:比較成績中的分數高低
// 在InputScores()中,錄入成績之後,會立即使用本比較對成績進行排序
struct CompareByMarkBigger
{
bool operator () (Score s1, Score s2) const
{
return (s1.mark > s2.mark);
}
};
// 錄入學生成績,錄入完成後即行排序
void StudentScoreManager::InputScores()
{
while(true)
{
unsigned int number;
cout << "請輸入學號(輸入0表示結束):";
cin >> number;
// 檢查用戶輸入是不是合法的數字
if (CheckInputFail())
{
continue;
}
if (number == 0)
{
break;
}
// 判斷學號大小是否在合法的範圍內:
if (number > students.size())
{
cout << "錯誤:學號必須位於: 1 ~ " << students.size() << " 之間。" << endl;
continue;
}
float mark;
cout << "請輸入成績(" << students[number-1].name << "):"; // 本版此處新增了姓名提示
cin >> mark;
// 檢查用戶輸入是不是合法的浮點數
if (CheckInputFail())
{
continue;
}
Score score;
score.number = number;
score.mark = mark;
scores.push_back(score);
}
// 本版新增功能:錄入成績後,立即按分數高低排序
// 保證scores中的元素永遠是有序的
CompareByMarkBigger cmp;
scores.sort(cmp); // c++14 OK ,排序------------------------------------------------
}
// 清空成績
void StudentScoreManager::ClearScores()
{
cout << "您確信要清空全部成績數據? (y/n)";
char c;
cin >> c;
if (c == 'y')
{
scores.clear();
cout << "成績數據清除完畢!" << endl;
}
cin.sync();
}
// 按分數高低,輸出每個成績,包括學生姓名,沒有參加考試學員,將不會被輸出
void StudentScoreManager::OutputScoresByMark() const
{
// 在每次錄入成績之後,我們都會調用sort立即為所有成績進行排序
// 所以scores中的所有成績,已經是按高低分排序了
// 問題是:分數相同時必須處理「名次並列」的情況。
int index = 1; // 當前名次,排名從1開始
int count = 0; // 相同分數個數
double last = -1.0; // 上一次分數,剛開始時,初始化為一個不可能的分數
for (list<Score>::const_iterator it = scores.begin();
it != scores.end();
++it)
{
if (last != it->mark) // 新的分數出現
{
last = it->mark;
index += count;
count = 1;
}
else // 還是原來的分數(同分)
{
++count;
}
cout << "名次:" << index;
cout << ",姓名:" << students[it->number - 1].name; // 通過學號得到名字
cout << ",學號:" << it->number;
cout << ",成績:" << it->mark << endl;
}
}
void About()
{
system("cls");
cout << "學生成績管理系統 Ver 2.0" << endl;
cout << "copyright 2008~?" << endl;
cout << "作者:丁小聰" << endl;
cout << "來自:www.d2school.com/白話C++" << endl;
}
void Help()
{
system("cls");
cout << "1 錄入學生基本信息:" << endl
<< "請注意,重新錄入時,原有數據會清空!" << endl
<< endl;
cout << "2 錄入成績:" << endl
<< "請注意,會在原有成績數據上錄入,如果需要清空成績,請使用:清空成績。" << endl
<< endl;
cout << "3 清空成績:" << endl
<< "之前錄入的成績將被清除,本操作不可恢復。" << endl
<< endl;
cout << "4 按學號次序顯示成績:" << endl
<< "按學號從小到大輸出成績,包括姓名。未參加考試或還錄入成績學員,將顯示查無成績。" << endl
<< endl;
cout << "5 按分數名次顯示成績:" << endl
<< "按分數從高到低輸出成績,包括名次,學號,姓名等。" << endl
<< "忠告:聽說教育部禁止學校公布成績排名。" << endl
<< endl;
cout << "6 按學號查找學生:" << endl
<< "輸入學號,查找到指定學生的學生信息,包括成績。" << endl
<< endl;
cout << "7 按姓名查找學生:" << endl
<< "輸入姓名,查到到該名字的學生,並輸出其信息,包括成績,如有重名,連續輸出。" << endl
<< endl;
cout << "8 關於:關於本軟體的一些信息。" << endl << endl;
cout << "9 幫助:顯示本幫助信息。" << endl << endl;
cout << "0 退出:輸入0,退出本程序。" << endl << endl;
}
int Menu()
{
cout << "-------------------------------" << endl;
cout << "----學生成績管理系統 Ver2.0----" << endl;
cout << "-------------------------------" << endl;
cout << "請選擇:(0~9)" << endl;
cout << "1 錄入學生基本信息" << endl;
cout << "2 錄入成績" << endl;
cout << "3 清空成績" << endl;
cout << endl;
cout << "4 按學號次序顯示成績" << endl;
cout << "5 按分數名次顯示成績" << endl;
cout << endl;
cout << "6 按學號查找學生" << endl;
cout << "7 按姓名查找學生" << endl;
cout << endl;
cout << "8 關於" << endl;
cout << "9 幫助" << endl;
cout << endl;
cout << "0 退出" << endl;
int sel;
cin >> sel;
if (CheckInputFail())
{
return -1;
}
cin.sync(); //清掉輸入數字之後的 回車鍵
return sel;
}
int main()
{
StudentScoreManager ssm;
while(true)
{
int sel = Menu();
if (sel == 1)
{
ssm.InputStudents();
}
else if (sel == 2)
{
ssm.InputScores();
}
else if (sel == 3)
{
ssm.ClearScores();
}
else if (sel == 4)
{
ssm.OutputScoresByNumber();
}
else if (sel == 5)
{
ssm.OutputScoresByMark();
}
else if (sel == 6)
{
ssm.FindStudentByNumber();
}
else if (sel == 7)
{
ssm.FindStudentByName();
}
else if (sel == 8)
{
About();
}
else if (sel == 9)
{
Help();
}
else if (sel == 0)
{
break;
}
else // 什麼也不是..
{
cout << "請正確輸入選擇:範圍在 0 ~ 9 之內。" << endl;
}
system("Pause");
}
cout << "bye~bye~" << endl;
return 0;
}
#endif
//-----------------------------------------------------------------------------
#if 0 // 文件讀寫熱身
//getline(ifs, line);有點問題,在線OK:https://www.onlinegdb.com/
#include <iostream>
#include <fstream> // 'f' -> 'file'
using namespace std;
istream& skip_comma ( istream& str )
{
char c = str.peek();
if (c == ',')
{
return str.ignore();
}
return str;
}
int main()
{
ofstream ofs;
ofs.open("./hello_file_stream.txt");
ofs << "Hello world!" << endl;
ofs << "11,22,33" << endl << "44" << endl;
ofs << "1 2" << endl;
ofs.close();
ifstream ifs;
ifs.open("./hello_file_stream.txt");
if (!ifs)
{
cout << "open file fail!" << endl;
}
else
{
string line;
getline(ifs, line); // c++ 14 OK
cout << line << endl;
int n1,n2,n3,n4;
ifs >> n1 >> skip_comma >> n2 >> skip_comma >> n3;
cout << n1 << ", " << n2 << ", " << n3 << endl;
ifs >> n4;
cout << n4 << endl;
n1 = n2 = -1;
string spaces;
//char c;
ifs >> n1;
ifs.unsetf(ios::skipws);
ifs >> spaces;
ifs.setf(ios::skipws);
ifs >> n2;
cout << n1 << "," << spaces << n2 << endl;
}
return 0;
}
#endif
//-----------------------------------------------------------------------------
#if 0 // 22 STL文件篇
// 在線運行https://www.onlinegdb.com/
#include <iostream>
#include <list>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
using namespace std;
struct Student // 學生
{
unsigned int number; // 學號
string name; // 姓名
};
struct Score // 成績
{
unsigned int number; // 學號
float mark; // 分數
};
struct StudentScoreManager // 學生成績管理類
{
public:
void InputStudents(); // 錄入學生基本信息(錄入前自動清空原有數據)
void SaveStudents() const; // 保存學生基體信息到文件
void LoadStudents(); // 從文件中讀入學生基本信息。
void InputScores(); // 錄入成績(錄入前不清空原有數據)
void ClearScores(); // 清空成績數據
void OutputScoresByNumber() const; // 以學號次序,輸出每個學生信息,包括成績
void OutputScoresByMark() const; // 以分數排名,輸出每個成績,包括學生基本信息
void FindStudentByNumber() const; // 通過學號,查找學生,顯示姓名,學號,成績
void FindStudentByName() const; // 通過姓名,查找學生,顯示姓名,學號,成績
private:
//內 部調用的函數:
// 給定一個學號,在scores中查找,並輸出其分數
void FindScoreByNumber(unsigned int number) const;
vector<Student> students;
list<Score> scores;
};
// 檢查是否輸入有誤,如有,則清除出錯狀態,並返回「真」.
bool CheckInputFail()
{
if (cin.fail ()) // 檢查 cin是不是出錯了?
{
// 出錯了...
cin.clear(); // 清除cin當前可能處於錯誤狀態
cin.sync(); // 再清除當前所有未處理的輸入
cout << "輸入有誤,請重新處理。" << endl;
return true;
}
return false;
}
// 輸入學生成績
void StudentScoreManager::InputStudents()
{
// 檢查是否已經有數據:
if (students.empty() == false)
{
cout << "確信要重新錄入學生基本信息嗎?(y/n)";
char c;
cin >> c;
if (c != 'y')
{
return;
}
cin.sync(); // 吃掉回車鍵.
}
// 因為允許用戶重新錄入,所以現在需要清除原有數據
students.clear();
unsigned int number = 1; // 學號從1開始
while(true)
{
cout << "請輸入學生姓名(輸入x表示結束), " << number << "號:";
string name;
getline(cin, name);
if (name == "x")
{
break;
}
Student student;
student.number = number;
student.name = name;
students.push_back(student);
++number;
}
}
//保存學生基本信息到特定的文件中:--------------------------------------
void StudentScoreManager::SaveStudents() const
{
ofstream ofs;
ofs.open(".\\students_base_info.txt");
if (!ofs)
{
cout << "打開成績輸出文件失敗!" << endl;
return;
}
// 特意輸入學員個數,方便於後面的讀文件過程
unsigned int count = students.size();
ofs << count << endl;
for (unsigned int i=0; i<count; ++i)
{
ofs << students[i].number << endl;
ofs << students[i].name << endl;
}
ofs.close();
cout << "保存完畢,共保存" << count << "位學生基本信息。" << endl;
}
// 從特定的文件中,讀入學生基本信息:
void StudentScoreManager::LoadStudents()
{
ifstream ifs;
ifs.open(".\\students_base_info.txt");
if (!ifs)
{
cout << "打開成績輸入文件失敗!" << endl;
return;
}
students.clear(); // 清除原來的學生數據
unsigned int count = 0;
ifs >> count; // 讀入個數
for (unsigned int i=0; i<count; ++i)
{
Student stu;
ifs >> stu.number;
ifs.ignore(); // 替後續的getline跳過:學號之後的換行符
getline(ifs, stu.name); // 讀入姓名
students.push_back(stu); // 加入
}
cout << "加載完畢,共加載:" << count << "位學生的基本信息。" << endl;
}
// 比較器:比較姓名是否相等
// 用於在students中查找指定姓名的學生
struct CompareByName4Find
{
bool operator () (Student student) const
{
return student.name == name;
}
// 待查找的姓名
string name;
};
// 比較器:比較成績中的學號是否相等
// 用於在 scores中查找指定學號的成績
struct CompareByNumber_Equal4Find
{
bool operator () (Score s) const
{
return (s.number == number);
}
unsigned int number;
};
// 內部調用的函數:
// 給定一個學號,在scores中查找,並輸出其分數
void StudentScoreManager::FindScoreByNumber(unsigned int number) const
{
CompareByNumber_Equal4Find cbne;
cbne.number = number;
list<Score>::const_iterator itScore = find_if(scores.begin(), scores.end(), cbne);
if (itScore == scores.end())
{
// 找不到成績:
cout << ",成績:查無成績。";
}
else
{
// 查到成績了,顯示:
cout << ",成績:" << itScore->mark;
}
}
// 通過學號查到詳細信息
void StudentScoreManager::FindStudentByNumber() const
{
cout << "請輸入要查找的學號:";
unsigned int number;
cin >> number;
// 用戶輸入非數字字符時,此時檢查出錯誤
if (CheckInputFail())
{
return;
}
// 檢查是不是在合法範圍內的學號:
unsigned int maxNumber = students.size();
if (number > maxNumber)
{
cout << "學號只允許在 1~" << maxNumber << " 之間!" << endl;
return;
}
cout << "學號:" << number;
cout << ",姓名:" << students[number - 1].name;
// 繼續查:用學號查分數:
FindScoreByNumber(number);
cout << endl;
}
// 通過姓名查找到學生基本信息,然後再通過學號找到學生成績。
// 逐步顯示查到的結果。如果有多個同名學生,則全部輸出。
void StudentScoreManager::FindStudentByName() const
{
cout << "請輸入待查找的學員姓名:";
string name;
getline(cin, name);
CompareByName4Find cmp;
cmp.name = name;
int foundCount = 0; // 已經查找到幾個人了?
vector<Student>::const_iterator itStu = students.begin(); // 從哪裡查起
while(itStu != students.end())
{
// 查找學生,注意查找範圍為: itStu ~ students.end()
itStu = find_if(itStu, students.end(), cmp);
if (itStu == students.end())
{
break; // 找不到人了...結束循環
}
// 查到該學生了...
++foundCount; // 找到的人數加1。
//顯示學生基本信息:
cout << "姓名:" << name;
cout << ",學號:" << itStu->number;
// 繼續查:用學號查分數:
FindScoreByNumber(itStu->number);
cout << endl;
// 重要:將itStu前進到下一個位置,
// 意思是:下次查找時,將從當前找到的那學生的下一個位置開始找起
itStu++;
}
cout << "總共查到" << foundCount << "位學生,名為:" << name << endl;
}
// 根據學號的次序輸出學生成績,沒有成績的學員,顯示「查無成績」
void StudentScoreManager::OutputScoresByNumber() const
{
for (unsigned int i=0; i<students.size(); ++i)
{
unsigned int number = students[i].number; //學號
cout << "學號:" << number;
cout << ",姓名:" << students[i].name;
// 查找成績:
CompareByNumber_Equal4Find cmp;
cmp.number = number;
list<Score>::const_iterator iter = find_if(scores.begin(), scores.end(), cmp);
if (iter != scores.end())
{
cout << ",成績:" << iter->mark << endl;
}
else // 沒找到
{
cout << ",成績:" << "查無成績。" << endl;
}
}
}
// 比較器:比較成績中的分數高低
// 在InputScores()中,錄入成績之後,會立即使用本比較對成績進行排序
struct CompareByMarkBigger
{
bool operator () (Score s1, Score s2) const
{
return (s1.mark > s2.mark);
}
};
// 錄入學生成績,錄入完成後即行排序
void StudentScoreManager::InputScores()
{
while(true)
{
unsigned int number;
cout << "請輸入學號(輸入0表示結束):";
cin >> number;
// 檢查用戶輸入是不是合法的數字
if (CheckInputFail())
{
continue;
}
if (number == 0)
{
break;
}
// 判斷學號大小是否在合法的範圍內:
if (number > students.size())
{
cout << "錯誤:學號必須位於: 1 ~ " << students.size() << " 之間。" << endl;
continue;
}
float mark;
cout << "請輸入成績(" << students[number-1].name << "):"; // 本版此處新增了姓名提示
cin >> mark;
// 檢查用戶輸入是不是合法的浮點數
if (CheckInputFail())
{
continue;
}
Score score;
score.number = number;
score.mark = mark;
scores.push_back(score);
}
// 本版新增功能:錄入成績後,立即按分數高低排序
// 保證scores中的元素永遠是有序的
CompareByMarkBigger cmp;
scores.sort(cmp);
}
// 清空成績
void StudentScoreManager::ClearScores()
{
cout << "您確信要清空全部成績數據? (y/n)";
char c;
cin >> c;
if (c == 'y')
{
scores.clear();
cout << "成績數據清除完畢!" << endl;
}
cin.sync();
}
// 按分數高低,輸出每個成績,包括學生姓名,沒有參加考試學員,將不會被輸出
void StudentScoreManager::OutputScoresByMark() const
{
// 在每次錄入成績之後,我們都會調用sort立即為所有成績進行排序
// 所以scores中的所有成績,已經是按高低分排序了
// 問題是:分數相同時必須處理「名次並列」的情況。
int currentIndex = 1; //當前名次,排名從1開始
int sameMarkCount = 0; //相同分數個數
double lastMark= -1; //上一次分數,剛開始時,初始化為一個不可能的分數
for (list<Score>::const_iterator it = scores.begin();
it != scores.end();
++it)
{
if (lastMark != it->mark)
{
lastMark = it->mark;
currentIndex += sameMarkCount;
sameMarkCount = 1;
}
else // 分數相同
{
++sameMarkCount;
}
cout << "名次:" << currentIndex;
cout << ",姓名:" << students[it->number - 1].name; // 通過學號得到名字
cout << ",學號:" << it->number;
cout << ",成績:" << it->mark << endl;
}
}
void About()
{
system("cls");
cout << "學生成績管理系統 Ver 3.0" << endl;
cout << "copyright 2008~?" << endl;
cout << "作者:丁小聰" << endl;
cout << "來自:www.d2school.com/白話C++" << endl;
}
void Help()
{
system("cls");
cout << "1 錄入學生基本信息:" << endl
<< "請注意,重新錄入時,原有數據會清空!" << endl
<< endl;
cout << "2 錄入成績:" << endl
<< "請注意,會在原有成績數據上錄入,如果需要清空成績,請使用:清空成績。" << endl
<< endl;
cout << "3 清空成績:" << endl
<< "之前錄入的成績將被清除,本操作不可恢復。" << endl
<< endl;
cout << "4 按學號次序顯示成績:" << endl
<< "按學號從小到大輸出成績,包括姓名。未參加考試或還錄入成績學員,將顯示查無成績。" << endl
<< endl;
cout << "5 按分數名次顯示成績:" << endl
<< "按分數從高到低輸出成績,包括名次,學號,姓名等。" << endl
<< "忠告:教育部禁止學校公布成績排名。" << endl
<< endl;
cout << "6 按學號查找學生:" << endl
<< "輸入學號,查找到指定學生的學生信息,包括成績。" << endl
<< endl;
cout << "7 按姓名查找學生:" << endl
<< "輸入姓名,查到到該名字的學生,並輸出其信息,包括成績,如有重名,連續輸出。" << endl
<< endl;
cout << "8 加載學生基本信息:" << endl
<< "如果曾經保存學生基本信息,則從該文件讀出學生基本信息,注意:當前已有的學生信息將丟失!"
<< endl << endl;
cout << "9 保存學生基本信息:" << endl
<< "保存當前學生基本信息到文件,如果已經原有文件,則原有文件內容將被刷新!"
<< endl << endl;
cout << "10 關於:關於本軟體的一些信息。" << endl << endl;
cout << "11 幫助:顯示本幫助信息。" << endl << endl;
cout << "0 退出:輸入0,退出本程序。" << endl << endl;
}
int Menu()
{
cout << "-------------------------------" << endl;
cout << "----學生成績管理系統 Ver3.0----" << endl;
cout << "-------------------------------" << endl;
cout << "請選擇:(0~9)" << endl;
cout << "1 錄入學生基本信息" << endl;
cout << "2 錄入成績" << endl;
cout << "3 清空成績" << endl;
cout << endl;
cout << "4 按學號次序顯示成績" << endl;
cout << "5 按分數名次顯示成績" << endl;
cout << endl;
cout << "6 按學號查找學生" << endl;
cout << "7 按姓名查找學生" << endl;
cout << endl;
cout << "8 加載學生基本信息" << endl;
cout << "9 保存學生基本文件" << endl;
cout << endl;
cout << "10 關於" << endl;
cout << "11 幫助" << endl;
cout << endl;
cout << "0 退出" << endl;
int sel;
cin >> sel;
if (CheckInputFail())
{
return -1;
}
cin.sync(); // 清掉輸入數字之後的 回車鍵
return sel;
}
int main()
{
StudentScoreManager ssm;
while(true)
{
int sel = Menu();
if (sel == 1)
{
ssm.InputStudents();
}
else if (sel == 2)
{
ssm.InputScores();
}
else if (sel == 3)
{
ssm.ClearScores();
}
else if (sel == 4)
{
ssm.OutputScoresByNumber();
}
else if (sel == 5)
{
ssm.OutputScoresByMark();
}
else if (sel == 6)
{
ssm.FindStudentByNumber();
}
else if (sel == 7)
{
ssm.FindStudentByName();
}
else if (sel == 8)
{
ssm.LoadStudents();
}
else if (sel == 9)
{
ssm.SaveStudents();
}
else if (sel == 10)
{
About();
}
else if (sel == 11)
{
Help();
}
else if (sel == 0)
{
break;
}
else // 什麼也不是..
{
cout << "請正確輸入選擇:範圍在 0 ~ 11 之內。" << endl;
}
system("Pause");
}
cout << "bye~bye~" << endl;
return 0;
}
#endif
// https://www.onlinegdb.com/
-End-