动态堆栈分配(来自c++思维)

Dynamic Stack allocation (from Thinking in C++)

本文关键字:c++ 思维 来自 堆栈 分配 动态      更新时间:2023-10-16

我试图解决练习22(第4章)从思考在c++ ,但有一些东西,我错过了,因为也经过几天的工作,我的解决方案不做它的工作。我不太喜欢在解决问题时寻求帮助,但在这一刻我感到不知所措。

创建一个存储存储的堆栈。每个储物箱将容纳五行从输入文件。使用new创建藏匿库。将文件读入您的堆栈,然后通过从中提取它以原始形式重新打印它堆栈。

#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.

哇,这太糟糕了。恐怕你的代码没有问题,只有布鲁斯·埃克尔的。问题是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的代码。

我在这个练习中也挣扎了很多,但最终解决了。我希望这就是你要找的。

请检查这个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;
}

我也想到了练习23的解决方案。

修改习题22,以便创建一个封装堆栈的结构体。用户应该只通过成员函数添加和获取行,但实际上该结构体恰好使用了Stack of Stashes。

Stack.cpp源代码

#include "CppLib.h"
#include "Stack.h"
#include "require.h"
using namespace::std;
const int bufsize = 80;
void Stack::Link::initialize(Stash* dat, Link* nxt) {
    data = dat;
    next = nxt;
}
void Stack::initialize() {
    head = 0;
    Stash* stash = new Stash;
    stash->initialize(sizeof(char) * bufsize);
    Link* newLink = new Link;
    newLink->initialize(stash, head);
    head = newLink;
}
void Stack::push(const void * element) {
    // each stash stores 5 lines
    if (head->data->count() < 5) {
        head->data->add(element);
    } else {
        // Push old stash
        Link* newLink = new Link;
        newLink->initialize(head->data, head);
        head = newLink;
        // Create new stash
        Stash* newStash = new Stash;
        newStash->initialize(sizeof(char) * bufsize);
        head->data = newStash;
        // Add element to new stash
        head->data->add(element);
    }
}
void* Stack::peek() {
    require(head != 0, "Stack empty");
    return head->data->fetch(head->data->next);
}
void* Stack::pop() {
    if (head == 0) return 0;
    void* result;
    Stash* stash = head->data;
    int index = stash->next;
    // retrieve next stash
    if (index < 1) {
        stash->cleanup();
        head = head->next;
        if (head == 0) return 0; // Check if next stash exists
        stash = head->data;
        index = stash->next;
    }
    // pop 5 lines within stash
    result = stash->fetch(index - 1);
    stash->next = index - 1;
    return result;
}
void Stack::cleanup() {
    require(head == 0, "Stack not empty");
}