2011-08-10 65 views
0

我需要爲一個具有對象數組作爲私有變量的類定義一個讀取和打印函數。我必須從文本文件讀入對象並將它們打印到屏幕上。爲此,我需要超載< <和>>運算符。我知道我需要使用循環來讀取和打印存儲在數組中的信息,但我不知道如何完成此操作。我的講師給了我們一個基本的函數原型和我需要堅持的主要功能的代碼。我明白這是如何與公共結構一起工作的,因爲我已經完成了這個確切的場景,但是班級的私有變量「讓我絆倒了。I/O過載和從文本文件中讀取

class EmployeeList { 
public: 
    //Constructors 
    EmployeeList(); 
    EmployeeList(istream&); 
    //Accessors 
    bool isEmpty() const; 
    bool isFull() const; 
    int size() const; //Number of employees in list 
    Employee item(int i) const; //i'th employee 
    //Mutators 
    void setItem(int i,const Employee& e); 
    //I/O functions, sets the i'th emplyee to e 
    void read(istream&); 
    void print(ostream&) const; 

private: 
    enum {MAXSIZE = 100}; 
    Employee list[MAXSIZE]; 
    int count; //Number of employees in the current list 
}; 

EmployeeList::EmployeeList() { 
    count = 0; 
} 

EmployeeList::EmployeeList(istream& in) { 
    //list[MAXSIZE] = in; 
} 

bool EmployeeList::isEmpty() const { 
    return (count == 0); 
} 

bool EmployeeList::isFull() const { 
    return (count == MAXSIZE); 
} 

int EmployeeList::size() const { 
    return count; 
} 

Employee EmployeeList::item(int i) const { 
} 

void EmployeeList::setItem(int i, const Employee& e) { 
} 

void EmployeeList::read(istream& in) { 
    Employee tempList; 
    while (in >> tempList) { 
    } 
} 

void EmployeeList::print(ostream& out) const { 
    for (int i=0; i < size(); i++) { 
    } 

    cout << out; 
} 

上面的部分是EmployeeListList類,下面的部分是重載函數。註釋掉的部分是我認爲可能工作但沒有的想法。

istream& operator>>(istream& in, EmployeeList& l) { 
    l.read(in); 
    return in; 
} 

ostream& operator<<(ostream& out, const EmployeeList& l) { 
    l.print(out); 
    return out; 
} 

以下是給我們的主要功能。

int main() { 
    authorInfo(); 
    ifstream infile("a1in.txt"); 
    if(!infile) { 
     cout << "file 'alin.txt' not found."; 
     return EXIT_FAILURE; 
    } 
    EmployeeList theList(infile); 

    cout << endl; 
    cout << theList.size() << " employees read:\n" << theList << endl; 
    process(theList); 
    return EXIT_SUCCESS; 

} 

希望有人能引導我走向正確的方向!讓我知道你是否需要更多的代碼。謝謝!

編輯: 僱員讀取和打印功能:

void Employee::read(istream& in) { 
    in >> name >> id >> salary; 
} 

void Employee::print(ostream& out) const { 
    out << getName() <<" "<< getID() <<" "<< getSalary() << endl; 
} 

僱員重載:

istream& operator>>(istream& in, Employee& e) { 
    e.read(in); 
    return in; 
} 

ostream& operator<<(ostream& out, const Employee& e) { 
    e.print(out); 
    return out; 
} 

編輯2:更新讀()函數。與此同時的線是錯誤的地方。

void EmployeeList::read(istream& in) { 
    Employee inEmployee; 
    while (in >> inEmployee && count < MAXSIZE) { 
     list[count] = inEmployee; 
     count++; 
    } 
} 

編輯3:這是我迄今爲止的print()函數。它確實打印,但我得到了默認的構造函數信息,而不是來自文件的信息。這是讀取還是打印功能問題?我正在考慮閱讀功能。

void EmployeeList::print(ostream& out) const { 
    cout << endl; 
    for (int i=0; i < count; i++) { 
     out << list[count]; 
    } 
} 
+0

私人變量爲什麼會讓你失望?在公共部分,快速瀏覽看起來應該是所有你需要的。 – BugFinder

+0

姓名,編號或工資中的空白將會中斷Employee :: read。 –

回答

1

數組界限

在你的類,你必須:

Employee list[MAXSIZE]; 

鑑於此,有一個錯誤,你試過代碼:

EmployeeList::EmployeeList(istream& in) { 
    list[MAXSIZE] = in; 
} 

