2013-04-15 134 views
0

我試圖解決練習22(第4章)在C++的思考,但有些東西我失蹤了,因爲也經過幾天的工作,我的解決方案沒有做它的工作。我不太喜歡在解決練習時尋求幫助,但在這一刻我感到不知所措。動態堆棧分配

創建一個存放Stashes的堆棧。每個Stash將從輸入文件中保存五行 。使用新的創建Stashes。讀取一個文件到 您的堆棧,然後重新打印它的原始形式從提取它從 堆棧。

#include "CppLib.h" 
#include "Stack.h" 
#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 

using namespace std; 

//typedef unsigned int uint; 

int main() { 
    ifstream in("main.cpp"); 

    Stack stackStashes; 
    stackStashes.initialize(); 

    Stash linesStash; 
    linesStash.initialize(sizeof(char) * 80); 

    string line; 
    bool flag = true; 
    while (flag) { 
     for (int i = 1; flag && (i <= 5); i++) 
      if ((flag = (bool)getline(in, line))) 
       linesStash.add(line.c_str()); 

     if (flag) { 
      stackStashes.push(new Stash(linesStash)); 
      linesStash.cleanup(); 
      linesStash.initialize(sizeof(char) * 80); 
     } 
    } 

    Stash* s; 
    char* cp; 
    int z = 0; 
    while ((s = (Stash*)stackStashes.pop()) != 0) { 
     while ((cp = (char*)s->fetch(z++)) != 0) 
      cout << "s->fetch(" << z << ") = " 
       << cp << endl; 

     delete s; 
    } 

    s->cleanup(); 
    stackStashes.cleanup(); 
    return 0; 
} 

我試着用向量解決它,而無需使用標誌的,我所有的解決方案返回一個錯誤。而且,在我的所有實驗中,情況都更糟,但是唯一剩下的就是這個。
以下是本書提供的圖書館。以下所有代碼均由Bruce Eckel編寫。
CppLib.cpp,CppLib.h, Stack.cpp,Stack.h,require.h

+4

而錯誤是?我認爲這是我今天第四次或第五次說,今天只有10:49。 –

+0

它不起作用?當您嘗試運行控制檯時,會回退一些行,然後窗口會終止該線程。 – Overflowh

+2

@sftrabbit這意味着你已經起得太早:) – jrok

回答

1

哇,這很糟糕。恐怕你的代碼沒有問題,只有布魯斯埃克爾的。問題是,Stash對象不能被複制,但你讓副本這裏

stackStashes.push(new Stash(linesStash)); 

這導致程序崩潰。

你沒辦法知道。你必須重寫你的程序這樣的東西

while (flag) { 
    Stash * stash_ptr = new Stash(); 
    for (int i = 1; flag && (i <= 5); i++) 
     if ((flag = (bool)getline(in, line))) 
      stash_ptr->add(line.c_str()); 

    if (flag) { 
     stackStashes.push(stash_ptr); 
    } 

這樣的事情,無論如何,我還沒有測試過它。重點是它不復制任何Stash對象,一切都通過Stash指針來完成。

建議您試試更好的書嗎?雖然對於Bruce Eckel來說是公平的,但他可能還沒有引入對象複製的概念,也沒有預料到任何人都會編寫試圖複製Stash的代碼。

+0

Ehm但是..當我寫這個時,像我非常確定它的任務應該是「採取堆棧 - >添加另一個元素與推 - >這個元素應該成爲一個品牌NEW linesStash鑄造成一個Stash「。爲什麼這成爲一個副本?然而你是對的,這本書還沒有介紹對象複製的概念。 – Overflowh

+0

(但是,你能建議我一本更好的書嗎?謝謝。) – Overflowh

+0

@unNaturhal'stackStashes.push(new Stash(linesStash))'創建一個新的Stash對象,但通過*複製現有的'LinesStash'對象來初始化它。用C++術語來說,你正在調用*拷貝構造函數*。我的版本使用'new Stash()'而不是'Stash(linesStash)',所以它調用*默認構造函數*。 – john

0

我也用這個練習掙扎了很多,但終於解決了。我希望這是你正在尋找的。

請檢查這個main.cpp:它的工作原理與原始源(它有你在問題中鏈接)沒有任何修改。

我希望這會有所幫助。隨意問問,如果有什麼不清楚。

//Create a Stack that holds Stashes. Each Stash will hold 
//five lines from an input file. Create the Stashes using 
//new. Read a file into your Stack, then reprint it in its 
//original form by extracting it from the Stack. 

#include <iostream> 
#include <fstream> 
#include "cpplib.h" 
#include "stack.h" 
#include <stdexcept> 
#include <string> 
#include <cstdlib> 

const std::string FILENAME = "file.txt"; 
const unsigned int LINES_PER_STASH = 5; 
const unsigned int MAX_LINE_LENGTH = 80; 

int main(){ 

    std::ifstream in; 

    try 
    { 
    in.open(FILENAME.c_str(),std::ios_base::in); 
    if(!in.is_open()) 
    { 
     throw new std::exception(); 
    } 
    } 
    catch(...) 
    { 
    std::cout << "Error should be handled" << std::endl; 
    exit(-1); 
    } 



    unsigned int lineCount = 0; 

    Stack stack; 
    stack.initialize(); 

    Stash* pStash = 0; 
    std::string line; 

    while(std::getline(in, line)) 
    { 
    if(! (lineCount % LINES_PER_STASH)) 
    { 
     if(lineCount) 
     { 
     stack.push(pStash); 
     } 
     pStash = new Stash(); 
     pStash->initialize(MAX_LINE_LENGTH); 
    } 
    pStash->add(line.c_str()); 

    lineCount++; 
    } 
    if(0 < pStash->count()) { 
     stack.push(pStash); 
    } 

    in.close(); 


    Stash* tempStash; 
    Stack* pTempStack = new Stack(); 
    pTempStack->initialize(); 


    //revert the order of stashes in a new stack 
    while((tempStash = static_cast<Stash*>(stack.pop())) != 0) 
    { 
    pTempStack->push(tempStash); 
    } 

    stack.cleanup(); 



    while(0 != (tempStash = static_cast<Stash*>(pTempStack->pop()))) 
    { 
    //a more elegant and consistent way should be to solve this loop with 'while', still 'for' and worked fine at first try, so I left it as it is: 
    for(int i = 0; i < LINES_PER_STASH; i++){ 
     std::cout << (char*)tempStash->fetch(i) << std::endl; 
    } 
    delete tempStash; 
    } 

    pTempStack->cleanup(); 
    delete pTempStack; 

    return 0; 
}