动态堆栈分配(来自c++思维)
Dynamic Stack allocation (from Thinking in C++)
我试图解决练习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");
}