list只有元素從list[0]list[MAXSIZE - 1]list[MAXSIZE]是一個超過數組的末尾,並且無效。

構造

這就是說,我會強烈反對有一個構造函數的istream&。用默認的構造函數構造一個空對象會更好,然後使用它的read(istream&)方法(通過operator <<)加載數據。換句話說,而不是:

EmployeeList theList(infile); 

使用:

EmployeeList theList; 
infile >> theList; 

如果你要求有一個構造函數的istream&,只是它初始化對象之後調用read()

EmployeeList::EmployeeList(istream& in): count(0) { 
    read(in); 
} 

請注意,只有一個構造函數被稱爲,因此EmployeeList::EmployeeList()中的初始化在EmployeeList::EmployeeList(istream&)中不會發生。我聽說C++的新版本處理這種不必要的重複,但是暫時就是我們所在的地方。

命名

另一件事:你的代碼將與更好的變量名容易混淆。在這種情況下:

void EmployeeList::read(istream& in) { 
    Employee tempList; 
    while (in >> tempList) { 
    } 
} 

不要說tempList因爲它不是「臨時清單」,這是已經被讀取單個Employee。更好的是:

void EmployeeList::read(istream& in) { 
    Employee inEmployee; 
    while (in >> inEmployee) { 
    list[count++] = inEmployee; 
    } 
} 
+0

感謝這一切都非常有幫助! – RedFred

+0

+1聲音建議。然而,我不同意這樣的建議:不要寫一個採用'istream&'的構造函數,如果你想從一個流中加載一個不可變的對象,這是獲取它的好方法。 –

+0

我可以看到你的觀點,但由於兩個原因,建議不要這樣做:1)由於它必須至少重複默認構造函數的代碼(在C++ 11中修復),並且2)隱式類型轉換從'istream'轉換爲' EmployeeList'可能會令人驚訝(通過使用'explicit'關鍵字解決)。所以,不是一個表演阻止者,但不是我想在介紹性課程中加入的東西(「你使用的C++不是標準C++,恐懼運行」)。 –

0

您可以從頭開始瞭解如何閱讀輸入內容。這種方法,這很可能是不完整的,我拿到的是:

EmployeeList::EmployeeList(istream& in) { 
    count = 0; 
    read(in); // delegate it to avoid duplication 
} 

void EmployeeList::read(istream& in) { 
    Employee tempList; 
    while (in >> tempList && count < MAXSIZE) { 
    list[count] = tempList; 
    ++count; 
    } 
} 

您將需要重載operator>>Employee類這個工作。

+0

當我現在編譯時,我在'inEmployee'中遇到'錯誤:'operator''不匹配'。這是否與我的Employee類有關?如果你也可以看到它會有幫助嗎? – RedFred

+0

按照我的建議,你是否爲'Employee'類重載'operator >>'?在你的代碼中,只顯示'EmployeeList'類的重載。 –

+0

是的,我的工作方式與EmployeeList相同。 – RedFred

0

這看起來像一個家庭作業,所以我會盡力只是給你一個提示:

void EmployeeList::read(istream& in) { 

    Employee tempList; 
    while (in >> tempList) { 
    //here you are creating a tempList so after you fill in the values in tempList 
    //the tempList is to become a part of Employee list[MAXSIZE]; 
    } 
} 

,你如何填入值?你做到這一點使用你的構造和維護count

EmployeeList::EmployeeList(istream& in) { 
    //here... 
} 
0

這是我如何寫,沒有骨架約束。隨意適應您的任務要求。

來源:http://www.ideone.com/R9EeF

IOSTREAMS是很難掌握。您必須閱讀std::getline,std::ios標誌和字符串流以瞭解如何使用它們解析員工列表。

我更喜歡給你一個工作模板(你不能用於你的任務,因爲我根本沒有使用骨架),因爲有很多關於iostreams的說法。

也可以隨時提問,以便我可以提高我的答案與您的實際問題。

+0

我很確定我們不能使用stringstream,我不知道我需要嗎?我們也不能使用它必須使用類的向量。由於這個原因,我不太瞭解這些事情,這意味着我無法很好地遵循你的代碼。 – RedFred

+0

@RedFred:我使用矢量,因爲否則如果讀取失敗就很難回滾。一旦你閱讀了一個由字符分隔的字符串,stringstream是非常方便的,但並不是絕對必要的。我再說一遍:編寫正確的istream閱讀器非常麻煩,我向您展示的代碼僅用於展示正確執行此操作的方法。它的目的是閱讀(至少從表面上)理解並用作模板,而不是複製並粘貼到您的作業中。 –