使用者工具

網站工具


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 (外部編輯)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki