cpp:example1
國立屏東商業技術學院 資訊工程系 物件導向程式設計
1. 實例演練
本節以cpp.hw2第二題為例,改以類別方式來實作,
- 物件指標陣列
- 成員函式多載
- istream
- ifstream
- string類別
- stringstream類別與數值轉換
請先參考下面的程式碼:
#include <iostream> #include <string> using namespace std; #ifndef _NAME_ #define _NAME_ class Name { private: string firstname; string lastname; public: Name(); Name(string n); void set_firstname(string fn); string get_firstname(); void set_lastname(string ln); string get_lastname(); void show(); }; #endif
#include "name.h" Name::Name() { } Name::Name(string n) { unsigned pos=n.find(" "); firstname = n.substr(0,pos); lastname = n.substr(pos+1,n.size()-firstname.size()); } void Name::set_firstname(string fn) { firstname=fn; } string Name::get_firstname() { return firstname; }; void Name::set_lastname(string ln) { lastname=ln; } string Name::get_lastname() { return lastname; } void Name::show() { cout << firstname << " " << lastname << endl; }
上面這兩個檔案分別是「Name」類別的定義與實作。下面則是「Member」類別的定義與實作:
#ifndef _MEMBER_ #define _MEMBER_ #include "name.h" enum Program {Gold, Silver}; class Member { private: Name *name; string phone; Program memberProgram; union { double discount; int freeMinute; } benefit; public: void showInfo(); void setPhone(string str); Name *getName(); void setName(Name *n); void setProgram(Program p); void setBenefit(int f); void setBenefit(double d); }; #endif
#include "member.h" #include "name.h" void Member::showInfo() { name->show(); cout << phone << " "; if(memberProgram==Gold) { cout << "Gold" << " " << benefit.discount << endl; } else { cout << "Silver" << " " << benefit.freeMinute << endl; } } void Member::setPhone(string str) { phone = str; } Name * Member::getName() { return name; } void Member::setName(Name *n) { name = n; } void Member::setProgram(Program p) { memberProgram = p; } void Member::setBenefit(int f) { benefit.freeMinute = f; } void Member::setBenefit(double d) { benefit.discount = d; }
我們打算設計一個類別「DataGetter」用以取得使用者輸入的資料:
#include <iostream> #include <istream> #include <sstream> #include <string> #include "member.h" using namespace std; #ifndef _DATA_GETTER_ #define _DATA_GETTER_ class DataGetter { public: string getAString(istream &is); Member *getMemberData(istream &is); }; #endif
在這個定義中,我們設計了兩個成員函式,用以取得一個字串以及取得會員資料。在設計上,這兩個函式都有一個參數「istream &is」,可以配合cin或是檔案的物件來進行資料的存取,其實作如下:
#include "dataGetter.h" #include "member.h" string DataGetter::getAString(istream &is) { string str; getline(is, str); return str; } Member * DataGetter::getMemberData(istream &is) { Member *newMember=new Member; string str; getline(is, str); newMember->setName(new Name(str)); getline(is, str); newMember->setPhone(str); getline(is, str); if(str.compare("Gold")==0) { newMember->setProgram(Gold); getline(is, str); double discount; stringstream convert; convert << str; if(!(convert >> discount)) discount=0.0; newMember->setBenefit(discount); } else if(str.compare("Silver")==0) { newMember->setProgram(Silver); getline(is, str); int freeMinute; stringstream convert; convert << str; if(!(convert>> freeMinute)) freeMinute=0; newMember->setBenefit(freeMinute); } return newMember; }
在上述的實作中,我們使用了定義在「<sstream>」中的,「stringstream」來進行字串與數值間的轉換。現在讓我們來看看,如何使用上述的類別來實作cpp.hw2:
#include <iostream> #include <fstream> #include "member.h" #include "dataGetter.h" using namespace std; typedef Member* Members; int main() { Members *members = new Members[5]; DataGetter *dg = new DataGetter; ifstream fin("members.dat"); for(int i=0;i<5;i++) { members[i] = dg->getMemberData(fin); } fin.close(); cout << "Input: "; string findName = dg->getAString(cin); bool found=false; while(findName.compare("Quit")!=0) { for(int i=0;i<5;i++) { if(((members[i]->getName())->get_lastname()).compare(findName)==0) { members[i]->showInfo(); found=true; } } if(!found) cout << "Member not found!" << endl; found=false; cout << "Input: "; findName = dg->getAString(cin); } cout << "Bye" << endl; delete [] members; }
在「main.cpp」的實作中,我們先以
ifstream fin("members.dat");
「ifstream」是定義在「<fstream>」中,我們用以開啟members.dat檔案,其檔案內容如下:
Jun Wu 0912345678 Gold 0.8 Ming-Chung Liu 0988123456 Silver 100 Cho-Ming Kuo 0999999999 Silver 80 Sing-Shi Chang 0933444555 Gold 0.95 Ping Kuo 0955333222 Gold 0.9
我們利用「DataGetter」類別來取得使用者輸入的資料:
DataGetter *dg = new DataGetter;
所取得的資料將會放在我們所建立的存放會員物件的陣列:
typedef Member* Members; Members *members = new Members[5];
在使用「getMemberData()」成員函式時,我們是以「fin」做為參數來透過檔案存取資料:
for(int i=0;i<5;i++) { members[i] = dg->getMemberData(fin); } fin.close();
最後,我們以下面的程式碼,完成程式所需的處理:
cout << "Input: "; string findName = dg->getAString(cin); bool found=false; while(findName.compare("Quit")!=0) { for(int i=0;i<5;i++) { if(((members[i]->getName())->get_lastname()).compare(findName)==0) { members[i]->showInfo(); found=true; } } if(!found) cout << "Member not found!" << endl; found=false; cout << "Input: "; findName = dg->getAString(cin); } cout << "Bye" << endl; delete [] members;
本實例的Makefile如下:
all: dataGetter.o name.o member.o g++ main.cpp name.o member.o dataGetter.o -o main dataGetter.o: dataGetter.cpp dataGetter.h g++ -c dataGetter.cpp name.o: name.cpp name.h g++ -c name.cpp member.o: member.cpp member.h g++ -c member.cpp clean: rm -f *.o main *.*~ *~
cpp/example1.txt · 上一次變更: 2019/07/02 15:01 (外部編輯)