В очередной раз взываю к помощи професионалов. У нас есть предмет ООП, там мы как бы разбиваемся на группы и выполняем задание, в общем такое задание один из участников реализовал, но выяснились недостатки и очевидные несоответствия с условием и все - переделать и доработать уже не можем, а сроки жмут. Далее представляю всю программу в исходнике. Задание следующее
Цитата
Реализовать программу, выполняющую ограниченный набор команд. Команды и аргументы к ним записываются в текстовом файле. Имя файла передается в аргументах командной строки. Каждая команда имеет свой набор аргументов. Если процессор не знает какую либо команду, то он выводит сообщение об ошибке и продолжает работать со следующей командой.
Необходимо реализовать следующие команды:
Название Аргументы Описание Примеры
print <строка> Распечатать на экране строку, заданную в аргументе print Hello World
eval <expression> Вычислить простую арифметическую операцию (+ , - , * , /). Результат вывести на экран. В случае некорректных аргументов вызывать исключение std::invalid_argument eval 8 / 2
createfile <file> Создать файл c именем <file>. Если файл уже существует, то пересоздать. Запросить ввод данных от пользователя (одна строка), записать введенные данные в файл. createfile test.txt
exec <command> Запустить командную строку, что записана в <command>. Используйте функцию system() из библиотеки "linesystem.h". exec notepad.exe test.txt
copy test.txt test2.txt
increment <file>
<file value> Прочитать содержимое файла <file> и проинтерпретировать его как int. Если в int не конвертируется вызывать исключение std::invalid_argument. Иначе увеличить полученное число на заданное значение и перезаписать в файл. Если число не задано, увеличить на 1. increment test.txt
increment test.txt 1
viewfile <file> Вывести содержимое файла c именем <file> на экран. Если файл не существует, вызывать исключение std::invalid_argument viewfile test.txt
Пример исходного файла для командного процессора:
Каждая команда представляется в виде класса, отнаследованного от абстрактного класса Command:
1. Файл считывается построчно с помощью класса для работы с потоками std::ifstream.
2. Команды хранятся в защищенном поле класса типа std::list
3. Обход элементов списка осуществляется с помощью итератора std::iterator
Пример использования класса CommandList:
Необходимо реализовать следующие команды:
Название Аргументы Описание Примеры
print <строка> Распечатать на экране строку, заданную в аргументе print Hello World
eval <expression> Вычислить простую арифметическую операцию (+ , - , * , /). Результат вывести на экран. В случае некорректных аргументов вызывать исключение std::invalid_argument eval 8 / 2
createfile <file> Создать файл c именем <file>. Если файл уже существует, то пересоздать. Запросить ввод данных от пользователя (одна строка), записать введенные данные в файл. createfile test.txt
exec <command> Запустить командную строку, что записана в <command>. Используйте функцию system() из библиотеки "linesystem.h". exec notepad.exe test.txt
copy test.txt test2.txt
increment <file>
<file value> Прочитать содержимое файла <file> и проинтерпретировать его как int. Если в int не конвертируется вызывать исключение std::invalid_argument. Иначе увеличить полученное число на заданное значение и перезаписать в файл. Если число не задано, увеличить на 1. increment test.txt
increment test.txt 1
viewfile <file> Вывести содержимое файла c именем <file> на экран. Если файл не существует, вызывать исключение std::invalid_argument viewfile test.txt
Пример исходного файла для командного процессора:
print Hello
print I know 2+2=
eval 2+2
print Please input your age:
createfile age.txt
increment age.txt
print It is your age in next year:
viewfile age.txt
print You could check it
exec notepad.exe age.txt
Каждая команда представляется в виде класса, отнаследованного от абстрактного класса Command:
class Command {Для инициализации и выполнения списка команд необходимо реализовать класс CommandList, который должен содержать следующие методы и операторы:
private:
string args;
public:
Command(const string& s = "") : args(s){};
void setArgs(const string& s) {
args = s;
};
const string& getArgs() const {
return args;
};
friend istream& operator>>(istream& in, Command& c) {
return in >> c.args;
};
friend ostream& operator<<(ostream& out, const Command& c) {
return out << c.getName() << " " << c.args << endl;
};
virtual const string& getName() const = 0;
virtual void execute() const throw (std::invalid_argument) = 0;
};
friend ostream& operator<<(ostream& out, const CommandList& c) {Особенности реализации класса CommandList:
// Вывести на экран все команды
// Обход списка с помощью класса std:iterator
return out;
};
friend istream& operator>>(istream& in, CommandList& c) {
// Считать из потока.
// В случае консольного ввода
// выполнение прекращается если строка равна ^D
return in;
};
void init(const string& file) {
// Считать из файла, используя оператор >>
}
void execute() const throw (std::invalid_argument) {
// Выполнить все команды.
// Обход списка с помощью класса std:iterator
}
1. Файл считывается построчно с помощью класса для работы с потоками std::ifstream.
2. Команды хранятся в защищенном поле класса типа std::list
3. Обход элементов списка осуществляется с помощью итератора std::iterator
Пример использования класса CommandList:
CommandList cl = CommandList();
// Чтение из файла:
cl.init("commands.txt");
cl.execute();
// Чтение с консоли:
cin >> cl;
cout << cl;
cl.execute();
Сам код:
cmanager.h:
#pragma once
#ifndef CMANAGER_H
#define CMANAGER_H
#include <fstream>
#include "pcontainer.h"
class CManager
{
private:
PervertedContainer f_command_list;
CManager();
CManager(const CManager&);
const CManager& operator=(const CManager&);
public:
CManager(std::ifstream& fin);
~CManager();
void execute();
};
#endif //CMANAGER_H
command.h:
#pragma once
#ifndef COMMAND_H
#define COMMAND_H
#include <string>
#include "pcontainer.h"
class Command:public StorableElement
{
private:
const Command& operator=(const Command&);
public:
static Command *create(std::string name);
virtual void print()=0;
virtual void execute()=0;
virtual void init(std::string arg)=0;
};
class PrintCommand:public Command
{
private:
std::string f_arg;
PrintCommand();
PrintCommand(const PrintCommand&);
const PrintCommand& operator=(const PrintCommand&);
public:
static const std::string f_name;
static PrintCommand *create();
void print();
void execute();
void init(std::string arg);
};
class CreateCommand:public Command
{
private:
std::string f_arg;
CreateCommand();
CreateCommand(const CreateCommand&);
const CreateCommand& operator=(const CreateCommand&);
public:
static const std::string f_name;
static CreateCommand *create();
void print();
void execute();
void init(std::string arg);
};
class ExecCommand:public Command
{
private:
std::string f_arg;
ExecCommand();
ExecCommand(const ExecCommand&);
const ExecCommand& operator=(const ExecCommand&);
public:
static const std::string f_name;
static ExecCommand *create();
void print();
void execute();
void init(std::string arg);
};
class IncCommand:public Command
{
private:
std::string f_arg;
IncCommand();
IncCommand(const IncCommand&);
const IncCommand& operator=(const IncCommand&);
public:
static const std::string f_name;
static IncCommand *create();
void print();
void execute();
void init(std::string arg);
};
class DecCommand:public Command
{
private:
std::string f_arg;
DecCommand();
DecCommand(const DecCommand&);
const DecCommand& operator=(const DecCommand&);
public:
static const std::string f_name;
static DecCommand *create();
void print();
void execute();
void init(std::string arg);
};
class ViewCommand:public Command
{
private:
std::string f_arg;
ViewCommand();
ViewCommand(const ViewCommand&);
const ViewCommand& operator=(const ViewCommand&);
public:
static const std::string f_name;
static ViewCommand *create();
void print();
void execute();
void init(std::string arg);
};
#endif //COMMAND_H
container.h:
#pragma once
#ifndef CONTAINER_H
#define CONTAINER_H
#include <exception>
#include <stdexcept>
template<class _type> class Container
{
private:
class Elem
{
private:
Elem *f_prev;
Elem *f_next;
_type f_data;
Elem(const Elem& el);
const Elem& operator=(const Elem& el);
public:
Elem();
Elem(_type data,Elem *const insertbefore);
~Elem();
_type get_data()const;
_type& get_data_ref();
Elem *get_next()const;
Elem *get_prev()const;
void set_next(Elem *const next);
void set_prev(Elem *const prev);
};
Elem *f_first;
int f_count;
int f_state;
Elem f_afterlast;
public:
class Iterator
{
private:
const Container *f_parent;
Elem *f_el;
bool f_bad;
int f_state;
int get_state()const;
public:
class bad_iterator:public std::exception
{
public:
virtual const char *what()const;
};
Iterator();
Iterator(const Iterator& it);
Iterator(const Container *const cont,Elem *const el);
const Iterator& operator=(const Iterator& it);
bool is_bad()const;
const Container *get_parent()const;
Elem *get_elem()const;
bool operator==(const Iterator& it)const;
bool operator!=(const Iterator& it)const;
_type& operator*();
_type operator*()const;
const Iterator& operator++();
const Iterator operator++(int);
const Iterator& operator--();
const Iterator operator--(int);
~Iterator();
};
Container();
Container(const Container& cont);
const Container& operator=(const Container& cont);
~Container();
const Iterator begin()const;
const Iterator end()const;
void insert(_type data,const Iterator &it);
void remove(const Iterator &it);
const Elem *get_afterlast()const;
const Elem *get_first()const;
int get_state()const;
void add(_type data);
void clear();
int size()const;
_type operator[](int pos)const;
_type& operator[](int pos);
};
#include "container.hh"
#endif //CONTAINER_H
pcontainer.h:
#pragma once
#ifndef PCONTAINER_H
#define PCONTAINER_H
#include "container.h"
class StorableElement
{
public:
virtual void print()=0;
};
class Iterator
{
private:
public:
virtual bool hasNext()=0;
virtual StorableElement *next()=0;
};
class PervertedContainer
{
private:
Container<StorableElement *> f_cont;
PervertedContainer(const PervertedContainer&);
const PervertedContainer& operator=(const PervertedContainer&);
public:
class ListIterator:public Iterator
{
friend class PervertedContainer;
private:
Container<StorableElement *>::Iterator f_it;
ListIterator();
ListIterator(Container<StorableElement *>& cont);
public:
ListIterator(const ListIterator&);
const ListIterator& operator=(const ListIterator&);
~ListIterator();
bool hasNext();
StorableElement *next();
};
typedef void(*cont_handle)(StorableElement *data);
PervertedContainer();
~PervertedContainer();
static PervertedContainer *allocate();
static void release(PervertedContainer *cont);
void add(StorableElement *el);
void insert(const int pos,StorableElement *el);
int size()const;
StorableElement *get(const int pos);
StorableElement *replace(const int pos,StorableElement *el);
StorableElement *remove(const int pos);
void foreach(cont_handle proc);
void foreach_reverse(cont_handle proc);
ListIterator iterator();
};
#endif //PCONTAINER_H
test.h
#pragma once
#ifndef TEST_H
#define TEST_H
#include "pcontainer.h"
class TestStorableElement:public StorableElement
{
private:
public:
int f_data;
void print();
};
#endif //TEST_H
cmanager.cpp
#include <iostream>
#include <exception>
#include "cmanager.h"
#include "command.h"
CManager::CManager(std::ifstream& fin)
{
while(!fin.eof())
{
std::string name;
std::string arg;
getline(fin,name,' ');
getline(fin,arg,'\n');
if(name.length())
{
try
{
Command *cmd=Command::create(name);
cmd->init(arg);
f_command_list.add(cmd);
}
catch(std::exception& exc)
{
std::cout<<"Error: "<<exc.what()<<std::endl;
}
}
}
}
CManager::~CManager()
{
}
namespace
{
void exec_proc(StorableElement *el)
{
Command *cmd=dynamic_cast<Command *>(el);
if(cmd)
{
try
{
cmd->execute();
}
catch(std::exception& exc)
{
std::cout<<"Error: "<<exc.what()<<std::endl;
}
}
}
}
void CManager::execute()
{
f_command_list.foreach(exec_proc);
}
command.cpp
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <exception>
#include "command.h"
//--------------------------------------------------------------------------
// Command
//--------------------------------------------------------------------------
Command *Command::create(std::string name)
{
if(PrintCommand::f_name==name)
{
return PrintCommand::create();
}
if(CreateCommand::f_name==name)
{
return CreateCommand::create();
}
if(ExecCommand::f_name==name)
{
return ExecCommand::create();
}
if(IncCommand::f_name==name)
{
return IncCommand::create();
}
if(DecCommand::f_name==name)
{
return DecCommand::create();
}
if(ViewCommand::f_name==name)
{
return ViewCommand::create();
}
throw std::exception("unknown command");
}
//--------------------------------------------------------------------------
// PrintCommand
//--------------------------------------------------------------------------
const std::string PrintCommand::f_name="print";
PrintCommand::PrintCommand()
{
}
PrintCommand *PrintCommand::create()
{
return new PrintCommand;
}
void PrintCommand::print()
{
std::cout<<f_name;
}
void PrintCommand::init(std::string arg)
{
f_arg=arg;
}
void PrintCommand::execute()
{
std::cout<<f_arg<<std::endl;
}
//--------------------------------------------------------------------------
// CreateCommand
//--------------------------------------------------------------------------
const std::string CreateCommand::f_name="createfile";
CreateCommand::CreateCommand()
{
}
CreateCommand *CreateCommand::create()
{
return new CreateCommand;
}
void CreateCommand::print()
{
std::cout<<f_name;
}
void CreateCommand::init(std::string arg)
{
f_arg=arg;
}
void CreateCommand::execute()
{
std::ofstream fout;
fout.open(f_arg.c_str(),std::ios_base::out);
if(!fout.is_open())
{
throw std::exception("bad file");
}
std::string input_string;
getline(std::cin,input_string);
fout<<input_string;
fout.close();
}
//--------------------------------------------------------------------------
// ExecCommand
//--------------------------------------------------------------------------
const std::string ExecCommand::f_name="exec";
ExecCommand::ExecCommand()
{
}
ExecCommand *ExecCommand::create()
{
return new ExecCommand;
}
void ExecCommand::print()
{
std::cout<<f_name;
}
void ExecCommand::init(std::string arg)
{
f_arg=arg;
}
void ExecCommand::execute()
{
::system(f_arg.c_str());
}
//--------------------------------------------------------------------------
// IncCommand
//--------------------------------------------------------------------------
const std::string IncCommand::f_name="increment";
IncCommand::IncCommand()
{
}
IncCommand *IncCommand::create()
{
return new IncCommand;
}
void IncCommand::print()
{
std::cout<<f_name;
}
void IncCommand::init(std::string arg)
{
f_arg=arg;
}
void IncCommand::execute()
{
int value=0;
{
std::ifstream fin;
fin.open(f_arg.c_str(),std::ios_base::in);
if(!fin.is_open())
{
throw std::exception("bad file");
}
fin>>value;
if(fin.fail())
{
throw std::exception("bad integer");
}
fin.close();
}
{
std::ofstream fout;
fout.open(f_arg.c_str(),std::ios_base::out | std::ios_base::trunc);
if(!fout.is_open())
{
throw std::exception("bad file");
}
fout<<(value+1);
fout.close();
}
}
//--------------------------------------------------------------------------
// DecCommand
//--------------------------------------------------------------------------
const std::string DecCommand::f_name="decrement";
DecCommand::DecCommand()
{
}
DecCommand *DecCommand::create()
{
return new DecCommand;
}
void DecCommand::print()
{
std::cout<<f_name;
}
void DecCommand::init(std::string arg)
{
f_arg=arg;
}
void DecCommand::execute()
{
int value=0;
{
std::ifstream fin;
fin.open(f_arg.c_str(),std::ios_base::in);
if(!fin.is_open())
{
throw std::exception("bad file");
}
fin>>value;
if(fin.fail())
{
throw std::exception("bad integer");
}
fin.close();
}
{
std::ofstream fout;
fout.open(f_arg.c_str(),std::ios_base::out | std::ios_base::trunc);
if(!fout.is_open())
{
throw std::exception("bad file");
}
fout<<(value-1);
fout.close();
}
}
//--------------------------------------------------------------------------
// ViewCommand
//--------------------------------------------------------------------------
const std::string ViewCommand::f_name="viewfile";
ViewCommand::ViewCommand()
{
}
ViewCommand *ViewCommand::create()
{
return new ViewCommand;
}
void ViewCommand::print()
{
std::cout<<f_name;
}
void ViewCommand::init(std::string arg)
{
f_arg=arg;
}
void ViewCommand::execute()
{
std::ifstream fin;
fin.open(f_arg.c_str(),std::ios_base::in);
if(!fin.is_open())
{
throw std::exception("bad file");
}
std::string line;
while(!fin.eof())
{
getline(fin,line);
std::cout<<line<<std::endl;
}
fin.close();
}
main.cpp
#include <iostream>
#include <fstream>
#include "cmanager.h"
int main(int argc,char **argv)
{
if(argc < 2)
{
std::cout<<"too few arguments"<<std::endl;
}
std::ifstream fin;
fin.open(argv[1],std::ios_base::in);
if(!fin.is_open())
{
std::cout<<"bad file"<<std::endl;
}
CManager mgr(fin);
fin.close();
mgr.execute();
return 0;
}
pcontainer.cpp
#include "pcontainer.h"
PervertedContainer::PervertedContainer()
{
}
PervertedContainer::~PervertedContainer()
{
}
PervertedContainer *PervertedContainer::allocate()
{
try
{
return new PervertedContainer;
}
catch(...)
{
return 0;
}
}
void PervertedContainer::release(PervertedContainer *cont)
{
delete cont;
}
void PervertedContainer::add(StorableElement *el)
{
try
{
f_cont.add(el);
}
catch(...)
{
}
}
void PervertedContainer::insert(const int pos,StorableElement *el)
{
Container<StorableElement *>::Iterator it=f_cont.begin();
for(int i=0;i < pos;i++)
{
it++;
}
try
{
f_cont.insert(el,it);
}
catch(...)
{
}
}
int PervertedContainer::size()const
{
return f_cont.size();
}
StorableElement *PervertedContainer::get(const int pos)
{
try
{
return f_cont[pos];
}
catch(...)
{
return 0;
}
}
StorableElement *PervertedContainer::replace(const int pos,StorableElement *el)
{
Container<StorableElement *>::Iterator it=f_cont.begin();
for(int i=0;i < pos;i++)
{
it++;
}
try
{
StorableElement *old=(*it);
f_cont.remove(it);
insert(pos,el);
return old;
}
catch(...)
{
return 0;
}
}
StorableElement *PervertedContainer::remove(const int pos)
{
Container<StorableElement *>::Iterator it=f_cont.begin();
for(int i=0;i < pos;i++)
{
it++;
}
try
{ StorableElement *old=(*it);
f_cont.remove(it);
return old;
}
catch(...)
{
return 0;
}
}
void PervertedContainer::foreach(cont_handle proc)
{
for(Container<StorableElement *>::Iterator it=f_cont.begin();f_cont.end()!=it;it++)
{
proc(*it);
}
}
void PervertedContainer::foreach_reverse(cont_handle proc)
{
for(int i=f_cont.size()-1;i >= 0;i--)
{
proc(f_cont[i]);
}
}
PervertedContainer::ListIterator PervertedContainer::iterator()
{
return ListIterator(f_cont);
}
//--------------------------------------------------------------------------
// ListIterator
//--------------------------------------------------------------------------
PervertedContainer::ListIterator::ListIterator(Container<StorableElement *>& cont)
{
f_it=cont.begin();
}
PervertedContainer::ListIterator::ListIterator(const ListIterator& it)
{
f_it=it.f_it;
}
const PervertedContainer::ListIterator& PervertedContainer::ListIterator::operator=(const ListIterator& it)
{
if(this!=&it)
{
f_it=it.f_it;
}
return (*this);
}
PervertedContainer::ListIterator::~ListIterator()
{
}
bool PervertedContainer::ListIterator::hasNext()
{
return (!f_it.is_bad() && (f_it.get_parent()->end())!=f_it);
}
StorableElement *PervertedContainer::ListIterator::next()
{
if(hasNext())
{
StorableElement *old=*f_it;
f_it++;
return old;
}
return 0;
}
test.cpp
#include <iostream>Вот, в чем суть. Преподаватель сказал, что в задании четко указанны классы и их формат - нужно сделать соответствие, верно реализовать абстрактный класс - тут он неполный, и вообще не совсем соответствует указанному в задание - прошу помочь... другое было - просто посмотреть и разглядеть недочеты....вот тут вообще не ясно, т.е. очень просим помочь (видимо с точки зрения правильного или желательного написания программ или с точки зрения профессионального программиста - общие советы по написанию подобных программ). Главное все таки на тему абстрактного класса и дореализации тех методов что там указаны - очень надо, всю суть командного процессора уже сделали (основные методы сделаны, пограмма верно работает) - остались мелочи, но на них стопор, а сроки жмут...
#include "test.h"
#include "pcontainer.h"
void TestStorableElement::print()
{
std::cout<<f_data;
}
void test()
{
}