# 東華大學資管系進階程式設計112年考古
## 相關資訊
課程代碼:IM__11300 -進階程式設計
老師:劉英和教授
使用程式:C++
[初階考古](https://hackmd.io/@sumo0711/SyFipiOfA)
## 免責申明
:::danger
此文件僅為個人參考解答,並非標準答案。請僅供個人學習使用,切勿用於商業用途,如有侵權請寫信告知。
:::
# 進階實習題
## char array
### Description
請撰寫一支程式,該程式讓使用者輸入姓名、性別、出生年月日(皆為不包含空格的字串,每個字串長度不超過512個字元),使用者輸入後,程式再輸出此三項資訊。請用C-string(char array)儲存字串。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input your name, sex, and birthday:
**Einstein**
**male**
**1879/3/14**
Your name is Einstein
Your sex is male
Your Birthday is 1879/3/14
### Solution
```cpp=
#include <iostream>
using namespace std;
int main()
{
const int lenth = 512;
char name[lenth], sex[lenth], birth[lenth];
cout << "Please input your name, sex, and birthday: " << endl;
cin >> name >> sex >> birth;
cout << "Your name is " << name << endl
<< "Your sex is " << sex << endl
<< "Your Birthday is " << birth;
return 0;
}
```
## cstring
### Description
請撰寫一完整程式,當中宣告三個長度皆為512的 C-string(char array),名稱分別為str1, str2, str3;接著讓使用者輸入str1及str2的值(需要包含使用者輸入的空白),之後程式會輸出str1是否等於str2(需輸出“equal” 或是 “not equal”於螢幕上);接下來,將str2的值assign給str3,再把str1及str3的內容串接後輸出在螢幕上。(假設不考量array長度是否足夠)
(程式輸入、輸出資料前,請先輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input two strings:
**abc**
**def**
not equal
The concatenated string is abcdef
### Solution
```cpp=
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const int lenth = 512;
char str1[lenth], str2[lenth], str3[lenth];
cout << "Please input two strings: " << endl;
cin.getline(str1, lenth); // char 的 getline 要 cin.getline
cin.getline(str2, lenth); // getline 包含空白
if (strcmp(str1, str2) == 0) // 如果 str1 str2 相等 會回傳 0
cout << "equal\n";
else
cout << "not equal\n";
strcpy(str3, str2); // 將 str2 的值 assign 給 str3
strcat(str1, str3); // 把 str3 串接到 str1 後面
cout << "The concatenated string is " << str1;
return 0;
}
```
## string
### Description
請撰寫一完整程式,當中宣告三個data type為string的變數,名稱分別為str1, str2, str3;接著讓使用者輸入str1及str2的值(需要包含使用者輸入的空白),之後程式會輸出str1是否等於str2(需輸出“equal” 或是 “not equal”於螢幕上);接下來,將str2的值assign給str3,再把str1及str3的內容串接後輸出在螢幕上。(程式輸入、輸出資料前,請先輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input two strings:
**abc**
**def**
not equal
The concatenated string is abcdef
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1, str2, str3;
cout << "Please input two strings:\n";
getline(cin, str1); // string 的 getline 不用加 cin.getline
getline(cin, str2); // getline 包含空白
if (str1 == str2)
cout << "equal\n";
else
cout << "not equal\n";
str3 = str2;
cout << "The concatenated string is " << str1 + str3;
return 0;
}
```
## string-2
### Description
東華銀行欲推出小孩存款方案,故先行調查現今小孩的零用錢多寡。附件PocketMoney.txt中記錄所收集來的每個小孩的每月零用錢。請撰寫一支程式從該檔案中讀取零用錢金額,並且計算所有男孩的零用錢總和與所有女孩的零用錢總和後輸出於螢幕上。(撰寫程式時並不知道檔案中男孩、女孩數量會有多少。請檢查開啟檔案是否失敗。)
提示:使用 string 這個 data type 處理字串。先確認每一行是男孩(boy)還是女孩(girl),再取出 $ 符號後的數字字串,轉成整數後再加總。
### Example
**PocketMoney.txt**
```
Andrew, boy, $5000
Bob, boy, $3000
Lisa, girl, $4000
Charlie, boy, $2050
Mary, girl, $6000
```
**Output**
The sum of boys is 10050
The sum of girls is 10000
### Solution
```cpp=
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream PocketMoney;
PocketMoney.open("PocketMoney.txt");
if (PocketMoney.fail())
{
cout << "Input PocketMoney opening failed.\n";
exit(1);
}
int BoyTotal = 0, GirlTotal = 0;
string line;
while (getline(PocketMoney, line)) // 逐行檢查是否包含 "boy" 或 "girl",getline包含空白
{
if (line.find("boy") != string::npos) // 如果此行有包含 boy 就進去做
BoyTotal += stoi(line.substr(line.find("$") + 1));
else if (line.find("girl") != string::npos) // 如果此行有包含 girl 就進去做
GirlTotal += stoi(line.substr(line.find("$") + 1));
}
cout << "The sum of boys is " << BoyTotal << endl;
cout << "The sum of girls is " << GirlTotal << endl;
PocketMoney.close();
return 0;
}
/*
BoyTotal += stoi(line.substr(line.find("$") + 1));
-------------------------
int money = line.find("$"); find 回傳值是一個 int,找不到則會回傳 npos
string number = line.substr(money + 1); 將 $ 後面的字串存到 number,為什麼要 +1,因為我不要 $ 字號
BoyTotal += stoi(number) 將這段字串 stoi 轉成 int 加總進 BoyTotal
*/
```
## vector
### Description
請為教務處撰寫一完整程式以計算學生的平均分數,該程式可讓使用者一一輸入每位學生的分數(分數為一大於0的正整數,學生人數未知,若輸入一個負數代表輸入結束)
在求出這些學生的平均分數後,於螢幕上輸出每一個分數及平均分數(平均分數請輸出至小數點後兩位)
請宣告一個base type為int的vector變數Scores,並將使用者輸入的分數儲存於Scores中。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input the scores:
**100**
**82**
**96**
-1
The scores are 100 82 96
The average is 92.67
### Solution
```cpp=
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
int main()
{
vector<int> scores;
double sum = 0;
int input;
cout << "Please input the scores:\n";
do
{
cin >> input;
if (input > 0) // 如果使用者輸入大於 0
{
scores.push_back(input); // 將數字 assign 給 scores
sum += input;
}
else
break; // 跳出 do while loop
} while (true);
cout << "The scores are ";
for (int i = 0; i < scores.size(); i++) // .size() 會把 vector 裡面的資料數印出來
cout << scores[i] << " ";
cout << "\nThe average is " << fixed << setprecision(2) << sum / scores.size();
return 0;
}
```
## insert
### Description
請撰寫一完整程式,當中宣告一個base type為string的vector變數vec,接下來以for loop讓使用者輸入4個字串儲存在vec中(字串可包含空格),接著將輸入的第二個字串插入在第一個字串中(於第一個字串的第二個element處插入),再將輸入的第四個字串插入在第三個字串中(於第三個字串的第四個element處插入),最後輸出經上述作法處理過後的四個字串於螢幕上。 (程式輸入、輸出資料前,請先輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input four strings:
**I like swimming.**
空白鍵**do not**
**I'm a student.**
空白鍵**not**
The four strings are:
I do not like swimming.
空白鍵do not
I'm not a student.
空白鍵not
### Solution
```cpp=
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> vec;
string line;
cout << "Please input four strings:\n";
for (int i = 0; i < 4; i++) // 輸入四行字串
{
getline(cin, line);
vec.push_back(line);
}
cout << "The four strings are:\n"
<< vec[0].insert(1, vec[1]) << endl // 插入的主字串.insert(要從第幾個字元插入 , 要插入的字串)
<< vec[1] << endl
<< vec[2].insert(3, vec[3]) << endl
<< vec[3];
return 0;
}
```
## pointer
### Description
請撰寫一完整程式,當中宣告一個data type為string的pointer變數str ,接著讓使用者輸入接下來要輸入多少個名字(不包含空格的字串)後,將str宣告為長度為名字數量的dynamic array,接著讓使用者一一輸入名字並儲存於str中,再將每個名字輸出於螢幕上。(程式輸入、輸出資料前,請先輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
How many names do you want to input?
**3**
Please input names:
**Alex**
**Bob**
**Charlie**
The names are:
Alex
Bob
Charlie
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
int main()
{
int choose;
cout << "How many names do you want to input?\n";
cin >> choose; // pointer長度
string *str = new string[choose]; // new 會給他一個未使用的記憶體
cout << "Please input names:\n";
for (int i = 0; i < choose; i++)
cin >> str[i];
cout << "The names are:\n";
for (int i = 0; i < choose; i++)
cout << str[i] << endl;
delete[] str; // 釋放記憶體
return 0;
}
```
## pointer-2
### Description
請撰寫一完整程式,當中宣告一個data type為string的pointer變數str,接著開啟一個檔案strings.txt(需檢查開啟檔案是否失敗,失敗則結束程式),該檔案中存在多個字串(每行一個字串,字串可包含空格,但假設所含的字串個數事先未知,見範例檔),請將每個字串讀入程式並存在str變數中,接著讓使用者輸入一個英文名字,並輸出strings.txt中所記載的字串中,有多少個字串出現該英文名字。(程式輸入、輸出資料前,請先輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input a name:
**Alice**
The number of hits is 2
### Solution
```cpp=
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
int n = 0, hits = 0;
string line, name;
ifstream strings("strings.txt");
if (strings.fail())
{
cout << "Input strings opening failed.\n";
exit(1);
}
while (getline(strings, line)) // 記錄 strings.txt 有幾行
n++;
strings.close();
strings.open("strings.txt"); // 重新開啟檔案以讀取字串
if (strings.fail())
{
cout << "Input strings opening failed.\n";
exit(1);
}
string *str = new string[n];
cout << "Please input a name:\n";
cin >> name;
for (int i = 0; i < n; i++)
{
getline(strings, str[i]); // 將字串一一讀出並儲存在str中
if (str[i].find(name) != string::npos) // 如果在該行找到使用者輸入的名子
hits++; // 記錄搜尋到的次數
}
strings.close();
cout << "The number of hits is " << hits << endl;
delete[] str; // 釋放記憶體
return 0;
}
```
## struct
### Description
請撰寫一完整程式,當中宣告一struct名為Car,該struct包含兩個member variable,其一為data type為string的name,其二為data type為int的displacement。另宣告一struct名為PersonInfo,該struct包含兩個member variable,其一為data type為string的變數name,其二為data type為Car的變數OwnCar。在main function中宣告一個PersonInfo的變數,並讓使用者輸入其兩個member variable的值,再將使用者輸入的值輸出在螢幕上。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input your name and data about your car:
**Tom**
**Mondeo**
**2000**
Your name is Tom
The name of your car is Mondeo
The displacement of your car is 2000
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
struct Car
{
string name;
int displacement;
};
struct PersonInfo
{
string name;
Car OwnCar;
};
int main()
{
PersonInfo p;
cout << "Please input your name and data about your car:\n";
cin >> p.name >> p.OwnCar.name >> p.OwnCar.displacement;
cout << "Your name is " << p.name << endl
<< "name of your car is " << p.OwnCar.name << endl
<< "The displacement of your car is " << p.OwnCar.displacement;
return 0;
}
```
## struct-2
### Description
承上題,請撰寫一完整程式,當中包含上題之Car與PersonInfo兩個data type,在main function中宣告一base type為PersonInfo的vector變數,並讓使用者輸入兩個人的資料(name與OwnCar這兩個member variable的值)存於該vector變數中,最後再輸出所輸入的資料。(提示:使用 push_back 這個 member function 將一個 PersonInfo 的變數輸入所宣告的 vector 變數中。)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input info of two people:
Input the name and car data of the first person:
**Andy**
**Kuga**
**2000**
Input the name and car data of the second person:
**Bob**
**Altis**
**1800**
The name and car data of the two people are:
Andy
Kuga
2000
Bob
Altis
1800
### Solution
```cpp=
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Car
{
string name;
int displacement;
};
struct PersonInfo
{
string name;
Car OwnCar;
};
int main()
{
vector<PersonInfo> vec;
PersonInfo p;
cout << "Please input info of two people:\nInput the name and car data of the first person:\n";
cin >> p.name >> p.OwnCar.name >> p.OwnCar.displacement;
vec.push_back(p);
cout << "Input the name and car data of the second person:\n";
cin >> p.name >> p.OwnCar.name >> p.OwnCar.displacement;
vec.push_back(p);
cout << "The name and car data of the two people are:\n";
for (PersonInfo &b : vec) // range-based for loop
cout << b.name << endl
<< b.OwnCar.name << endl
<< b.OwnCar.displacement << endl
<< endl;
return 0;
}
```
## class&constructor
### Description
請為汽車公司撰寫一程式以記錄汽車的資訊,當中宣告一class名為Car,該class包含兩個member variable,其一為data type為string的name,其二為data type為int的displacement。並且加入一member function為 Input,其沒有回傳值,兩個參數分別是data type為string的 model_name 跟 data type為 int 的model_displacement,在Input中,會把 name 跟 displacement 的值分別設定為 model_name及 model_displacement 的值。
另有兩 member function為 get_name及get_displacement,分別回傳 name及 displacement的值。(請將member function設定為public,member variable設定為private)
Car有一default constructor,其中會把name的值設為空字串(“”),把displacement的值設為0。另有一constructor有兩個參數,兩個參數分別是data type為string的 model_name 跟 data type為 int 的model_displacement,在該constructor中,會把 name 跟 displacement 的值分別設定為 model_name及 model_displacement 的值。
接著,在main function中請宣告一個Car的變數 YourCar,並讓使用者填入車的資料(名字及排氣量),最後再將使用者輸入的值一一輸出在螢幕上。另宣告一個Car變數MyCar,其宣告為 Car MyCar(Kuga, 2000); 隨後也輸出該變數的兩個member variable的值於螢幕上。
(程式輸入、輸出資料前,請先輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input the name and displacement of your car:
**Sentra**
**1600**
The name of your car is Sentra
The displacement of your car is 1600
The name of my car is Kuga
The displacement of my car is 2000
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
class Car
{
public:
void Input(string model_name, int model_displacement);
string get_name();
int get_displacement();
Car();
Car(string model_name, int model_displacement);
private:
string name;
int displacement;
};
int main()
{
Car YourCar, MyCar("Kuga", 2000);
string YourCar_name;
int YourCar_displacement;
cout << "Please input the name and displacement of your car:\n";
cin >> YourCar_name >> YourCar_displacement;
YourCar.Input(YourCar_name, YourCar_displacement);
cout << "The name of your car is " << YourCar.get_name() << endl
<< "The displacement of your car is " << YourCar.get_displacement() << endl
<< "The name of my car is " << MyCar.get_name() << endl
<< "The displacement of my car is " << MyCar.get_displacement();
return 0;
}
void Car::Input(string model_name, int model_displacement)
{
name = model_name;
displacement = model_displacement;
}
string Car::get_name()
{
return name;
}
int Car::get_displacement()
{
return displacement;
}
Car::Car()
{
name = "";
displacement = 0;
}
Car::Car(string model_name, int model_displacement)
{
name = model_name;
displacement = model_displacement;
}
```
## friend
### Description
請設計一class名為Money,其有兩個member variable,分別為data type為string的Currency與float的Amount,分別代表幣別與金額。其default constructor將兩個member variable分別設為NT與0。另有一包含兩個參數的constructor,其將兩參數的值分別設定給兩個member variable。Money有兩個friend function,分別為Add與Subtract。
Add有兩個Money的參數,會回傳一Money變數,其運作方式如下:
1.先檢查兩個Money參數的幣別是否一致,假設幣別只有兩種,一為USD,一為NT,若兩參數的幣別一致,則回傳值(為一Money變數)的Currency之值為參數的Currency值,而回傳值的Amount之值為兩個Money參數的金額(Amount變數)的加總值。
2.若兩參數的幣別不同(一為USD,一為NT),先將回傳值(為一Money變數)的Currency之值設為NT,再將幣別為USD的參數其Amount變數的值乘以28後(即轉成新台幣)並加上另一參數(其幣別原本就為NT)的Amount之值,以該加總值做為回傳值之Amount之值。
Subtract亦有兩個Money參數,其處理原則與Add相同,唯一不同在於回傳值的Amount值為第一個參數之Amount值減去第二個參數之Amount值(記得若兩個參數的幣別不同,要先轉成新台幣)。
Money有一public member function為Input,沒有參數與回傳值,其讓使用者輸入兩個member variable的值。
Money有兩個public member function分別為GetCurrency與GetAmount,分別回傳Currency與Amount的值。
Money有一public member function為Output,沒有回傳值,會輸出一Money變數之Currency與Amount的值。
請於main function中宣告兩個Money變數,一個沒有參數(使用default constructor),一個有參數("NT", 300),並使用Input這個member function讓使用者輸入第一個Money變數的兩個member variable的值,最後呼叫Output這個member function輸出兩個Money變數的總和與第一個Money變數減去第二個Money變數的值(分別呼叫Add與Subtract)。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please enter currency and amount
**USD**
**1**
Add The result is:
Currency: NT, Amount: 328
Subtract The result is:
Currency: NT, Amount: -272
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
class Money
{
public:
Money() { Currency = "NT", Amount = 0; }
Money(string currency, float amount);
friend Money Add(Money &a, Money &b);
friend Money Subtract(Money &a, Money &b);
void Input();
string GetCurrency() const { return Currency; }
float GetAmount() const { return Amount; }
void Output();
private:
string Currency;
float Amount;
};
int main()
{
Money a, b("NT", 300);
cout << "Please enter currency and amount\n";
a.Input();
cout << "Add The result is:\n";
Money sum = Add(a, b);
sum.Output();
cout << "Subtract The result is:\n";
Money difference = Subtract(a, b);
difference.Output();
return 0;
}
Money::Money(string currency, float amount)
{
Currency = currency;
Amount = amount;
}
Money Add(Money &a, Money &b)
{
Money sum;
if (a.Currency == b.Currency)
{
sum.Currency = a.Currency;
sum.Amount = a.Amount + b.Amount;
}
else if (a.Currency == "USD" && b.Currency == "NT")
{
sum.Currency = "NT";
sum.Amount = a.Amount * 28 + b.Amount;
}
else if (a.Currency == "NT" && b.Currency == "USD")
{
sum.Currency = "NT";
sum.Amount = b.Amount * 28 + a.Amount;
}
return sum;
}
Money Subtract(Money &a, Money &b)
{
Money sum;
if (a.Currency == b.Currency)
{
sum.Currency = a.Currency;
sum.Amount = a.Amount - b.Amount;
}
else if (a.Currency == "USD" && b.Currency == "NT")
{
sum.Currency = "NT";
sum.Amount = a.Amount * 28 - b.Amount;
}
else if (a.Currency == "NT" && b.Currency == "USD")
{
sum.Currency = "NT";
sum.Amount = a.Amount - b.Amount * 28;
}
return sum;
}
void Money::Input()
{
string currency;
float amount;
cin >> currency >> amount;
Currency = currency;
Amount = amount;
}
void Money::Output()
{
cout << "Currency: " << Currency << ", Amount: " << Amount << endl;
}
```
## overload
### Description
延續上題的題目,但請重載(overload)+, -, >>, << 這四個運算子(operator)以取代上題中的add, subtract, input與output這四個function. 其輸出、輸入的要求與上題一致。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
**NT**
**500**
Add The result is:
Currency: NT, Amount: 800
Subtract The result is:
Currency: NT, Amount: 200
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
class Money
{
public:
Money() { Currency = "NT", Amount = 0; }
Money(string currency, float amount);
friend Money operator+(const Money &a, const Money &b);
friend Money operator-(const Money &a, const Money &b);
friend istream &operator>>(istream &ins, Money &m);
friend ostream &operator<<(ostream &outs, const Money &m);
string GetCurrency() const { return Currency; }
float GetAmount() const { return Amount; }
private:
string Currency;
float Amount;
};
int main()
{
Money a, b("NT", 300);
cout << "Please enter currency and amount\n";
cin >> a;
cout << "Add The result is:\n";
Money sum = a + b;
cout << sum;
cout << "Subtract The result is:\n";
Money difference = a - b;
cout << difference;
return 0;
}
Money::Money(string currency, float amount)
{
Currency = currency;
Amount = amount;
}
Money operator+(const Money &a, const Money &b)
{
Money sum;
if (a.Currency == b.Currency)
{
sum.Currency = a.Currency;
sum.Amount = a.Amount + b.Amount;
}
else if (a.Currency == "USD" && b.Currency == "NT")
{
sum.Currency = "NT";
sum.Amount = a.Amount * 28 + b.Amount;
}
else if (a.Currency == "NT" && b.Currency == "USD")
{
sum.Currency = "NT";
sum.Amount = b.Amount * 28 + a.Amount;
}
return sum;
}
Money operator-(const Money &a, const Money &b)
{
Money sum;
if (a.Currency == b.Currency)
{
sum.Currency = a.Currency;
sum.Amount = a.Amount - b.Amount;
}
else if (a.Currency == "USD" && b.Currency == "NT")
{
sum.Currency = "NT";
sum.Amount = a.Amount * 28 - b.Amount;
}
else if (a.Currency == "NT" && b.Currency == "USD")
{
sum.Currency = "NT";
sum.Amount = a.Amount - b.Amount * 28;
}
return sum;
}
istream &operator>>(istream &ins, Money &m)
{
ins >> m.Currency >> m.Amount;
return ins;
}
ostream &operator<<(ostream &outs, const Money &m)
{
outs << "Currency: " << m.Currency << ", Amount: " << m.Amount << endl;
return outs;
}
```
## Classes and Dynamic Arrays
**copy constructor**
**assignment operator**
**destructor**
### Description
請設計一完整程式,其中包含一個class名為Animal,Animal有三個private member variable,其一是data type是char*的變數(請注意是char的pointer變數),名為Name,其二是data type為int的變數MaxLength,其三是data type為int的變數,名為NumOfLegs。
Animal有一default constructor(沒有參數的constructor),其將MaxLength的值設定為32,而將Name宣告為長度是(MaxLength + 1)的dynamic array,並將字串內容設定為空字串(""),NumOfLegs設定為-1。
其有一個含有兩個參數的constructor,第一個參數為data type為char []的const變數_N,第二個參數為data type為int的const變數 _L,在該constructor中,會將MaxLength的值設定為_N內含字串內容的長度,並將Name宣告為長度是(MaxLength + 1)的dynamic array,且將 _N與 _L的值分別assign給Name與NumOfLegs。
其有一個copy constructor,有一個data type為Animal&的const變數 _Ani,會將MaxLength的值設定為_Ani.Name內含字串內容的長度,並將Name宣告為長度是(MaxLength + 1)的dynamic array ,且將 _Ani.Name與 _Ani.NumOfLegs的值分別assign給Name與NumOfLegs。
其有一destructor,會將配置給Name的記憶體回收。
接著為Animal重載(overload)>>與<<這兩個運算子(operator),分別會讓使用者輸入與輸出兩個member variable的值,其中輸入時可以允許空格,並且最多輸入MaxLength這麼多個字元。
為Animal重載 == 這個符號,其回傳值為bool,有兩個Animal的參數,其會比較兩個參數的Name與NumOfLegs的值是否相等,若皆相等,則回傳true,否則就回傳false。
再為Animal重載 = 這個符號,其沒有回傳值,有一個const call-by-reference的Animal參數right_side,當中會將right_side.NumOfLegs的值assign給NumOfLegs,並視right_side.Name所存字串長度與MaxLength的長度來決定是否要為Name重新配置記憶體及更新MaxLength的值,再將right_side.Name的字串複製給Name。
在mail function中,請宣告三個Animal變數如下:
`Animal FirstAnimal("Dog", 4), SecondAnimal,ThirdAnimal;`
然後讓使用者輸入SecondAnimal的兩個member
variable的值,接著:
`ThirdAnimal = SecondAnimal; // assignment operator`
再宣告第四個Animal變數如下:
`Animal FourthAnimal = FirstAnimal; // copy constructor`
隨後輸出四個動物的名字與腳的數量於螢幕上後,再比較FirstAnimal與SecondAnimal是否相等。
( 提示:可在程式碼開頭處加上 `#define _CRT_SECURE_NO_WARNINGS` 以避免 Error C4996 )
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input the name and number of legs of an animal:
**cat**
**4**
The name and number of legs of the first animal are:
Dog and 4
The name and number of legs of the second animal are:
cat and 4
The name and number of legs of the third animal are:
cat and 4
The name and number of legs of the fourth animal are:
Dog and 4
They are not equal!
### Solution
```cpp=
#define _CRT_SECURE_NO_WARNINGS // 避免 Error C4996
#include <iostream>
#include <cstring>
using namespace std;
class Animal
{
public:
Animal();
Animal(const char _N[], int _L);
Animal(const Animal &_Ani); // Copy Constructor
~Animal(); // Destructor
friend istream &operator>>(istream &ins, Animal &animal);
friend ostream &operator<<(ostream &outs, const Animal &animal);
friend bool operator==(const Animal &animal1, const Animal &animal2);
void operator=(const Animal &right_side); // assignment operator
private:
char *Name; // 名稱
int MaxLength; // 最大長度
int NumOfLegs; // 腳的數量
};
int main()
{
Animal FirstAnimal("Dog", 4), SecondAnimal, ThirdAnimal;
cout << "Please input the name and number of legs of an animal:\n";
cin >> SecondAnimal;
ThirdAnimal = SecondAnimal; // assignment operator
Animal FourthAnimal = FirstAnimal; // copy constructor
cout << "The name and number of legs of the first animal are:\n"
<< FirstAnimal << endl
<< "The name and number of legs of the second animal are:\n"
<< SecondAnimal << endl
<< "The name and number of legs of the third animal are:\n"
<< ThirdAnimal << endl
<< "The name and number of legs of the fourth animal are:\n"
<< FourthAnimal << endl;
if (FirstAnimal == SecondAnimal) // 比較第一個動物和第二個動物是否相等
cout << "They are equal!" << endl;
else
cout << "They are not equal!" << endl;
return 0;
}
Animal::Animal()
{
MaxLength = 32; // 設置最大長度
Name = new char[MaxLength + 1]; // 動態分配記憶體
strcpy(Name, ""); // 初始化名稱為空字串
NumOfLegs = -1; // 初始化腳的數量為-1
}
Animal::Animal(const char _N[], int _L)
{
MaxLength = strlen(_N); // 計算名稱的長度
Name = new char[MaxLength + 1]; // 動態分配記憶體 +1是為了填入'\0'
strcpy(Name, _N); // 複製名稱
NumOfLegs = _L; // 初始化腳的數量
}
Animal::Animal(const Animal &_Ani) : MaxLength(_Ani.MaxLength), NumOfLegs(_Ani.NumOfLegs) // Copy Constructor
{
Name = new char[MaxLength + 1];
strcpy(Name, _Ani.Name);
// NumOfLegs(_Ani.NumOfLegs) 也等於 NumOfLegs = _Ani.NumOfLegs;
}
Animal::~Animal()
{
delete[] Name; // 釋放動態分配的記憶體
}
istream &operator>>(istream &ins, Animal &animal)
{
ins.getline(animal.Name, animal.MaxLength); // animal.MaxLength = 32
animal.MaxLength = strlen(animal.Name) + 1; // 切記不是在 strlen (animal.Name +1)
ins >> animal.NumOfLegs; // 讀取腳的數量
return ins;
}
ostream &operator<<(ostream &outs, const Animal &animal)
{
outs << animal.Name << " and " << animal.NumOfLegs;
return outs;
}
bool operator==(const Animal &animal1, const Animal &animal2)
{
return (strcmp(animal1.Name, animal2.Name) == 0 && animal1.NumOfLegs == animal2.NumOfLegs); // strcmp 如果相等會回傳 0
}
void Animal::operator=(const Animal &right_side) // assignment operator
{
int len = strlen(right_side.Name); // 取得 =右邊的字串長度
if (len > MaxLength) // 判斷 =左邊的字串長度可否放進 =右邊的字串
{
delete[] Name; // 如果不夠就先把 Name的記憶體釋放
MaxLength = len; // 把長度設定為 =右邊的字串長度
Name = new char[MaxLength + 1]; // 重新分配記憶體
}
for (int i = 0; i < len; i++) // strcpy(Name, right_side.Name);
Name[i] = right_side.Name[i];
Name[MaxLength] = '\0'; // strcpy會自己補就不用這行
NumOfLegs = right_side.NumOfLegs;
}
```
## Separate Compilation
### Description
請設計一完整程式,其中包含一個class名為Car,Car擁有兩個private member variable,分別為Brand, 及NumOfDoors,Brand的data type為char*,NumOfDoors為int變數。Car有一個default constructor,其中將Brand宣告為長度100的char array,並設為空字串,而把NumOfDoors的值設為 -1。
有一constructor,有兩個參數,_brand為char array的參數,_num為int參_brand 與 _num數,會把Brand宣告為_brand所含字串的長度+1的char array,並把_brand的值assign給Brand,另外把_num的值assign給 NumOfDoors。
另有一destructor,會把配置給Brand的記憶體收回。
Car有一個copy constructor,其內容是複製參數的兩個member variable的值,其中先將Brand的長度宣告為參數的Brand變數內含字串的長度+1。
另外也overload = (assignment)這個符號,其內容與copy constructor的內容一致,但需要先把Brand原先配置的記憶體刪除後再複製參數的Brand變數內含的字串。(簡化題目,故一律先刪除Brand的記憶體)
此外還有一個member function為output,沒有參數也沒有回傳值,會把兩個member variable的值列印出來。
程式中有一獨立function稱為Calling,其沒有回傳值,有一個call-by-reference的Car 參數 CarPar,在Calling中會呼叫CarPar的member function output。(Calling function的定義及宣告寫在application file裡。
在application file裡的main function中宣告兩個Car的變數
Car MyCar("Ford", 4), YourCar;
然後把MyCar assign 給 YourCar,
接著呼叫Calling並把YourCar當做參數。
以上請將題目需求分別以class的header file、implementation file及application file的方式實作。
在header file中請加上 #ifndef, #define, #endif
### Example
The brand is Ford
The number of doors is 4
### Solution
**Car.h**
```cpp=
#ifndef CAR_H
#define CAR_H
class Car
{
public:
Car();
Car(const char _brand[], int _num);
Car(const Car &_C); // Copy Constructor
~Car(); // Destructor
void operator=(const Car &_C); // assignment operator
void output() const;
private:
char *Brand;
int NumOfDoors;
};
#endif // CAR_H
```
**Car.cpp**
```cpp=
#include "Car.h"
#include <iostream>
#include <cstring>
using namespace std;
Car::Car()
{
Brand = new char[100];
Brand[0] = '\0';
NumOfDoors = -1;
}
Car::Car(const char _brand[], int _num)
{
int len = strlen(_brand);
Brand = new char[len + 1];
strcpy(Brand, _brand);
NumOfDoors = _num;
}
Car::Car(const Car &_C) // Copy Constructor
{
int len = strlen(_C.Brand);
Brand = new char[len + 1];
strcpy(Brand, _C.Brand);
NumOfDoors = _C.NumOfDoors;
}
Car::~Car() // Destructor
{
delete[] Brand;
}
void Car::operator=(const Car &_C) // assignment operator
{
delete[] Brand;
int len = strlen(_C.Brand);
Brand = new char[len + 1];
strcpy(Brand, _C.Brand);
NumOfDoors = _C.NumOfDoors;
}
void Car::output() const
{
cout << "The brand is " << Brand << endl
<< "The number of doors is " << NumOfDoors;
}
```
**main.h**
```cpp=
#include <iostream>
#include "Car.h"
using namespace std;
void Calling(Car &C) { C.output(); }
int main()
{
Car MyCar("Ford", 4), YourCar;
YourCar = MyCar;
Calling(YourCar);
return 0;
}
```
## Namespace
### Description
請設計一完整程式,其中包含一個class名為Pizza,Pizza擁有三個private member variable,分別為radius, unit_price 及 price,皆為 float 變數。Pizza有一個default constructor,其中將三個member variable的值皆設為0,另有一constructor,有兩個 float 參數 _r 及 _p,在這 constructor 中會分別把_r 及 _p 的值assign給 radius 及 price 這兩個member variable,接著計算該pizza的每單位面積價格並儲存在 unit_price 變數(假設PI值為3.14)。此外有一個public member function為output,沒有參數也沒有回傳值,會輸出該pizza的半徑、價格及每單位面積價格於螢幕上。
而另一個public member function為set,沒有回傳值,有兩個 float 參數 _r 及 _p,在 set 中會分別把_r 及 _p 的值assign給 radius 及 price 這兩個member variable,接著計算該pizza的每單位面積價格並儲存在 unit_price 變數。另外該程式以friend function的方式去overload == 這個符號,是要比較兩個Pizza的變數其每單位面積的價格是否相等。
在main function中,先宣告兩個Pizza的變數,其宣告方式為 Pizza MyPizza(10, 320), YourPizza;
接著讓使用者輸入一張pizza的半徑及價格,並存在YourPizza中,接著輸出MyPizza及YourPizza各自的半徑、價格及每單位面積價格,最後比較 MyPizza 及 YourPizza 的每單位面積價格是否相等,若相等就輸出 equal,若不相等就輸出 not equal。
請將Pizza宣告於一名為PizzaSpace的namespace中。
以上請將題目需求分別以class的header file、implementation file及application file的方式實作。
在header file中請加上 #ifndef, #define, #endif
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input the radius and price of your pizza:
**12**
**570**
MyPizza details:
The radius of this pizza is 10
The price of this pizza is 320
The unit price of this pizza is 1.01911
YourPizza details:
The radius of this pizza is 12
The price of this pizza is 570
The unit price of this pizza is 1.26062
not equal
### Solution
**Pizza.h**
```cpp=
#ifndef PIZZA_H
#define PIZZA_H
namespace PizzaSpace
{
class Pizza
{
public:
Pizza();
Pizza(float _r, float _p);
void set(float _r, float _p);
void output() const;
friend bool operator==(const Pizza &p1, const Pizza &p2);
private:
float radius;
float unit_price;
float price;
};
}
#endif // PIZZA_H
```
**Pizza.cpp**
```cpp=
#include <iostream>
#include "Pizza.h"
namespace PizzaSpace
{
Pizza::Pizza()
{
radius = 0;
price = 0;
unit_price = 0;
}
Pizza::Pizza(float _r, float _p) : radius(_r), price(_p)
{
unit_price = price / (3.14 * radius * radius);
}
void Pizza::set(float _r, float _p)
{
radius = _r;
price = _p;
unit_price = price / (3.14 * radius * radius);
}
void Pizza::output() const
{
std::cout << "The radius of this pizza is " << radius << std::endl;
std::cout << "The price of this pizza is " << price << std::endl;
std::cout << "The unit price of this pizza is " << unit_price << std::endl;
}
bool operator==(const Pizza &p1, const Pizza &p2)
{
return p1.unit_price == p2.unit_price;
}
}
```
**main.cpp**
```cpp=
#include <iostream>
#include "Pizza.h"
using namespace PizzaSpace;
using namespace std;
int main()
{
Pizza MyPizza(10, 320), YourPizza;
float radius, price;
cout << "Please input the radius and price of your pizza:" << endl;
cin >> radius >> price;
YourPizza.set(radius, price);
cout << "MyPizza details:" << endl;
MyPizza.output();
cout << "YourPizza details:" << endl;
YourPizza.output();
if (MyPizza == YourPizza)
cout << "equal" << endl;
else
cout << "not equal" << endl;
return 0;
}
```
## Inheritance
### Description
請設計一完整程式,其中包含一個class名為Parent,其有一個private member variable為int變數ParentValue,有一個default constructor(其將ParentValue的值設為100),另有一個constructor含有一個int的變數為其參數,其將ParentValue的值設為該參數的值。有一個回傳值為int的public member function名為Get_ParentValue,當中回傳ParentValue的值。
有一個繼承自Parent的class名為Child,其有一private member variable為一int變數ChildValue,有一default constructor(其呼叫Parent的default constructor,並將ChildValue的值設為200)。另有一擁有兩個int變數(設為FirstPar與SecontPar)為參數的constructor,其呼叫Parent的一個參數版本的constructor(以FirstPar為其參數),並將ChildValue的值設為SecondPar的值。有一回傳值為int的public member function名為Get_ChildValue,其回傳值為ChildValue的值。另有一回傳值為int的public member function名為 Get_Sum,其回傳值為 ParentValue加上ChildValue的值。
在main function中,宣告data type為Parent與Child的變數各一個(沒有參數),並各自呼叫 Gen_Value()。另外宣告兩個int變數為First, Second,且讓使用者輸入兩個變數的值後,再以First、Second為參數來宣告另一個data type為Child的變數,最後呼叫第二個Child變數的Get_Sum()。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
The value of ParentValue is: 100
The value of ChildValue is: 200
Please input two integers:
**50**
**75**
The sum is: 125
### Solution
```cpp=
#include <iostream>
using namespace std;
class Parent
{
public:
Parent();
Parent(int p);
int Get_ParentValue();
private:
int ParentValue;
};
class Child : public Parent
{
public:
Child();
Child(int FirstPar, int SecondPar);
int Get_ChildValue();
int Get_Sum();
private:
int ChildValue;
};
int main()
{
Parent p;
Child c;
int First, Second;
cout << "The value of ParentValue is: " << p.Get_ParentValue() << endl;
cout << "The value of ChildValue is: " << c.Get_ChildValue() << endl;
cout << "Please input two integers:\n";
cin >> First >> Second;
Child c2(First, Second);
cout << "The sum is: " << c2.Get_Sum() << endl;
return 0;
}
Parent::Parent()
{
ParentValue = 100;
}
Parent::Parent(int p)
{
ParentValue = p;
}
int Parent::Get_ParentValue()
{
return ParentValue;
}
Child::Child() : Parent()
{
ChildValue = 200;
}
Child::Child(int FirstPar, int SecondPar) : Parent(FirstPar)
{
ChildValue = SecondPar;
}
int Child::Get_ChildValue()
{
return ChildValue;
}
int Child::Get_Sum()
{
return Get_ParentValue() + ChildValue;
}
```
# 進階回家作業
## 1st homework
### Description
請設計一完整的程式,讓使用者可以從鍵盤輸入兩串文字(包含空格),並使用兩個string 變數將這兩串文字儲存起來,接著開啟outfile.txt 這個檔案,並將第二串文字的後半段串接在第一串文字的前半段之後,再把串接完的字串輸出到outfile.txt 檔案中。
(讓使用者輸入資料前,請輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input two strings:
**abcdefgh**
**ijklmno**
**outfile.txt**
```
The processed string is:
abcdmno
```
### Solution
```cpp=
#include <iostream>
#include <string>
#include <cmath>
#include <fstream>
using namespace std;
int main()
{
string str1, str2;
ofstream outfile;
outfile.open("outfile.txt");
if (outfile.fail()) // 如果沒有成功開啟檔案
{
cout << "Output file opening failed.\n";
exit(1);
}
cout << "Please input two strings:\n";
getline(cin, str1);
getline(cin, str2);
outfile << "The processed string is:\n"
<< str1.substr(0, ceil(str1.length() / 2.0)) // length字串長度 ceil無條件進位 substr提取字串
<< str2.substr(ceil(str2.length() / 2.0));
outfile.close();
cout << "Success!";
return 0;
}
```
## 2nd homework
### Description
假設檔案height.txt中記錄了一群人的身高,另一檔案weight.txt中記錄了這群人的體重,而身高、體重皆為帶小數的實數,檔案中每一行為一個數字,但事先不知道存了多少人的資料。請寫一支完整的程式,先宣告一個struct為Person,其包含三個double變數,分別為Height、Weight及BMI,在main function中從檔案讀取這些人的身高、體重,且宣告一base type為Person的vector變數PersonBMI來記錄這些資料,然後設計一個function名為ComputeBMI,其參數為一個base type為Person的vector變數,在ComputeBMI中會計算參數中每個人的BMI值。在main function中呼叫BMI function來計算每個人的BMI後,最後將算得的BMI值輸出在螢幕上,請輸出到小數點後3位。
(程式輸出資料前,請輸出提示字串)
### Example
**height.txt**
```
173
168
170
176
```
**weight.txt**
```
70
77
58
90
```
**output**
BMI for each person:
Person 1:23.389
Person 2:27.282
Person 3:20.069
Person 4:29.055
### Solution
```cpp=
#include <iostream>
#include <vector>
#include <fstream>
#include <iomanip>
using namespace std;
struct Person
{
double Height;
double Weight;
double BMI;
};
void ComputeBMI(vector<Person> &bmi)
{
for (Person &b : bmi) // range-based for loop
b.BMI = b.Weight / ((b.Height / 100.0) * (b.Height / 100.0));
}
int main()
{
ifstream height_file, weight_file;
height_file.open("height.txt");
if (height_file.fail())
{
cout << "Input height opening failed.\n";
exit(1);
}
weight_file.open("weight.txt");
if (weight_file.fail())
{
cout << "Input weight opening failed.\n";
exit(1);
}
vector<Person> PersonBMI;
double height, weight;
while (height_file >> height && weight_file >> weight)
{
Person p;
p.Height = height;
p.Weight = weight;
PersonBMI.push_back(p);
}
ComputeBMI(PersonBMI);
cout << "BMI for each person:\n";
int num = 1;
for (Person &b : PersonBMI)
{
cout << "Person " << num << ":" << fixed << setprecision(3) << b.BMI << endl;
num++;
}
return 0;
}
```
## 3rd homework
### Description
假設檔案height.txt中記錄了一群人的身高,另一檔案weight.txt中記錄了這群人的體重,而身高、體重皆為帶小數的實數,檔案中每一行為一個數字,但事先不知道存了多少人的資料。請寫一支完整的程式,先宣告一個struct為Person,其包含三個double變數,分別為Height、Weight及BMI,在main function中從檔案讀取這些人的身高、體重,且宣告一base type為Person的pointer變數PersonBMI來記錄這些資料,然後設計一個function名為ComputeBMI,其第一個參數為一個base type為Person的pointer變數,第二個參數為一int變數,其值代表有幾個人。在ComputeBMI中會計算參數中每個人的BMI值。在main function中呼叫BMI function來計算每個人的BMI後,最後將算得的BMI值輸出在螢幕上,請輸出到小數點後3位。之後刪除所配置的記憶體。
(提示:先讀取一次檔案,確認人數有多少,再將PersonBMI宣告為等長的dynamic array。程式輸出資料前,請輸出提示字串)
### Example
**height.txt**
```
173
168
170
176
```
**weight.txt**
```
70
77
58
90
```
**output**
BMI for each person:
Person 1:23.389
Person 2:27.282
Person 3:20.069
Person 4:29.055
### Solution
```cpp=
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
struct Person
{
double Height;
double Weight;
double BMI;
};
void ComputeBMI(Person *people, int num)
{
for (int i = 0; i < num; i++)
people[i].BMI = people[i].Weight / ((people[i].Height / 100.0) * (people[i].Height / 100.0));
}
int main()
{
ifstream height_file, weight_file;
height_file.open("height.txt");
if (height_file.fail())
{
cout << "Input height opening failed.\n";
exit(1);
}
weight_file.open("weight.txt");
if (weight_file.fail())
{
cout << "Input weight opening failed.\n";
exit(1);
}
int people_num = 0;
double height, weight;
while (height_file >> height && weight_file >> weight)
people_num++;
height_file.clear(); // 清除檔案狀態,以確保後續操作不受影響
height_file.seekg(0); // 將檔案指標移到檔案的開頭位置,方便重新讀取檔案資料
weight_file.clear();
weight_file.seekg(0);
Person *PersonBMI = new Person[people_num];
for (int i = 0; i < people_num; i++)
{
height_file >> PersonBMI[i].Height;
weight_file >> PersonBMI[i].Weight;
}
ComputeBMI(PersonBMI, people_num);
cout << "BMI for each person:\n";
for (int i = 0; i < people_num; i++)
{
cout << "Person " << i + 1 << ":" << fixed << setprecision(3) << PersonBMI[i].BMI << endl;
}
delete[] PersonBMI;
height_file.close();
weight_file.close();
return 0;
}
```
## 4th homework
### Description
請撰寫一計算平均成績的程式,首先會詢問使用者一共有多少個學生,接著宣告一個double 2D array,其第一個維度為學生人數、第二個維度為2,array名稱為Score,然後讓使用者輸入每一個學生的程設與計概成績。
接著設計三個function(名稱為分別為StuAvg、ProAVG與CompAvg)來計算每位學生的平均成績、程設平均成績與計概平均成績,並將算得的成績回傳。在main function中會呼叫這三個function,並將算得的成績顯示在螢幕上。之後刪除所配置的記憶體。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
How many students?
**2**
Please input two scores for student#0 :
**100**
**90**
Please input two scores for student#1 :
**80**
**70**
The average score of each student is:
student#0 : 95
student#1 : 75
The average score of programming is 90
The average score of basic computer concepts is 80
### Solution
```cpp=
#include <iostream>
using namespace std;
void StuAvg(double **Score_StuAvg, int num_StuAvg);
double ProAVG(double **Score_ProAVG, int num_ProAVG);
double CompAvg(double **Score_CompAvg, int num_CompAvg);
int main()
{
int num;
cout << "How many students?\n";
cin >> num;
double **Score = new double *[num];
for (int i = 0; i < num; i++)
Score[i] = new double[2];
for (int i = 0; i < num; i++)
{
cout << "Please input two scores for student#" << i << ":" << endl;
cin >> Score[i][0] >> Score[i][1];
}
StuAvg(Score, num);
cout << "The average score of programming is " << ProAVG(Score, num) << endl;
cout << "The average score of basic computer concepts is " << CompAvg(Score, num);
for (int i = 0; i < num; i++)
delete[] Score[i]; // 先刪除二維
delete[] Score; // 再刪除一維
return 0;
}
void StuAvg(double **Score_StuAvg, int num_StuAvg)
{
cout << "The average score of each student is:\n";
for (int i = 0; i < num_StuAvg; i++)
cout << "student#" << i << " : " << (Score_StuAvg[i][0] + Score_StuAvg[i][1]) / 2.0 << endl;
}
double ProAVG(double **Score_ProAVG, int num_ProAVG)
{
double total = 0;
for (int i = 0; i < num_ProAVG; i++)
total += Score_ProAVG[i][0];
return total / num_ProAVG;
}
double CompAvg(double **Score_CompAvg, int num_CompAvg)
{
double total = 0.0;
for (int i = 0; i < num_CompAvg; i++)
total += Score_CompAvg[i][1];
return total / num_CompAvg;
}
```
## 5th homework
### Description
撰寫一完整的程式,其有一個struct稱為CharacterBag,其有一個int變數稱為NumOfChars,另有一個長度為128的char array變數稱為Characters;在main function中,宣告一個CharacterBag的array變數稱為CBags,其長度為32,接著請使用者輸入CBags每個element的NumOfChars的值,其代表每個element各要儲存幾個字母,若超過128,則改成128,接著讓使用者輸入每個element的每個字母,最後輸出每個element的每個字母。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Enter the number of characters for CharacterBag 1: **5**
Enter 5 characters: **a b c d e**
Enter the number of characters for CharacterBag 2: **3**
Enter 3 characters: **x y z**
...
(Continue for all 32 CharacterBags)
CharacterBag 1 contains 5 characters: a b c d e
CharacterBag 2 contains 3 characters: x y z
...
### Solution
```cpp=
#include <iostream>
using namespace std;
struct CharacterBag
{
int NumOfChars; // 儲存字元數量
char Characters[128]; // 儲存字元的陣列
};
int main()
{
CharacterBag CBags[32]; // 宣告一個長度為 32 的 CharacterBag 陣列
for (int i = 0; i < 32; ++i) // 迴圈處理每個 CBags 陣列的元素
{
cout << "Enter the number of characters for CharacterBag " << i + 1 << ": ";
cin >> CBags[i].NumOfChars; // 輸入字元數量
if (CBags[i].NumOfChars > 128) // 如果字元數量超過 128,將其設為 128
CBags[i].NumOfChars = 128;
for (int k = 0; k < 128; k++) // 初始化 Characters 陣列為空字符 '\0'
CBags[i].Characters[k] = '\0';
cout << "Enter " << CBags[i].NumOfChars << " characters: "; // 輸入實際的字元
for (int j = 0; j < CBags[i].NumOfChars; j++)
cin >> CBags[i].Characters[j];
}
for (int i = 0; i < 32; i++) // 輸出每個 CharacterBag 的內容
{
cout << "CharacterBag " << i + 1 << " contains " << CBags[i].NumOfChars << " characters: ";
for (int j = 0; j < CBags[i].NumOfChars; j++)
cout << CBags[i].Characters[j] << ' ';
cout << endl;
}
return 0;
}
```
## 6th homework
### Description
請定義一個class為MotorcycleType,其包含兩個private member variable:data type為string的Model(型號)、data type為int的Displacement(排氣量),其包含一個default constructor,當中會把Model的值設為空字串,Displacement的值設為-1,有一個public member function為Set,沒有回傳值,有兩個參數:data type為string的_M、data type為int的_D,會把兩個member variable的值分別設定為_M及_D的值,有一public member function為Output,沒有回傳值及參數,會把兩個member variable的值輸出在螢幕上。另為MotorcycleType重載(overload) << 與 >> 這兩個符號,operator << 輸出兩個member variable的值,operator >> 則可輸入兩個member variable的值(其中Model的值可包含空格)。
main function中宣告一MotorcycleType的變數稱為MT,沒有參數,隨後讓使用者輸入型號(可包含空格)以及排氣量,最後輸出其兩個member variable的值於螢幕上。(請使用<< 與 >> )
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input Model and Displacement:
**Harley Davidson**
**1200**
Model: Harley Davidson, Displacement: 1200
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
class MotorcycleType
{
public:
MotorcycleType();
void Set(string _M, int _D);
void Output();
friend istream &operator>>(istream &ins, MotorcycleType &M);
friend ostream &operator<<(ostream &outs, const MotorcycleType &M);
private:
string Model;
int Displacement;
};
int main()
{
MotorcycleType MT;
cout << "Please input Model and Displacement:\n";
cin >> MT;
cout << MT;
return 0;
}
MotorcycleType::MotorcycleType()
{
Model = "";
Displacement = -1;
}
void MotorcycleType::Set(string _M, int _D)
{
Model = _M;
Displacement = _D;
}
void MotorcycleType::Output()
{
cout << "Model: " << Model << ", Displacement: " << Displacement << endl;
}
istream &operator>>(istream &ins, MotorcycleType &M)
{
getline(ins, M.Model); // 包含空格
ins >> M.Displacement;
return ins;
}
ostream &operator<<(ostream &outs, const MotorcycleType &M)
{
outs << "Model: " << M.Model << ", Displacement: " << M.Displacement << endl;
return outs;
}
```
## 7th homework
### Description
請以class定義一data type為Keyboard,其有四個member variable:一為int的變數NumOfKeys,一為char*的變數Name,一為int的變數MaxLength,另一為double的變數Price;Keyboard有一default constructor,當中會把NumOfKeys的值設為0、MaxLength的值為32,將Name宣告為一長度是MaxLength加1的陣列並其值為空字串,再把Price的值設為-1。Keyboard另有一constructor,其有三個參數,一為int的變數_num、一為char陣列_name,另一為double的變數_price,在該constructor中,會把_num的值assign給NumOfKeys、將MaxLength設定為_name所記錄的字串的長度,並把_name的值assign給Name(會先把Name宣告為一陣列,長度是MaxLength加1),另把_price的值assign給Price。
Keyboard有一copy constructor、destructor與重載assignment operator。在copy constructor中複製參數的四個member variable(需先為Name配置記憶體,長度為MaxLength加1)。Destructor會收回配置給Name的記憶體。重載assignment operator可需要先考量Name變數的array長度是否足夠以決定是否要為Name重新配置記憶體。
另外重載(overload)operator <<,當中會輸出NumOfKeys、Name、Price 這三個member variable的值。
此外也重載operator +,其回傳值的data type為Keyboard,有兩個data type為Keyboard的參數KBOne及KBTwo。當中宣告一個Keyboard的變數temp(無參數),會把KBOne的Name的值與KBTwo的Name的值串接後assign給temp的Name(先將Temp之MaxLength的值設為KBOne與KBTwo兩者的字串長度之和,再配置temp的Name的記憶體,使其剛好可以容納串接後的字串。)接著把temp的NumOfKeys的值設定為KBOne.NumOfKeys與KBTwo.NumOfKeys的和,把temp的Price的值設定為KBOne.Price與KBTwo.Price的和,最後回傳temp。
在main function中讓使用者輸入一個鍵盤的名字、按鍵的數目及價格,並藉此三個值宣告一個Keyboard的變數為KBOne,然後再讓使用者輸入一個鍵盤的名字、按鍵的數目及價格,並藉此三個值宣告一個Keyboard的變數為KBTwo,接著將KBOne及KBTwo利用+符號相加後assign給另一個Keyboard變數KBThree,然後輸出KBThree的三個member variable的值。
程式開頭可寫上`#define _CRT_SECURE_NO_WARNINGS`以避免 error 4996。
請將程式分別以header file, implementation file與application file的方式撰寫。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
The first keyboard:
Please input the number of keys:
**128**
Please input the name:
**MyKeyboard**
Please input the price:
**550**
The second keyboard:
Please input the number of keys:
**100**
Please input the name:
**YourKeyboard**
Please input the price:
**450**
The number of Keys is 228
The name is MyKeyboardYourKeyboard
The price is 1000
### Solution
**Keyboard.h**
```cpp=
#ifndef KEYBOARD_H // 如果沒有定義 KEYBOARD_H
#define KEYBOARD_H // 定義 KEYBOARD_H
#include <iostream>
using namespace std;
class Keyboard
{
public:
Keyboard();
Keyboard(int _num, const char _name[], double _price);
Keyboard(const Keyboard &_keyboard); // copy constructor
~Keyboard(); // destructor
void operator=(const Keyboard &right_side); // assignment operator
friend istream &operator>>(istream &ins, Keyboard &K);
friend ostream &operator<<(ostream &outs, const Keyboard &K);
friend Keyboard operator+(const Keyboard &KBOne, const Keyboard &KBTwo);
private:
int NumOfKeys;
char *Name;
int MaxLength;
double Price;
};
#endif // 結束條件指令
```
**Keyboard.cpp**
```cpp=
#include "Keyboard.h"
#include <cstring>
Keyboard::Keyboard() // Default constructor
{
NumOfKeys = 0;
MaxLength = 32;
Name = new char[MaxLength + 1];
strcpy(Name, ""); // 設成空字串
Price = -1;
}
Keyboard::Keyboard(int _num, const char _name[], double _price) // constructor
{
NumOfKeys = _num;
MaxLength = strlen(_name);
Name = new char[MaxLength + 1];
strcpy(Name, _name);
Price = _price;
}
Keyboard::Keyboard(const Keyboard &_k) // Copy constructor
{
NumOfKeys = _k.NumOfKeys;
MaxLength = strlen(_k.Name);
Name = new char[MaxLength + 1];
strcpy(Name, _k.Name);
Price = _k.Price;
}
Keyboard::~Keyboard() // Destructor
{
delete[] Name;
}
void Keyboard::operator=(const Keyboard &right_side) // Assignment operator
{
int len = strlen(right_side.Name);
if (len > MaxLength)
{
delete[] Name;
MaxLength = len;
Name = new char[MaxLength + 1];
}
strcpy(Name, right_side.Name);
NumOfKeys = right_side.NumOfKeys;
Price = right_side.Price;
}
istream &operator>>(istream &ins, Keyboard &K) // Input operator
{
cout << "Please input the number of keys:\n";
ins >> K.NumOfKeys;
cout << "Please input the name:\n";
ins >> K.Name;
K.MaxLength = strlen(K.Name);
cout << "Please input the price:\n";
ins >> K.Price;
return ins;
}
ostream &operator<<(ostream &outs, const Keyboard &K) // Output operator
{
outs << "The number of Keys is " << K.NumOfKeys << endl
<< "The name is " << K.Name << endl
<< "The price is " << K.Price;
return outs;
}
Keyboard operator+(const Keyboard &KBOne, const Keyboard &KBTwo) // Addition operator
{
Keyboard temp;
temp.Name = strcat(KBOne.Name, KBTwo.Name);
temp.MaxLength = strlen(temp.Name);
temp.NumOfKeys = KBOne.NumOfKeys + KBTwo.NumOfKeys;
temp.Price = KBOne.Price + KBTwo.Price;
return temp;
}
```
**main.cpp**
```cpp=
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "Keyboard.h"
using namespace std;
int main()
{
Keyboard KBOne, KBTwo, KBThree;
cout << "The first keyboard:\n";
cin >> KBOne;
cout << "The second keyboard:\n";
cin >> KBTwo;
KBThree = KBOne + KBTwo;
cout << KBThree;
return 0;
}
```
# 進階期中考題
## 1st exam(15分)
### Description
請撰寫一完整程式,其中有一char pointer變數ptr,另有一變數size,讓使用者輸入size的值後,然後將變數ptr初始化成為大小為size的dynamic array,接著利用for廻圈讓使用者輸入ptr這個array的每個element的值,然後將array的內容倒著輸出到螢幕上。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
input num
**5**
input 5 char
**1**
**2**
**3**
**4**
**5**
reverse:
5
4
3
2
1
### Solution
```cpp=
#include <iostream>
using namespace std;
int main()
{
int size;
cout << "input num\n";
cin >> size;
char *ptr = new char[size];
cout << "input " << size << " char\n";
for (int i = 0; i < size; i++)
cin >> ptr[i];
cout << "reverse:\n";
for (int i = (size - 1); i >= 0; i--)
cout << ptr[i] << endl;
return 0;
}
```
## 2nd exam(15分)
### Description
請撰寫一完整程式,其中宣告一個data type為string的變數str,然後讓使用者從鍵盤輸入一字串並儲存於str(包括空格)。接著針對str中每個element,把大寫字母換成小寫,小寫字母換成大寫,其餘種類的字母則不做變動,再將更動後的str的值輸出到螢幕上。接著再讓使用者輸入另一個字串(包含空格)並在螢幕上輸出第二個字串是否包含在第一個字串之中。(程式輸入、輸出資料前,請先輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
input string
**Sumo 0711**
After the change:
sUMO 0711
Enter the string you are looking for
**sUMO**
There is a matching string
### Solution
```cpp=
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string str, str2;
cout << "input string\n";
getline(cin, str);
for (int i = 0; i <= str.length(); i++) // str.length()會回傳字串長度
{
if (islower(str[i])) // 判斷是否為小寫
str[i] = toupper(str[i]); // 轉成大寫
else if (isupper(str[i])) // 判斷是否為大寫
str[i] = tolower((str[i])); // 轉成小寫
}
cout << "After the change:\n"
<< str << endl
<< "Enter the string you are looking for\n";
getline(cin, str2);
if (str.find(str2) != string::npos)
cout << "There is a matching string";
else
cout << "No matching string";
return 0;
}
```
## 3rd exam(20分)
### Description
請撰寫一完整程式,在程式中會從檔案infile.txt讀入若干個數字(假設檔案中每一列是一個double數字),請利用一個vector變數將這些數字儲存起來,並且在讀完所有數字後,計算出這些數字的平均值及標準差,並將結果輸出到螢幕上。(計算平方請使用pow(),輸出結果時,要提示使用者。)
$$
s = \sqrt{\frac{1}{n-1} \sum_{i=1}^{n} (x_i - \overline{x})^2}
$$
### Example
**infile.txt**
```
3.0
4.0
5.0
```
The average is: 4
The standard deviation is: 1
### Solution
```cpp=
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
ifstream infile("infile.txt");
if (infile.fail())
{
cout << "infile opening failed";
exit(1);
}
double num, sum = 0, avg, dif;
vector<double> nums;
while (infile >> num)
{
nums.push_back(num);
}
for (int i = 0; i < nums.size(); i++)
{
sum += nums[i];
}
avg = sum / nums.size();
cout << "The average is: " << avg << endl;
sum = 0;
for (int i = 0; i < nums.size(); i++)
{
sum += pow((nums[i] - avg), 2);
}
dif = sqrt((1.0 / double(nums.size() - 1)) * sum);
cout << "The standard deviation is: " << dif << endl;
infile.close();
return 0;
}
```
## 4th exam(20分)
### Description
請撰寫一完整程式,程式中建立一個二維的dynamic double array 為 score,以記錄m個學生各n個科目的成績,程式中會讓使用者輸入m與n的值,再一一輸入這m個學生各n個科目的成績,然後再計算出每個科目的平均成績與最大值、最小值並輸出,最後要刪去配置的記憶體。(程式輸入、輸出資料前,請先輸出提示字串)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Enter how many students there are
**3**
Enter how many subjects there are
**3**
Student 1
**100**
**88**
**67**
Student 2
**34**
**68**
**80**
Student 3
**45**
**79**
**99**
subject 1
The average is 59.6667
The maximum value is 100
The minimum value is 34
subject 2
The average is 78.3333
The maximum value is 88
The minimum value is 68
subject 3
The average is 82
The maximum value is 99
The minimum value is 67
### Solution
```cpp=
#include <iostream>
using namespace std;
int main()
{
int m, n;
cout << "Enter how many students there are\n";
cin >> m; // 學生數量
cout << "Enter how many subjects there are\n";
cin >> n; // 科目數量
double **score = new double *[m];
for (int i = 0; i < m; ++i)
{
score[i] = new double[n];
}
for (int i = 0; i < m; i++)
{
cout << "Student " << i + 1 << endl;
for (int j = 0; j < n; j++)
cin >> score[i][j];
}
for (int j = 0; j < n; j++)
{
double max = 0, low = 100, sum = 0; // 在迴圈開始時重置
for (int i = 0; i < m; i++)
{
if (score[i][j] > max)
max = score[i][j];
if (score[i][j] < low)
low = score[i][j];
sum += score[i][j];
}
cout << "subject " << j + 1 << endl;
cout << "The average is " << sum / m << endl
<< "The maximum value is " << max << endl
<< "The minimum value is " << low << endl;
}
for (int i = 0; i < m; ++i) // 釋放記憶體
delete[] score[i];
delete[] score;
return 0;
}
```
## 5th exam(30分)
### Description
請撰寫一完整程式,其中利用struct關鍵字定義一個data type稱為Date,其中含有三個int變數分別為Day, Month, Year;再定義另一個data type稱為Person,其中含有一個string變數Name與一個Date變數Birthday。在main function中宣告一個base type為Person的vector變數Employee,先讓使用者輸入他/她想要輸入幾個員工的資料,再一一輸入員工的姓名與生日,最後再輸出這些員工的姓名與生日(程式輸入、輸出資料前,請先輸出提示字串,輸出生日時以 / 符號隔開年月日,如2024/4/18)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Enter employee name and date of birth:
**sumo 2002 07 11**
**vector 2004 09 29**
staff ID:sumo
2002/7/11
staff ID:vector
2004/9/29
### Solution
```cpp=
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Date
{
int Day;
int Month;
int Year;
};
struct Person
{
string name;
Date Birthday;
};
int main()
{
int num;
cout << "Please enter how many employees there are:\n";
cin >> num;
vector<Person> Employee;
cout << "Enter employee name and date of birth:\n";
for (int i = 0; i < num; i++)
{
Person Token;
cin >> Token.name >> Token.Birthday.Year >> Token.Birthday.Month >> Token.Birthday.Day;
if (Token.Birthday.Month <= 1 || Token.Birthday.Month <= 12 || Token.Birthday.Day <= 1 || Token.Birthday.Day >= 31)
Employee.push_back(Token);
}
for (Person &p : Employee)
cout << "staff ID:" << p.name << endl
<< p.Birthday.Year << '/' << p.Birthday.Month << '/' << p.Birthday.Day << endl;
return 0;
}
```
# 進階期末考題
**輸出、輸入前需顯示提示字串,class設計需符合ADT規範**
## 1st exam(20分)
### Description
一部車子有型號model(可包含空格的字串)與馬力horsepower(整數)兩種屬性,另外可以藉由按下喇叭發出”BiBi!”的聲音,也可藉由踩下剎車讓該車輛停止前進。
(1) 請以class設計一個名為Car的data type代表車輛,其型號與馬力兩種屬性做為其member variable(data type分別是string與int)。
(2) 該class有一個名為horn的member function,其輸出”BiBi!”字串,另一名為brake的member function則會輸出”Stop!”字串。
(3) 另有一個member function名為set,其可讓使用者輸入一部車的型號以及馬力,再有一個member function名為output,當中輸出一部車的型號以及馬力。
(4) horn、brake、set與output皆為void function並且沒有參數。horn、brake與output為constant member function。
(5) 請在main function中宣告一個Car的變數,並且讓使用者輸入該車的型號以及馬力後再輸出這兩個值於螢幕上,最後呼叫horn以及brake。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input the model and horsepower of the car:
**Ford Kuga**
**250**
The model and horsepower of the car are Ford Kuga and 250.
BiBi!
Stop!
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
class Car
{
public:
void horn() const { cout << "BiBi!\n"; }
void brake() const { cout << "Stop!\n"; }
void set(string M, int H)
{
model = M;
horsepower = H;
}
void output() const { cout << "The model and horsepower of the car are " << model << " and " << horsepower << ".\n"; }
private:
string model;
int horsepower;
};
int main()
{
Car C;
string M;
int H;
cout << "Please input the model and horsepower of the car:\n";
getline(cin, M);
cin >> H;
C.set(M, H);
C.output();
C.horn();
C.brake();
return 0;
}
```
## 2nd exam(20分)
### Description
承第一題:
(1) 請為Car這個class加入一default constructor,當中將model設為空字串,horsepower設為-1。
(2) 另有一constructor有兩個參數,兩個參數分別是data type為string的model_name跟data type為int的model_horsepower,在該constructor中,會把model跟 horsepower 的值分別設定為 model_name及 model_horsepower 的值。
(3) 接著以friend function為Car重載(overload) >> 與 << 這兩個符號以取代第一題中的set與output這兩個member function(在此題中的Car沒有set與output這兩個member function,仍保留horn與brake為constant member function)。
(4) 此外以friend function也重載 == 這個符號,當中比較兩個Car變數的兩個member variable值是否相等,若都相等則回傳true,否則回傳false。
(5) 在main function中宣告兩個Car的變數,第一個變數於宣告時即有初始值”Ford Kuga”與250,第二個變數宣告時沒有初始值,接著輸入第二部車的型號以及馬力,再將兩部車的型號以及馬力輸出於螢幕中,然後比較兩部車是否相等,若相等回傳”Identical!”字串,否則回傳”Different!”字串。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input the model and horsepower of the car:
**Nissan Sentra**
**138**
The data of the two cars:
The model and horsepower of the car are Ford Kuga and 250.
The model and horsepower of the car are Nissan Sentra and 138.
Different!
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
class Car
{
public:
Car()
{
model = "";
horsepower = -1;
}
Car(string model_name, int model_horsepower)
{
model = model_name;
horsepower = model_horsepower;
}
friend istream &operator>>(istream &ins, Car &C)
{
getline(ins, C.model);
ins >> C.horsepower;
return ins;
}
friend ostream &operator<<(ostream &outs, Car &C)
{
outs << "The model and horsepower of the car are " << C.model << " and " << C.horsepower << ".\n";
return outs;
}
friend bool operator==(const Car &C1, const Car &C2)
{
return C1.model == C2.model && C1.horsepower == C2.horsepower;
}
void horn() const { cout << "BiBi!\n"; }
void brake() const { cout << "Stop!\n"; }
private:
string model;
int horsepower;
};
int main()
{
Car C1("Ford Kuga", 250), C2;
cout << "Please input the model and horsepower of the car:\n";
cin >> C2;
cout << "The data of the two cars:\n";
cout << C1 << C2;
if (C1 == C2)
cout << "Identical!\n";
else
cout << "Different!\n";
return 0;
}
```
## 3rd exam(25分)
### Description
承第二題,許多人會為愛車取小名(可包含空格的字串),因此再為Car新增一個char* 的變數為nickname以及一個int變數max_size。
(1) 在default constructor以及兩個參數版本的constructor中新增將max_size的值設為32而將nickname宣告為長度為max_size + 1的dynamic array,再將nickname設為空字串。
(2) 再新增一個三個參數版本的constructor,三個參數分別是data type為string的model_name、data type為int的model_horsepower以及data type為string的變數model_nickname,在該constructor中,會把model跟 horsepower 的值分別設定為 model_name及 model_horsepower 的值,並把max_size設為model_nickname所存的字串的長度,並把nickname宣告為max_size + 1的dynamic array,再將model_nickname所存的字串複製給nickname。
(3) 為Car重載(overload) >> 與 << 這兩個符號需再讓使用者分別輸入與輸出nickname的值。而在重載 == 中要比較兩個變數的三個member variable是否相等。以friend function重載兩符號。
(4) 請再為Car新增copy constructor、destructor以及重載 = 這個符號。Copy constructor中複製參數的三個member variable的值、destructor中刪除配置給nickname的值,重載 = 符號中複製參數的三個member variable的值。
(5) horn與break兩個constant member function的內容不變。
(6) 在main function中以初始值”Ford Kuga”、250、“Kugy”來宣告一個Car的變數,另外宣告一個沒有初始值的Car變數,並隨後讓使用者輸入第二個Car變數的三個member variable的值,再將兩部車的型號、馬力以及小名輸出於螢幕中,然後比較兩部車是否相等,若相等回傳”Identical!”字串,否則回傳”Different!”字串。請將Car置放於CarName這個namespace之中。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input the model, horsepower, and nickname of the car:
**Nissan Sentra**
**138**
**Sentry**
The data of the two cars:
The model, horsepower, and nickname of the car are Ford Kuga, 250, and Kugy.
The model, horsepower, and nickname of the car are Nissan Sentra, 138, and Sentry.
Different!
### Solution
```cpp=
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
namespace CarName
{
class Car
{
public:
Car()
{
max_size = 32;
nickname = new char[max_size + 1];
strcpy(nickname, "");
model = "";
horsepower = -1;
}
Car(string model_name, int model_horsepower)
{
max_size = 32;
nickname = new char[max_size + 1];
strcpy(nickname, "");
model = model_name;
horsepower = model_horsepower;
}
Car(string model_name, int model_horsepower, string model_nickname)
{
model = model_name;
horsepower = model_horsepower;
max_size = model_nickname.length();
nickname = new char[max_size + 1];
strcpy(nickname, model_nickname.c_str()); // model_nickname 轉成 char
}
friend istream &operator>>(istream &ins, Car &C)
{
getline(ins, C.model);
ins >> C.horsepower;
ins.ignore(); // 忽略換行
string temp_nickname;
getline(ins, temp_nickname);
strcpy(C.nickname, temp_nickname.c_str());
return ins;
}
friend ostream &operator<<(ostream &outs, const Car &C)
{
outs << "The model and horsepower of the car are " << C.model << " ," << C.horsepower << ", and " << C.nickname << ".\n";
return outs;
}
friend bool operator==(const Car &C1, const Car &C2)
{
return C1.model == C2.model && C1.horsepower == C2.horsepower && strcmp(C1.nickname, C2.nickname) == 0;
}
void horn() const { cout << "BiBi!\n"; }
void brake() const { cout << "Stop!\n"; }
~Car() { delete[] nickname; }
Car(const Car &C) // copy constructor
{
max_size = C.max_size;
nickname = new char[max_size + 1];
strcpy(nickname, C.nickname);
model = C.model;
horsepower = C.horsepower;
}
void operator=(const Car &C) // assignment operator
{
int len = strlen(C.nickname);
if (len > max_size)
{
delete[] nickname;
max_size = len;
nickname = new char[max_size + 1];
}
strcpy(nickname, C.nickname);
model = C.model;
horsepower = C.horsepower;
}
private:
string model;
int horsepower;
char *nickname;
int max_size;
};
} // namespace CarName
int main()
{
using namespace CarName;
Car C1("Ford Kuga", 250, "Kugy"), C2;
cout << "Please input the model and horsepower of the car:\n";
cin >> C2;
cout << "The data of the two cars:\n";
cout << C1 << C2;
if (C1 == C2)
cout << "Identical!\n";
else
cout << "Different!\n";
return 0;
}
```
## 4th exam(35分)
### Description
承第一題與第二題,重新定義Car如下:
(1) 一部車子有型號model(可包含空格的字串)與馬力horsepower(整數)兩種屬性,其型號與馬力兩種屬性做為其member variable(data type分別是string與int)。
(2) 該class有一個名為horn的member function,其輸出”BiBi!”字串,另一名為brake的member function則會輸出”Stop!”字串。
(3) 另有一個member function名為set,其可讓使用者輸入一部車的型號以及馬力,再有一個member function名為output,當中輸出一部車的型號以及馬力。
(4) horn、brake、set與output皆為void function並且沒有參數。horn、brake與output為constant member function。
(5) 有一member function名為get_model,沒有參數,回傳model的值。有一member function名為get_horsepower,沒有參數,回傳horsepower的值。兩個function皆為constant member function。
(6) Car有一default constructor,當中將model設為空字串,horsepower設為 -1。
(7) 另有一constructor有兩個參數,兩個參數分別是data type為string的model_name跟data type為int的model_horsepower,在該constructor中,會把model跟 horsepower 的值分別設定為 model_name及 model_horsepower 的值。
而電動車為一種車子,故可定義一個class為ElectricCar,其public繼承Car。ElectricCar有一個自身的member variable為battery_type,代表電池的型式,為一string變數。
(1) ElectricCar有一default constructor,其將model設為空字串、horsepower設為-1、battery_type設為空字串。
(2) 有一含有三個參數的constructor,三個參數分別是data type為string的model_name、data type為int的model_horsepower及data type是string的model_battery_type,其將三個member variable分別設為三個參數的值。
(3) 重新定義horn這個constant member function,沒有回傳值也沒有參數,在螢幕上輸出”BiBi from an electric car!”。
(4) 重新定義brake這個constant member function,沒有回傳值也沒有參數,在螢幕上輸出”Stop from an electric car!”。
(5) 有一constant member function名為get_battery_type,沒有參數,回傳battery_type的值。
(6) 有一member function名為set_ec,沒有回傳值與參數,其讓使用者輸入三個member variable的值。
(7) 有一const member function名為output_ec,沒有回傳值,其輸出三個member variable的值於螢幕上。
(8) 以friend function重載 == 這個符號,當中比較兩個ElectricCar變數的三個member variable值是否相等,若都相等則回傳true,否則回傳false。
(9) 在main function中宣告兩個ElectricCar的變數,第一個變數於宣告時即有初始值”Tesla Model Y”、256與”LFP”,第二個變數宣告時沒有初始值,接著輸入第二部車的型號、馬力及電池型式,再將兩部車的型號、馬力及電池型式輸出於螢幕中,然後比較兩部車是否相等,若相等回傳”Identical!”字串,否則回傳”Different!”字串。
(10) 請以separate compilation的方式撰寫此程式。兩個class各要有header file與implementation file,main function寫在application file中,注意 #ifndef 的設定。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please input the model and horsepower of the car:
**Luxgen n7**
**234**
Please input the battery type of the car:
**LFP**
The model, horsepower, and battery type of the car are Tesla Model Y, 256, and LFP.
The model, horsepower, and battery type of the car are Luxgen n7, 234, and LFP.
Different!
### Solution
**Car.h**
```cpp=
#ifndef CAR_H
#define CAR_H
#include <string>
using namespace std;
class Car
{
public:
Car();
Car(string model_name, int model_horsepower);
string get_model() const;
int get_horsepower() const;
void set(string M, int H);
void horn() const;
void brake() const;
void output() const;
private:
string model;
int horsepower;
};
class ElectricCar : public Car
{
public:
ElectricCar();
ElectricCar(string model_name, int model_horsepower, string model_battery_type);
void horn() const;
void brake() const;
string get_battery_type() const;
void set_ec(string M, int H, string B);
void output() const;
friend bool operator==(const ElectricCar &C1, const ElectricCar &C2);
private:
string battery_type;
};
#endif // CAR_H
```
**Car.cpp**
```cpp=
#include <string>
#include <iostream>
#include "Car.h"
using namespace std;
Car::Car()
{
model = "";
horsepower = -1;
}
Car::Car(string model_name, int model_horsepower)
{
model = model_name;
horsepower = model_horsepower;
}
string Car::get_model() const { return model; }
int Car::get_horsepower() const { return horsepower; }
void Car::set(string M, int H)
{
model = M;
horsepower = H;
}
void Car::horn() const
{
cout << "BiBi!\n";
}
void Car::brake() const
{
cout << "Stop!\n";
}
void Car::output() const
{
cout << "The model and horsepower of the car are " << model << " and " << horsepower << ".\n";
}
ElectricCar::ElectricCar() : Car()
{
battery_type = "";
}
ElectricCar::ElectricCar(string model_name, int model_horsepower, string model_battery_type) : Car(model_name, model_horsepower)
{
battery_type = model_battery_type;
}
void ElectricCar::horn() const
{
cout << "BiBi from an electric car!\n";
}
void ElectricCar::brake() const
{
cout << "Stop from an electric car!\n";
}
string ElectricCar::get_battery_type() const { return battery_type; }
void ElectricCar::set_ec(string M, int H, string B)
{
Car::set(M, H);
battery_type = B;
}
void ElectricCar::output() const
{
cout << "The model and horsepower of the car are " << Car::get_model() << " ," << Car::get_horsepower() << ", and " << battery_type << ".\n";
}
bool operator==(const ElectricCar &C1, const ElectricCar &C2)
{
return C1.Car::get_model() == C2.Car::get_model() && C1.Car::get_horsepower() == C2.Car::get_horsepower() && C1.battery_type == C2.battery_type;
}
```
**main.cpp**
```cpp=
#include <iostream>
#include <string>
#include "Car.h"
using namespace std;
int main()
{
ElectricCar C1("Tesla Model Y", 256, "LFP"), C2;
cout << "Please input the model and horsepower of the car:\n";
string M, B;
int H;
getline(cin, M);
cin >> H;
cout << "Please input the battery type of the car:\n";
cin >> B;
C2.set_ec(M, H, B);
C1.output();
C2.output();
if (C1 == C2)
cout << "Identical!\n";
else
cout << "Different!\n";
return 0;
}
```
# 關於作者
國立東華大學 資訊管理學系 一年級學生
信箱:411235041@gms.ndhu.edu.tw
IG:sumo20020711