Консультация № 184738
11.12.2011, 15:59
627.02 руб.
0 21 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:Помогите написать программу "Пакетный менеджер", ОС Windows XP, Borland Builder C++ 6, Visual Studio 2005.Код прокомментировать.
Условие задачи:
Разработать приложение-пакетный менеджер(базу данных о находящихся на некотором узле пакетах программ).
Разновидности пакетов:
1) Пакет, содержащий основную функциональность пользовательского или системного приложения. Все подобные пакеты должны быть в явном виде доступны пользователю через некоторый интерфейс хранилища. Характеризуется признаком установки пакета, именем файла пакета, номером последней версии, номером установленной версии(если он установлен), именем издателя, ссылками на требуемые для его функционирования другие пакеты.
2) Пакет со вспомогательным ПО(библиотеками). Характеристики те же, но данный пакет должен устанавливаться в системе только при наличии хотя бы одного основного пакета, ссылающегося на него.
3) "Пустой" пакет- связан с конкретным пакетом, но не содержит конкретной версии продукта; с этим пакетом обязательно связан пакет другого типа(основной или вспомогательный) последней версии.
Действия:
Для пакетного менеджера:
инициализация списком пакетов, требуемых для первоначальной установки
установка требуемого пользовательского или "пустого" пакета ( с автоматической установкой всех требуемых пакетов)
установка требуемого пользовательского или "пустого" пакета ( с запросом пользователя на установку каждого требуемого пакета)
удаление указанного пользовательского пакета с автоматическим удалением ненужных пакетов со вспомогательным ПО или без него
очистка системы от неиспользуемых вспомогательных пакетов
глобальное обновление системы с выводом данных о каждом обновленном пакете
Для пакета:
добавление пакета в хранилище(* с контролем ацикличности графа зависимостей)
получение информации о состоянии пакета(тип,установлен или нет, текущая и последняя версии, количество связей с другими пакетами каждого типа)
удаление пакета из хранилища, если это возможно(полное удаление, не снос ПО)
обновление пакета
Для пакета со вспомогательным ПО:
разделение пакета на заданное количество частей с указанием их параметров; считать, что все зависимости наследуются пакетами-наследниками
Для непустого пакета(не связанного с пустым):
объединение пакетов заданного набора с заданием параметров и объединением зависимостей(дуюлирующиеся зависимости устраняются)

Считать, что обновление пакета не влияет на функционал
Порядок выполнения работы:
На основе описания задачи определить состав классов
Разработать иерархию классов и схему их взаимодействия
Для каждого класса определить его состояние и необходимые методы
Разработать и отладить все классы. Приложение для отладки реализовать в виде простой диалоговой программы
Разработать и отладить класс, реализующий работу приложения. Предусмотреть в классе возможность сохранения таблицы в файле и ее восстановления
Повторить разработку контейнерного класса(вместе с необходимыми итераторами), используя стандартную библиотеку STL. Использовать шаблон класса <vector>.


Приложение:
Примерное время на написание программы 2-4 недели. По возможности желательно до 23 декабря.
class Packet {
string name; //название
bool installed; //признак установки
int last_version; //последняя версия
int installed_version; //установленная версия
vector<Packet*> dependency; //список зависимых пакетов
Packet* parent; //родительский пакет (ОС для основных)
public:
Packet ();
Packet (const Packet& p);
~Packet ();
void Load (string n, int lv, vector<Packet*> &d); //загрузка пакета
void Merge (Packet* p); //объединение с другим пакетом
void Divide (int count); //деление на несколько пакетов
void Uninstall (); //удаление
void Install (); //установка
void GetInfo (string &n, int &lv, int &iv, bool &inst, int& depcount); //получение информации
};

class Manager {
vector<Packet*> all; //все пакеты в системе
Packet* system; //корневой пакет - ОС
public:
Manager ();
Manager (vector<Packet*> &def); //инициализация списком пакетов
~Manager ();
int Install (string packet, int ver, bool dependency = true); //установка пакета по имени и версии с или без автоустановки зависимых
int Uninstall (string packet, int ver, bool dependency = true); //удаление -||-
void ClearSystem (); //чистка системы
void UpdateSystem (); //обновление системы
void AddPacket (Packet* p); //добавление пакета в разных вариантах
void AddPacket (string n, int lv, vector<Packet*> &d);
void AddPacket (string n, int lv, vector<string> &d);
};

Данные три класса нужно дополнить и подправить:
class PacketBasicFunction: public Packet //Пакет, содержащий основную функциональность
{
string name; //название
bool installed; //признак установки
int last_version; //последняя версия
int installed_version; //установленная версия
vector<Packet*> dependency; //список зависимых пакетов
Packet* parent; //родительский пакет (ОС для основных)
public:
PacketBasicFunction();
PacketBasicFunction(const Packet& p);
~PacketBasicFunction();
void Merge (Packet* p); //объединение с другим пакетом
};

class PacketSupportSoftWare: public Packet // Пакет со вспомогательным ПО(библиотеками)
{
string name; //название
bool installed; //признак установки
int last_version; //последняя версия
int installed_version; //установленная версия
vector<Packet*> dependency; //список зависимых пакетов
Packet* parent; //родительский пакет (ОС для основных)
public:
void Divide (int count); //деление на несколько пакетов
void Install (); //установка
};

class EmptyPacket: public Packet //"Пустой" пакет
{
Packet* LinkedPacket;
public:
void LinkedPacket();
};

Обсуждение

давно
Посетитель
276566
297
14.12.2011, 23:54
общий
Здравствуйте! Данный текст это пояснение к пункту "Для не пустого пакета":
Под операцией подразумевается создание одного "большого" пакета из
нескольких "маленьких": если имеются пакеты A, B, C, причём пакет A
зависит от B, D, E, а B --- от D и F, то результат объединения
X=Union(A, B, C) зависит от D, E, F. При этом необходимо отдельно
указать название нового пакета X и прочие его параметры. После этой
операции все исходные пакеты удаляются из дерева зависимостей, так как
функциональность итогового пакета поглощает функциональность исходных.
Кроме того, все пакеты, зависимые от каждого из исходных, должны
теперь зависеть от результата операции.

Фраза "Для не пустого пакета(не связанного с пустым)" включена в
задание, так как ни один исходный пакет не может исчезнуть, если его
существование требуется пустым пакетом явно (т.е., когда существует
пустой пакет libcv, пакет с реальным ПО libcv-3.2 не может просто так
исчезнуть, ведь пользователи могли выбрать для установки конкретное
ПО, и менять их настройки нежелательно). Сливать же пустые пакеты явно
не нужно.
Неизвестный
15.12.2011, 13:48
общий
Адресаты:
Я постараюсь всё-таки сделать эту задачу, постараюсь к 23 декабря, если раньше никто другой не возьмётся.
давно
Посетитель
276566
297
22.12.2011, 09:50
общий
Здравствуйте! скажите когда вы примерно выложите программу?
Неизвестный
23.12.2011, 22:16
общий
Адресаты:
Сегодня ночью или завтра ночью. Не успела доделать, везде предновогодний аврал.
Неизвестный
26.12.2011, 02:50
общий
Адресаты:
Вот примерно так. Только не тестировала ещё.
[code h=300]#pragma once

#include <string>
#include <vector>
using namespace std;

enum PacketType {
UndefinedType, Empty, Main, Utility };

const char UndefinedVersion [] = "Undefined";

class Packet
{
protected:
string name;
string author;
vector<Packet*> deps;
bool installed;
int clients;
public:
Packet () : installed (false), clients (0) {};
Packet (const Packet& ep);
Packet (string n, string a, vector<Packet*> d) : name(n), author(a), deps (d) {};
~Packet () {};

bool IsInstalled () {return installed;};
void GetDependencyCount (int &emptyps, int &mainps, int &utilityps);
void Uninstall (bool automat);
bool CanDelete ();

virtual PacketType GetPacketType () {return UndefinedType;};
virtual const const char* GetLastVersion () {return UndefinedVersion;};
virtual const const char* GetInstalledVersion () {return UndefinedVersion;};

virtual void Install (const char* version, bool automat);
virtual void Update () {};

protected:
bool NeedYou ();
void DontNeedYouAnymore ();
friend class PacketManager;
friend class EmptyPacket;
friend class MainPacket;
friend class UtilityPacket;
};

class EmptyPacket : public Packet
{
Packet* linked;
public:
EmptyPacket (Packet* l) : linked(l), Packet() {};
EmptyPacket (const EmptyPacket& ep);
EmptyPacket (string n, string a, vector<Packet*> d, Packet* l) : Packet(n, a, d), linked(l) {};
~EmptyPacket () {};

virtual PacketType GetPacketType () {return Empty;};
};

class MainPacket : public Packet
{
string lastVersion;
string installedVersion;
public:
MainPacket():Packet() {};
MainPacket (const MainPacket& mp):Packet(mp),lastVersion(mp.lastVersion),installedVersion(mp.installedVersion) {};
~MainPacket() {};

bool Merge (Packet* ep);
virtual void Update ();

virtual PacketType GetPacketType () {return Main;};
virtual const const char* GetLastVersion () {return lastVersion.c_str();};
virtual const const char* GetInstalledVersion () {return installedVersion.c_str();};

virtual void Install (const char* version, bool automat);
};

class UtilityPacket : public MainPacket
{
public:
UtilityPacket():MainPacket() {};
UtilityPacket(const UtilityPacket& up) : MainPacket (up) {};
~UtilityPacket ();

Packet** Divide (int count);

virtual PacketType GetPacketType () {return Utility;};
};

class PacketManager
{
Packet system;
public:
PacketManager ();
~PacketManager ();

void Init (vector<Packet*> &ep);
bool Install (string name, string author, string version, bool automat);
bool Uninstall (string name, string autor, bool automat);
void Divide (string name, string author, int count);
void Merge (string name1, string author1, string name2, string author2);
void ClearSystem ();
void Update ();

private:
Packet* Find (string &name, string &author, Packet* begin);
void Replace (Packet* p, Packet** ps, Packet* begin, int n = 1);
void ListofPackets (vector<Packet*> & res, Packet* begin);
};


#include "StdAfx.h"
#include "Packets.h"
#include <algorithm>
#include <iostream>

void Packet::GetDependencyCount (int &emptyps, int &mainps, int &utilityps)
{
emptyps = mainps = utilityps = 0;
for (int i=0; i<deps.size(); i++)
switch (deps[i]->GetPacketType()) {
case Empty:
emptyps++;
break;
case Main:
mainps++;
break;
case Utility:
utilityps++;
break;
}
}

bool Packet::CanDelete ()
{
return (clients==0);
}

void Packet::Uninstall (bool automat)
{
installed = false;
for (int i=0; i<deps.size(); i++) {
deps[i]->DontNeedYouAnymore();
if (deps[i]->CanDelete()) {
if (automat)
deps[i]->Uninstall (true);
else {
cout << "Uninstall " << deps[i]->name << "? (y/n)";
char c;
cin >> c;
if (c=='y') deps[i]->Install (NULL, true);
else cout << "Ok, but program may be not needed anymore.";
}
}
}
}

void Packet::Install (const char* version, bool automat)
{
for (int i=0; i<deps.size(); i++) {
if (deps[i]->installed == false) {
if (automat)
deps[i]->Install (NULL, true);
else {
cout << "Install " << deps[i]->name << "? (y/n)";
char c;
cin >> c;
if (c=='y') deps[i]->Install (NULL, true);
else cout << "Ok, but program may not work correctly.";
}
}
deps[i]->NeedYou();
}
}

bool Packet::NeedYou ()
{
clients++;
return installed;
}

void Packet::DontNeedYouAnymore ()
{
clients--;
}

bool MainPacket::Merge (Packet* ep)
{
name = name + "+" + ep->name;
author = author + "&" + ep->author;
installed = installed||ep->installed;
installedVersion = "1.0";
lastVersion = "1.0";
deps.insert (deps.end(), ep->deps.begin(), ep->deps.end());
unique (deps.begin(), deps.end());
clients+=ep->clients;
delete ep;
ep = NULL;
return true;
}

void MainPacket::Update ()
{
installedVersion = lastVersion;
}

void MainPacket::Install (const char* version, bool automat)
{
if (version!=NULL)
installedVersion = version;
else installedVersion = lastVersion;
Packet::Install (version, automat);
}

Packet** UtilityPacket::Divide (int count)
{
Packet** ps = new Packet* [count];
ps[0] = this;
for (int i=1; i<count; i++)
ps[i] = new Packet (*this);
return ps;
}

PacketManager::PacketManager ()
{
system.Install (NULL, true);
}

PacketManager::~PacketManager ()
{
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
delete ps[i];
}

void PacketManager::Init (vector<Packet*> &ep)
{
system.deps.assign (ep.begin(), ep.end());
}

bool PacketManager::Install (string name, string author, string version, bool automat)
{
Packet* p = Find (name, author, &system);
if (p!=NULL)
p->Install (version.c_str(), automat);
return p!=NULL;
}

bool PacketManager::Uninstall (string name, string autor, bool automat)
{
Packet* p = Find (name, autor, &system);
if (p!=NULL)
p->Uninstall (automat);
return p!=NULL;
}

void PacketManager::Divide (string name, string author, int count)
{
Packet* p = Find (name, author, &system);
if (p->GetPacketType()!=Utility) {
cout << "Cannot divide packet of this type";
return;
}
Replace (p, ((UtilityPacket*)p)->Divide (count), &system, count);
}

void PacketManager::Merge (string name1, string author1, string name2, string author2)
{
Packet* p1 = Find (name1, author1, &system);
Packet* p2 = Find (name2, author2, &system);
if (p1->GetPacketType()==Empty || p1->GetPacketType()==UndefinedType) {
cout << "Cannot merge packet of this type";
return;
}
((MainPacket*)p1)->Merge (p2);
Packet** s = new Packet*[1];
s[0] = p1;
Replace (p2, s, &system);
delete [] s;
}

void PacketManager::ClearSystem ()
{
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
if (ps[i]->CanDelete()) {
ps[i]->Uninstall (true);
delete ps[i];
}
}

void PacketManager::Update ()
{
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
ps[i]->Update();
}

Packet* PacketManager::Find (string &name, string &author, Packet* begin)
{
if (begin->name == name && begin->author == author) return begin;
for (int i = 0; i<begin->deps.size(); i++) {
Packet* p = Find (name, author, begin->deps[i]);
if (p!=NULL) return p;
}
return NULL;
}

void PacketManager::Replace (Packet* p, Packet** ps, Packet* begin, int n)
{
for (int i=0; i<begin->deps.size(); i++) {
Replace (p, ps, begin->deps[i], n);
for (vector<Packet*>::iterator j=begin->deps[i]->deps.begin(); j!=begin->deps[i]->deps.end(); j++)
if (*j == p) {
for (int k = 0; k<n; k++)
begin->deps[i]->deps.insert (j, ps[k]);
break;
}
}
}

void PacketManager::ListofPackets (vector<Packet*> & res, Packet* begin)
{
for (int i=0; i<begin->deps.size(); i++) {
if (find (res.begin(), res.end(), begin->deps[i])==res.end()) res.push_back (begin->deps[i]);
ListofPackets (res, begin->deps[i]);
}
}

[/code]
давно
Посетитель
276566
297
26.12.2011, 10:14
общий
26.12.2011, 22:36
Здравствуйте! Можете код прокомментировать. При компиляции выдает предупреждение "comparing signed and unsigned values" в подобных строчках "i<deps.size()". Где диалоговая программа со списками меню. Скажите где выполнен данный пункт"Повторить разработку контейнерного класса(вместе с необходимыми итераторами), используя стандартную библиотеку STL. Использовать шаблон класса <vector>.". Где реализован данный пункт "Предусмотреть в классе возможность сохранения таблицы в файле и ее восстановления".
давно
Посетитель
276566
297
28.12.2011, 11:24
общий
Здравствуйте! скажите вы можете до завтрашнего дня доделать программу, желательно в районе первой половины дня.
Неизвестный
28.12.2011, 13:40
общий
Адресаты:
Постараюсь.
Неизвестный
29.12.2011, 04:38
общий
Адресаты:
Предупреждение про сравнение знаковых и беззнаковых типов - в данном случае там нет никакого риска, можно просто не обращать внимания. Библиотека stl тут используется. Вот пока комментарии, сохранение в файл завтра постараюсь выложить, там несколько заморочено.
[code h=300]
#pragma once

#include <string>
#include <vector>
using namespace std;

enum PacketType { //тип пакета
UndefinedType, Empty, Main, Utility };

const char UndefinedVersion [] = "Undefined";

class Packet //базовый класс
{
protected:
string name; //имя программы
string author; //автор
vector<Packet*> deps; //зависимости
bool installed; //флаг установки
int clients; //сколько других программ нуждаются в данной
public:
Packet () : installed (false), clients (0) {}; //конструктор по умолчанию
Packet (const Packet& ep):name(ep.name),author(ep.author),deps(ep.deps),installed(ep.installed),clients(ep.clients){}; //конструктор копирования
Packet (string n, string a, vector<Packet*> d) : name(n), author(a), deps (d), installed(false),clients(0) {}; //конструктор с инициализацией
~Packet () {};

bool IsInstalled () {return installed;}; //проверка на установку
void GetDependencyCount (int &emptyps, int &mainps, int &utilityps); //число зависимостей по типам пакетов
void Uninstall (bool automat); //удаление
bool CanDelete (); //можно ли удалять

virtual PacketType GetPacketType () {return UndefinedType;}; //тип пакета
virtual const const char* GetLastVersion () {return UndefinedVersion;}; //версии
virtual const const char* GetInstalledVersion () {return UndefinedVersion;};

virtual void Install (const char* version, bool automat); //установить
virtual void Update () {}; //обновить до последней версии

protected:
bool NeedYou (); //вызывается при установке пакета, зависящего от данного
void DontNeedYouAnymore (); //вызывается при удалении пакета, зависящего от данного
friend class PacketManager; //дружественные классы для доступа к закрытым полям
friend class EmptyPacket;
friend class MainPacket;
friend class UtilityPacket;
};

class EmptyPacket : public Packet
{
Packet* linked; //связанный пакет
public:
EmptyPacket (Packet* l) : linked(l), Packet() {};
EmptyPacket (const EmptyPacket& ep);
EmptyPacket (string n, string a, vector<Packet*> d, Packet* l) : Packet(n, a, d), linked(l) {};
~EmptyPacket () {};

virtual PacketType GetPacketType () {return Empty;};
};

class MainPacket : public Packet
{
string lastVersion; //последняя версия
string installedVersion; //установленная версия
public:
MainPacket():Packet() {};
MainPacket (const MainPacket& mp):Packet(mp),lastVersion(mp.lastVersion),installedVersion(mp.installedVersion) {};
MainPacket (string n, string a, vector<Packet*> d, string lv):Packet(n,a,d),lastVersion(lv){};
~MainPacket() {};

bool Merge (Packet* ep); //объединение с другим пакетом
virtual void Update ();

virtual PacketType GetPacketType () {return Main;};
virtual const const char* GetLastVersion () {return lastVersion.c_str();};
virtual const const char* GetInstalledVersion () {return installedVersion.c_str();};

virtual void Install (const char* version, bool automat);
};

class UtilityPacket : public MainPacket
{
public:
UtilityPacket():MainPacket() {};
UtilityPacket(const UtilityPacket& up) : MainPacket (up) {};
UtilityPacket (string n, string a, vector<Packet*> d, string lv):MainPacket(n,a,d,lv){};
~UtilityPacket ();

Packet** Divide (int count); //разделение на заданное число пакетов

virtual PacketType GetPacketType () {return Utility;};
};

class PacketManager
{
Packet system; //вся система (корень дерева)
public:
PacketManager ();
~PacketManager ();

void Init (vector<Packet*> &ep); //инициализация системы
bool Install (string name, string author, string version, bool automat); //установка пакета
bool Uninstall (string name, string autor, bool automat); //удаление пакета
void Divide (string name, string author, int count); //деление пакета
void Merge (string name1, string author1, string name2, string author2); //объединение пакетов
void ClearSystem (); //очистка системы
void Update (); //обновление системы

private:
Packet* Find (string &name, string &author, Packet* begin); //поиск по дереву
void Replace (Packet* p, Packet** ps, Packet* begin, int n = 1); //замена по дереву
void ListofPackets (vector<Packet*> & res, Packet* begin); //получение всех пакетов списком
};

#include "StdAfx.h"
#include "Packets.h"
#include <algorithm>
#include <iostream>

void Packet::GetDependencyCount (int &emptyps, int &mainps, int &utilityps)
{//проходим по зависимостям и считаем по типам
emptyps = mainps = utilityps = 0;
for (int i=0; i<deps.size(); i++)
switch (deps[i]->GetPacketType()) {
case Empty:
emptyps++;
break;
case Main:
mainps++;
break;
case Utility:
utilityps++;
break;
}
}

bool Packet::CanDelete ()
{//проверяем наличие программ, использующих данную
return (clients==0);
}

void Packet::Uninstall (bool automat)
{//освобождаем все зависимые и удаляем освободившиеся
installed = false;
for (int i=0; i<deps.size(); i++) {
deps[i]->DontNeedYouAnymore();
if (deps[i]->CanDelete()) {
if (automat)
deps[i]->Uninstall (true);
else {
cout << "Uninstall " << deps[i]->name << "? (y/n)";
char c;
cin >> c;
if (c=='y') deps[i]->Install (NULL, true);
else cout << "Ok, but program may be not needed anymore.";
}
}
}
}

void Packet::Install (const char* version, bool automat)
{//занимаем зависимости и устанавливаем их при необходимости
for (int i=0; i<deps.size(); i++) {
if (deps[i]->installed == false) {
if (automat)
deps[i]->Install (NULL, true);
else {
cout << "Install " << deps[i]->name << "? (y/n)";
char c;
cin >> c;
if (c=='y') deps[i]->Install (NULL, true);
else cout << "Ok, but program may not work correctly.";
}
}
deps[i]->NeedYou();
}
}

bool Packet::NeedYou ()
{
clients++;
return installed;
}

void Packet::DontNeedYouAnymore ()
{
clients--;
}

bool MainPacket::Merge (Packet* ep)
{//объединяем в новый пакет, заменяем им текущий
name = name + "+" + ep->name;
author = author + "&" + ep->author;
installed = installed||ep->installed;
installedVersion = "1.0";
lastVersion = "1.0";
deps.insert (deps.end(), ep->deps.begin(), ep->deps.end());
unique (deps.begin(), deps.end());
clients+=ep->clients;
delete ep;
ep = NULL;
return true;
}

void MainPacket::Update ()
{
installedVersion = lastVersion;
}

void MainPacket::Install (const char* version, bool automat)
{
if (version!=NULL)
installedVersion = version;
else installedVersion = lastVersion;
Packet::Install (version, automat);
}

Packet** UtilityPacket::Divide (int count)
{ //делим пакет на несколько, текущий оставляем одним их них
Packet** ps = new Packet* [count];
ps[0] = this;
for (int i=1; i<count; i++)
ps[i] = new Packet (*this);
return ps;
}

PacketManager::PacketManager ()
{ //устанавливаем систему
system.Install (NULL, true);
}

PacketManager::~PacketManager ()
{ //получаем список всех пакетов и удаляем их
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
delete ps[i];
}

void PacketManager::Init (vector<Packet*> &ep)
{ //заполняем систему зависимостями
system.deps.assign (ep.begin(), ep.end());
}

bool PacketManager::Install (string name, string author, string version, bool automat)
{//ищем пакет и устанавливаем, если нашли
Packet* p = Find (name, author, &system);
if (p!=NULL)
p->Install (version.c_str(), automat);
return p!=NULL;
}

bool PacketManager::Uninstall (string name, string autor, bool automat)
{//ищем пакет и удаляем
Packet* p = Find (name, autor, &system);
if (p!=NULL)
p->Uninstall (automat);
return p!=NULL;
}

void PacketManager::Divide (string name, string author, int count)
{//ищем пакет, делим и заменяем его вхождения массивом новых пакетов
Packet* p = Find (name, author, &system);
if (p->GetPacketType()!=Utility) {
cout << "Cannot divide packet of this type";
return;
}
Replace (p, ((UtilityPacket*)p)->Divide (count), &system, count);
}

void PacketManager::Merge (string name1, string author1, string name2, string author2)
{//ищем пакеты, объединяем и заменяем второй первым (т.к. он теперь его содержит)
Packet* p1 = Find (name1, author1, &system);
Packet* p2 = Find (name2, author2, &system);
if (p1->GetPacketType()==Empty || p1->GetPacketType()==UndefinedType) {
cout << "Cannot merge packet of this type";
return;
}
((MainPacket*)p1)->Merge (p2);
Packet** s = new Packet*[1];
s[0] = p1;
Replace (p2, s, &system);
delete [] s;
}

void PacketManager::ClearSystem ()
{//удаляем пакеты, которые можно удалить
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
if (ps[i]->CanDelete()) {
ps[i]->Uninstall (true);
delete ps[i];
}
}

void PacketManager::Update ()
{
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
ps[i]->Update();
}

Packet* PacketManager::Find (string &name, string &author, Packet* begin)
{//рекурсивный поиск по дереву системы
if (begin->name == name && begin->author == author) return begin;
for (int i = 0; i<begin->deps.size(); i++) {
Packet* p = Find (name, author, begin->deps[i]);
if (p!=NULL) return p;
}
return NULL;
}

void PacketManager::Replace (Packet* p, Packet** ps, Packet* begin, int n)
{//рекурсивная замена по дереву системы
for (int i=0; i<begin->deps.size(); i++) {
Replace (p, ps, begin->deps[i], n);
for (vector<Packet*>::iterator j=begin->deps[i]->deps.begin(); j!=begin->deps[i]->deps.end(); j++)
if (*j == p) {
for (int k = 0; k<n; k++)
begin->deps[i]->deps.insert (j, ps[k]);
break;
}
}
}

void PacketManager::ListofPackets (vector<Packet*> & res, Packet* begin)
{//рекурсивное составление списка всех пакетов
for (int i=0; i<begin->deps.size(); i++) {
if (find (res.begin(), res.end(), begin->deps[i])==res.end()) res.push_back (begin->deps[i]);
ListofPackets (res, begin->deps[i]);
}
}


[/code]
давно
Посетитель
276566
297
29.12.2011, 09:59
общий
Здравствуйте! не забудьте написать диалоговую программу.
Неизвестный
29.12.2011, 17:41
общий
это ответ
Здравствуйте, Maverick!
Я размещаю ответом, чтобы больше не продлевать, остальное в мини-форуме буду дополнять. Тут вся программа по заданию, сохранение в файл добавила. Тестовую диалоговую программу Вы, в принципе, можете сами написать, но если не справитесь, я завтра где-то между 9 и 15 выложу, сегодня уже не успею ничего больше.
Пакеты организованы в форме дерева, в принципе все они должны быть связаны с пакетом "система", но я предусмотрела ситуацию, в которой это будет не так.
По комментариям должно быть всё ясно, но если будут вопросы - задавайте.

Приложение:
#pragma once

#include <string>
#include <vector>
using namespace std;

struct strpair {string n; string a;};

enum PacketType { //тип пакета
UndefinedType, Empty, Main, Utility };

const char UndefinedVersion [] = "Undefined";

class Packet //базовый класс
{
protected:
string name; //имя программы
string author; //автор
vector<Packet*> deps; //зависимости
bool installed; //флаг установки
int clients; //сколько других программ нуждаются в данной
public:
Packet () : installed (false), clients (0) {}; //конструктор по умолчанию
Packet (const Packet& ep):name(ep.name),author(ep.author),deps(ep.deps),installed(ep.installed),clients(ep.clients){}; //конструктор копирования
Packet (string n, string a, vector<Packet*> d) : name(n), author(a), deps (d), installed(false),clients(0) {}; //конструктор с инициализацией
~Packet () {};

bool IsInstalled () {return installed;}; //проверка на установку
void GetDependencyCount (int &emptyps, int &mainps, int &utilityps); //число зависимостей по типам пакетов
void Uninstall (bool automat); //удаление
bool CanDelete (); //можно ли удалять

virtual PacketType GetPacketType () {return UndefinedType;}; //тип пакета
virtual const const char* GetLastVersion () {return UndefinedVersion;}; //версии
virtual const const char* GetInstalledVersion () {return UndefinedVersion;};

virtual void Install (const char* version, bool automat); //установить
virtual void Update () {}; //обновить до последней версии

virtual bool Save (FILE* f); //сохранение базовых данных
virtual bool Load (FILE* f, vector<strpair>& dps); //загрузка базовых данных

protected:
bool NeedYou (); //вызывается при установке пакета, зависящего от данного
void DontNeedYouAnymore (); //вызывается при удалении пакета, зависящего от данного
friend class PacketManager; //дружественные классы для доступа к закрытым полям
friend class EmptyPacket;
friend class MainPacket;
friend class UtilityPacket;
};

class EmptyPacket : public Packet
{
Packet* linked; //связанный пакет
int lds;
public:
EmptyPacket () : linked(NULL), Packet() {};
EmptyPacket (Packet* l) : linked(l), Packet() {};
EmptyPacket (const EmptyPacket& ep);
EmptyPacket (string n, string a, vector<Packet*> d, Packet* l) : Packet(n, a, d), linked(l) {};
~EmptyPacket () {};

virtual PacketType GetPacketType () {return Empty;};
virtual bool Save (FILE* f); //сохранение всех данных пустого пакета
virtual bool Load (FILE* f, vector<strpair>& dps); //загрузка
};

class MainPacket : public Packet
{
string lastVersion; //последняя версия
string installedVersion; //установленная версия
public:
MainPacket():Packet() {};
MainPacket (const MainPacket& mp):Packet(mp),lastVersion(mp.lastVersion),installedVersion(mp.installedVersion) {};
MainPacket (string n, string a, vector<Packet*> d, string lv):Packet(n,a,d),lastVersion(lv){};
~MainPacket() {};

bool Merge (Packet* ep); //объединение с другим пакетом
virtual void Update ();

virtual PacketType GetPacketType () {return Main;};
virtual const const char* GetLastVersion () {return lastVersion.c_str();};
virtual const const char* GetInstalledVersion () {return installedVersion.c_str();};

virtual bool Save (FILE* f); //сохранение
virtual bool Load (FILE* f, vector<strpair>& dps); //загрузка

virtual void Install (const char* version, bool automat);
};

class UtilityPacket : public MainPacket
{
public:
UtilityPacket():MainPacket() {};
UtilityPacket(const UtilityPacket& up) : MainPacket (up) {};
UtilityPacket (string n, string a, vector<Packet*> d, string lv):MainPacket(n,a,d,lv){};
~UtilityPacket ();

Packet** Divide (int count); //разделение на заданное число пакетов

virtual PacketType GetPacketType () {return Utility;};
};

class PacketManager
{
Packet system; //вся система (корень дерева)
public:
PacketManager ();
~PacketManager ();

void Init (vector<Packet*> &ep); //инициализация системы
bool Install (string name, string author, string version, bool automat); //установка пакета
bool Uninstall (string name, string autor, bool automat); //удаление пакета
void Divide (string name, string author, int count); //деление пакета
void Merge (string name1, string author1, string name2, string author2); //объединение пакетов
void ClearSystem (); //очистка системы
void Update (); //обновление системы

bool Save (string filename); //сохранение
bool Load (string filename); //загрузка

private:
Packet* Find (string &name, string &author, Packet* begin); //поиск по дереву
void Replace (Packet* p, Packet** ps, Packet* begin, int n = 1); //замена по дереву
void ListofPackets (vector<Packet*> & res, Packet* begin); //получение всех пакетов списком
};

#include "StdAfx.h"
#include "Packet.h"
#include <algorithm>
#include <iostream>

void Packet::GetDependencyCount (int &emptyps, int &mainps, int &utilityps)
{//проходим по зависимостям и считаем по типам
emptyps = mainps = utilityps = 0;
for (int i=0; i<deps.size(); i++)
switch (deps[i]->GetPacketType()) {
case Empty:
emptyps++;
break;
case Main:
mainps++;
break;
case Utility:
utilityps++;
break;
}
}

bool Packet::CanDelete ()
{//проверяем наличие программ, использующих данную
return (clients==0);
}

void Packet::Uninstall (bool automat)
{//освобождаем все зависимые и удаляем освободившиеся
installed = false;
for (int i=0; i<deps.size(); i++) {
deps[i]->DontNeedYouAnymore();
if (deps[i]->CanDelete()) {
if (automat)
deps[i]->Uninstall (true);
else {
cout << "Uninstall " << deps[i]->name << "? (y/n)";
char c;
cin >> c;
if (c=='y') deps[i]->Install (NULL, true);
else cout << "Ok, but program may be not needed anymore.";
}
}
}
}

void Packet::Install (const char* version, bool automat)
{//занимаем зависимости и устанавливаем их при необходимости
for (int i=0; i<deps.size(); i++) {
if (deps[i]->installed == false) {
if (automat)
deps[i]->Install (NULL, true);
else {
cout << "Install " << deps[i]->name << "? (y/n)";
char c;
cin >> c;
if (c=='y') deps[i]->Install (NULL, true);
else cout << "Ok, but program may not work correctly.";
}
}
deps[i]->NeedYou();
}
}

bool Packet::NeedYou ()
{
clients++;
return installed;
}

void Packet::DontNeedYouAnymore ()
{
clients--;
}

bool Packet::Save (FILE* f)
{
if (!f) return false; //проверяем на открытие файл
int er; //пишем все данные в файл текстом
er = fprintf (f, "%s\n%s\n%d\n%d\n%d\n", name.c_str(), author.c_str(), installed, clients, deps.size());
for (int i=0; i<deps.size(); i++) //пишем зависимости в виде имён пакетов
er = fprintf (f, "%s\n%s\n", deps[i]->name.c_str(), deps[i]->author.c_str());
return er>0;
}

bool Packet::Load (FILE* f, vector<strpair>& dps)
{//возвращает список зависимостей в виде имён пакетов
if (!f) return false;
int er1, sz;
char* er;
char s[256]; //считываем данные
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
name = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
author = s;
er1 = fscanf (f, "%d\n%d\n%d\n", &installed, &clients, &sz);
dps.resize (sz);
for (int i=0; i<sz; i++) { //считываем имена зависимостей
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
dps[i].n = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
dps[i].a = s;
}
return (er1>0 && er!=NULL);
}

bool EmptyPacket::Save (FILE* f)
{
if (!f) return false;
bool fl1 = linked->Save(f); //дополнительно сохраняем связанный пакет
er = fprintf (f, "%s\n%s\n", linked->name.c_str(), linked->author.c_str());
bool fl2 = Packet::Save (f);
return (fl1 && fl2);
}

bool EmptyPacket::Load (FILE* f, vector<strpair>& dps)
{
if (!f) return false;
strpair t;
char* er = fgets (s, 255, f);//дополнительно загружаем связанный пакет
s[strlen(s)-1] = '\0';
t.n = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
t.a = s;
bool fl2 = Packet::Load (f, dps);
dps.push_back (t); //кладём связанный пакет в конец списка зависимостей
return (er!=NULL && fl2);
}

bool MainPacket::Merge (Packet* ep)
{//объединяем в новый пакет, заменяем им текущий
name = name + "+" + ep->name;
author = author + "&" + ep->author;
installed = installed||ep->installed;
installedVersion = "1.0";
lastVersion = "1.0";
deps.insert (deps.end(), ep->deps.begin(), ep->deps.end());
unique (deps.begin(), deps.end());
clients+=ep->clients;
delete ep;
ep = NULL;
return true;
}

void MainPacket::Update ()
{
installedVersion = lastVersion;
}

void MainPacket::Install (const char* version, bool automat)
{
if (version!=NULL)
installedVersion = version;
else installedVersion = lastVersion;
Packet::Install (version, automat);
}

bool MainPacket::Save (FILE* f)
{
if (!f) return false;
int er; //сохраняем дополнительно версии
er = fprintf (f, "%s\n%s\n", lastVersion.c_str(), installedVersion.c_str());
bool fl = Packet::Save (f);
return (er>0 && fl);
}

bool MainPacket::Load (FILE* f, vector<strpair>& dps)
{
if (!f) return false;
int sz;
char *er;
char s[256]; //загружаем дополнительно версии
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
lastVersion = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
installedVersion = s;
bool fl = Packet::Load (f, dps);
return (er!=NULL && fl);
}

Packet** UtilityPacket::Divide (int count)
{ //делим пакет на несколько, текущий оставляем одним их них
Packet** ps = new Packet* [count];
ps[0] = this;
for (int i=1; i<count; i++)
ps[i] = new Packet (*this);
return ps;
}

PacketManager::PacketManager ()
{ //устанавливаем систему
system.Install (NULL, true);
}

PacketManager::~PacketManager ()
{ //получаем список всех пакетов и удаляем их
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
delete ps[i];
}

void PacketManager::Init (vector<Packet*> &ep)
{ //заполняем систему зависимостями
system.deps.assign (ep.begin(), ep.end());
}

bool PacketManager::Install (string name, string author, string version, bool automat)
{//ищем пакет и устанавливаем, если нашли
Packet* p = Find (name, author, &system);
if (p!=NULL)
p->Install (version.c_str(), automat);
return p!=NULL;
}

bool PacketManager::Uninstall (string name, string autor, bool automat)
{//ищем пакет и удаляем
Packet* p = Find (name, autor, &system);
if (p!=NULL)
p->Uninstall (automat);
return p!=NULL;
}

void PacketManager::Divide (string name, string author, int count)
{//ищем пакет, делим и заменяем его вхождения массивом новых пакетов
Packet* p = Find (name, author, &system);
if (p->GetPacketType()!=Utility) {
cout << "Cannot divide packet of this type";
return;
}
Replace (p, ((UtilityPacket*)p)->Divide (count), &system, count);
}

void PacketManager::Merge (string name1, string author1, string name2, string author2)
{//ищем пакеты, объединяем и заменяем второй первым (т.к. он теперь его содержит)
Packet* p1 = Find (name1, author1, &system);
Packet* p2 = Find (name2, author2, &system);
if (p1->GetPacketType()==Empty || p1->GetPacketType()==UndefinedType) {
cout << "Cannot merge packet of this type";
return;
}
((MainPacket*)p1)->Merge (p2);
Packet** s = new Packet*[1];
s[0] = p1;
Replace (p2, s, &system);
delete [] s;
}

void PacketManager::ClearSystem ()
{//удаляем пакеты, которые можно удалить
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
if (ps[i]->CanDelete()) {
ps[i]->Uninstall (true);
delete ps[i];
}
}

void PacketManager::Update ()
{//получаем список пакетов и обновляем каждый
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
ps[i]->Update();
}

Packet* PacketManager::Find (string &name, string &author, Packet* begin)
{//рекурсивный поиск по дереву системы
if (begin->name == name && begin->author == author) return begin;
for (int i = 0; i<begin->deps.size(); i++) {
Packet* p = Find (name, author, begin->deps[i]);
if (p!=NULL) return p;
}
return NULL;
}

void PacketManager::Replace (Packet* p, Packet** ps, Packet* begin, int n)
{//рекурсивная замена по дереву системы
for (int i=0; i<begin->deps.size(); i++) {
Replace (p, ps, begin->deps[i], n);
for (vector<Packet*>::iterator j=begin->deps[i]->deps.begin(); j!=begin->deps[i]->deps.end(); j++)
if (*j == p) {
for (int k = 0; k<n; k++)
begin->deps[i]->deps.insert (j, ps[k]);
break;
}
}
}

void PacketManager::ListofPackets (vector<Packet*> & res, Packet* begin)
{//рекурсивное составление списка всех пакетов
for (int i=0; i<begin->deps.size(); i++) {
if (find (res.begin(), res.end(), begin->deps[i])==res.end()) res.push_back (begin->deps[i]);
ListofPackets (res, begin->deps[i]);
}
}

bool PacketManager::Save (string filename)
{
FILE* f = fopen (filename.c_str(), "wt");
if (!f) return false;
vector<Packet*> ps; //получаем список всех пакетов
ListofPackets (ps, &system);
fprintf (f, "%d\n", ps.size()); //сохраняем число пакетов
for (int i=0; i<ps.size(); i++) { //сохраняем каждый пакет последовательно в файле
fprintf (f, "%d\n", ps[i]->GetPacketType());
ps[i]->Save (f);
}
fclose (f); //закрываем файл
return true;
}

bool PacketManager::Load (string filename)
{
FILE* f = fopen (filename.c_str(), "rt");
if (!f) return false;
vector<Packet*> ps; //очищаем систему
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
delete ps[i];
system.deps.clear();
int sz, type;
fscanf (f, "%d\n", &sz); //получаем число пакетов
system.deps.resize (sz);
vector<strpair> *sp = new vector<strpair> [sz]; //подготавливаем массив для имён зависимостей каждого пакета системы
for (int i=0; i<sz; i++) {
fscanf (f, "%d\n", &type); //получаем тип
switch (type) { //в зависимости от типа выделяем память под пакет
case Empty:
system.deps[i] = new EmptyPacket();
break;
case Utility:
system.deps[i] = new UtilityPacket();
break;
case Main:
system.deps[i] = new MainPacket();
break;
default:
system.deps[i] = new Packet();
break;
}
system.deps[i]->Load (f,sp[i]); //грузим данные пакета (вызовется виртуальная функция нужного типа)
}

for (int i=0; i<sz; i++) //ищем ссылки на зависимости для каждого пакета
if (system.deps[i]->deps.size()==0) { //если ссылки ещё не найдены
if (system.deps[i]->GetPacketType()==Empty) { //если пустой пакет
((EmptyPacket*)system.deps[i])->linked = Find (sp[i][sp[i].size()-1].n, sp[i][sp[i].size()-1].a, &system);
sp[i].pop_back(); //грузим связанный и удаляем из списка зависимостей

}
for (int j=0; j<sp[i].size(); j++) { //ищем для каждого имени реальный пакет
Packet* p = Find (sp[i][j].n, sp[i][j].a, &system);
if (p) system.deps[i]->deps.push_back (p); //грузим в список зависимостей ссылку
}
}
return true;
}
давно
Посетитель
276566
297
29.12.2011, 22:51
общий
29.12.2011, 22:52
Здравствуйте! Напишите диалоговую прогу, в нее должны войти данные пункты и то что нужно будет еще по логике:
инициализация списком пакетов, требуемых для первоначальной установки
установка требуемого пользовательского или "пустого" пакета ( с автоматической установкой всех требуемых пакетов)
установка требуемого пользовательского или "пустого" пакета ( с запросом пользователя на установку каждого требуемого пакета)
удаление указанного пользовательского пакета с автоматическим удалением ненужных пакетов со вспомогательным ПО или без него
очистка системы от неиспользуемых вспомогательных пакетов
глобальное обновление системы с выводом данных о каждом обновленном пакете
При компиляции возникли ошибки в данных функциях:
bool EmptyPacket::Save (FILE* f)
{
if (!f) return false;
bool fl1 = linked->Save(f); //дополнительно сохраняем связанный пакет
er = fprintf (f, "%s\n%s\n", linked->name.c_str(), linked->author.c_str());// undefined symbol 'er'
bool fl2 = Packet::Save (f);
return (fl1 && fl2);
}
bool EmptyPacket::Load (FILE* f, vector<strpair>& dps)
{
if (!f) return false;
strpair t;
char* er = fgets (s, 255, f);//дополнительно загружаем связанный пакет //undefined symbol 's'
s[strlen(s)-1] = '\0';
t.n = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
t.a = s;
bool fl2 = Packet::Load (f, dps);
dps.push_back (t); //кладём связанный пакет в конец списка зависимостей
return (er!=NULL && fl2);
}
((EmptyPacket*)system.deps[i])->linked = Find (sp[i][sp[i].size()-1].n, sp[i][sp[i].size()-1].a, &system);
//'EmptyPacket::linked' is not accessible
давно
Посетитель
276566
297
31.12.2011, 17:25
общий
Здравствуйте! скажите когда вы примерно сможете выложить доделанную программу
Неизвестный
02.01.2012, 16:56
общий
Адресаты:
Прошу прощения, я немного отвлеклась на Новый год)) Завтра или послезавтра точно выложу, потому что 5-го я уезжаю.
давно
Посетитель
276566
297
04.01.2012, 10:36
общий
Здравствуйте! Скажите когда вы выложите полностью готовую прогу.
Неизвестный
04.01.2012, 21:49
общий
[code h=300]
#pragma once

#include <string>
#include <vector>
using namespace std;

struct strpair {string n; string a;};

enum PacketType { //тип пакета
UndefinedType, Empty, Main, Utility };

const char UndefinedVersion [] = "Undefined";

class Packet //базовый класс
{
protected:
string name; //имя программы
string author; //автор
vector<Packet*> deps; //зависимости
bool installed; //флаг установки
int clients; //сколько других программ нуждаются в данной
public:
Packet () : installed (false), clients (0) {}; //конструктор по умолчанию
Packet (const Packet& ep):name(ep.name),author(ep.author),deps(ep.deps),installed(ep.installed),clients(ep.clients){}; //конструктор копирования
Packet (string n, string a, vector<Packet*> d) : name(n), author(a), deps (d), installed(false),clients(0) {}; //конструктор с инициализацией
~Packet () {};

bool IsInstalled () {return installed;}; //проверка на установку
void GetDependencyCount (int &emptyps, int &mainps, int &utilityps); //число зависимостей по типам пакетов
void Uninstall (bool automat); //удаление
bool CanDelete (); //можно ли удалять

virtual PacketType GetPacketType () {return UndefinedType;}; //тип пакета
virtual const const char* GetLastVersion () {return UndefinedVersion;}; //версии
virtual const const char* GetInstalledVersion () {return UndefinedVersion;};

virtual void Install (const char* version, bool automat); //установить
virtual void Update () {}; //обновить до последней версии

virtual bool Save (FILE* f); //сохранение базовых данных
virtual bool Load (FILE* f, vector<strpair>& dps); //загрузка базовых данных

protected:
bool NeedYou (); //вызывается при установке пакета, зависящего от данного
void DontNeedYouAnymore (); //вызывается при удалении пакета, зависящего от данного
friend class PacketManager; //дружественные классы для доступа к закрытым полям
friend class EmptyPacket;
friend class MainPacket;
friend class UtilityPacket;
};

class EmptyPacket : public Packet
{
Packet* linked; //связанный пакет
int lds;
public:
EmptyPacket () : linked(NULL), Packet() {};
EmptyPacket (Packet* l) : linked(l), Packet() {};
EmptyPacket (const EmptyPacket& ep);
EmptyPacket (string n, string a, vector<Packet*> d, Packet* l) : Packet(n, a, d), linked(l) {};
~EmptyPacket () {};

virtual PacketType GetPacketType () {return Empty;};
virtual bool Save (FILE* f); //сохранение всех данных пустого пакета
virtual bool Load (FILE* f, vector<strpair>& dps); //загрузка
friend class PacketManager; //дружественные классы для доступа к закрытым полям
};

class MainPacket : public Packet
{
string lastVersion; //последняя версия
string installedVersion; //установленная версия
public:
MainPacket():Packet() {};
MainPacket (const MainPacket& mp):Packet(mp),lastVersion(mp.lastVersion),installedVersion(mp.installedVersion) {};
MainPacket (string n, string a, vector<Packet*> d, string lv):Packet(n,a,d),lastVersion(lv){};
~MainPacket() {};

bool Merge (Packet* ep); //объединение с другим пакетом
virtual void Update ();

virtual PacketType GetPacketType () {return Main;};
virtual const const char* GetLastVersion () {return lastVersion.c_str();};
virtual const const char* GetInstalledVersion () {return installedVersion.c_str();};

virtual bool Save (FILE* f); //сохранение
virtual bool Load (FILE* f, vector<strpair>& dps); //загрузка

virtual void Install (const char* version, bool automat);
friend class PacketManager; //дружественные классы для доступа к закрытым полям
};

class UtilityPacket : public MainPacket
{
public:
UtilityPacket():MainPacket() {};
UtilityPacket(const UtilityPacket& up) : MainPacket (up) {};
UtilityPacket (string n, string a, vector<Packet*> d, string lv):MainPacket(n,a,d,lv){};
~UtilityPacket ();

Packet** Divide (int count); //разделение на заданное число пакетов

virtual PacketType GetPacketType () {return Utility;};
};

class PacketManager
{
Packet system; //вся система (корень дерева)
public:
PacketManager ();
~PacketManager ();

void Init (vector<Packet*> &ep); //инициализация системы
bool Install (string name, string author, string version, bool automat); //установка пакета
bool Uninstall (string name, string autor, bool automat); //удаление пакета
void Divide (string name, string author, int count); //деление пакета
void Merge (string name1, string author1, string name2, string author2); //объединение пакетов
void ClearSystem (); //очистка системы
void Update (); //обновление системы

bool Save (string filename); //сохранение
bool Load (string filename); //загрузка

private:
Packet* Find (string &name, string &author, Packet* begin); //поиск по дереву
void Replace (Packet* p, Packet** ps, Packet* begin, int n = 1); //замена по дереву
void ListofPackets (vector<Packet*> & res, Packet* begin); //получение всех пакетов списком
void Delete (Packet* w, Packet* begin);
};

#include "StdAfx.h"
#include "Packets.h"
#include <algorithm>
#include <iostream>

void Packet::GetDependencyCount (int &emptyps, int &mainps, int &utilityps)
{//проходим по зависимостям и считаем по типам
emptyps = mainps = utilityps = 0;
for (int i=0; i<deps.size(); i++)
switch (deps[i]->GetPacketType()) {
case Empty:
emptyps++;
break;
case Main:
mainps++;
break;
case Utility:
utilityps++;
break;
}
}

bool Packet::CanDelete ()
{//проверяем наличие программ, использующих данную
return (clients==0);
}

void Packet::Uninstall (bool automat)
{//освобождаем все зависимые и удаляем освободившиеся
installed = false;
for (int i=0; i<deps.size(); i++) {
deps[i]->DontNeedYouAnymore();
if (deps[i]->CanDelete()) {
if (automat)
deps[i]->Uninstall (true);
else {
cout << "Uninstall " << deps[i]->name << "? (y/n)";
char c;
cin >> c;
if (c=='y') deps[i]->Install (NULL, true);
else cout << "Ok, but program may be not needed anymore.";
}
}
}
}

void Packet::Install (const char* version, bool automat)
{//занимаем зависимости и устанавливаем их при необходимости
for (int i=0; i<deps.size(); i++) {
if (deps[i]->installed == false) {
if (automat)
deps[i]->Install (NULL, true);
else {
cout << "Install " << deps[i]->name << "? (y/n)";
char c;
cin >> c;
if (c=='y') deps[i]->Install (NULL, true);
else cout << "Ok, but program may not work correctly.";
}
}
deps[i]->NeedYou();
}
}

bool Packet::NeedYou ()
{
clients++;
return installed;
}

void Packet::DontNeedYouAnymore ()
{
clients--;
}

bool Packet::Save (FILE* f)
{
if (!f) return false; //проверяем на открытие файл
int er; //пишем все данные в файл текстом
er = fprintf (f, "%s\n%s\n%d\n%d\n%d\n", name.c_str(), author.c_str(), installed, clients, deps.size());
for (int i=0; i<deps.size(); i++) //пишем зависимости в виде имён пакетов
er = fprintf (f, "%s\n%s\n", deps[i]->name.c_str(), deps[i]->author.c_str());
return er>0;
}

bool Packet::Load (FILE* f, vector<strpair>& dps)
{//возвращает список зависимостей в виде имён пакетов
if (!f) return false;
int er1, sz;
char* er;
char s[256]; //считываем данные
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
name = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
author = s;
er1 = fscanf (f, "%d\n%d\n%d\n", &installed, &clients, &sz);
dps.resize (sz);
for (int i=0; i<sz; i++) { //считываем имена зависимостей
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
dps[i].n = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
dps[i].a = s;
}
return (er1>0 && er!=NULL);
}

bool EmptyPacket::Save (FILE* f)
{
if (!f) return false;
int er = fprintf (f, "%s\n%s\n", linked->name.c_str(), linked->author.c_str());
bool fl2 = Packet::Save (f);
return (er>0 && fl2);
}

bool EmptyPacket::Load (FILE* f, vector<strpair>& dps)
{
if (!f) return false;
strpair t;
char s[256]; //считываем данные
char* er = fgets (s, 255, f);//дополнительно загружаем связанный пакет
s[strlen(s)-1] = '\0';
t.n = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
t.a = s;
bool fl2 = Packet::Load (f, dps);
dps.push_back (t); //кладём связанный пакет в конец списка зависимостей
return (er!=NULL && fl2);
}

bool MainPacket::Merge (Packet* ep)
{//объединяем в новый пакет, заменяем им текущий
name = name + "+" + ep->name;
author = author + "&" + ep->author;
installed = installed||ep->installed;
installedVersion = "1.0";
lastVersion = "1.0";
deps.insert (deps.end(), ep->deps.begin(), ep->deps.end());
unique (deps.begin(), deps.end());
clients+=ep->clients;
delete ep;
ep = NULL;
return true;
}

void MainPacket::Update ()
{
installedVersion = lastVersion;
}

void MainPacket::Install (const char* version, bool automat)
{
if (version!=NULL)
installedVersion = version;
else installedVersion = lastVersion;
Packet::Install (version, automat);
}

bool MainPacket::Save (FILE* f)
{
if (!f) return false;
int er; //сохраняем дополнительно версии
er = fprintf (f, "%s\n%s\n", lastVersion.c_str(), installedVersion.c_str());
bool fl = Packet::Save (f);
return (er>0 && fl);
}

bool MainPacket::Load (FILE* f, vector<strpair>& dps)
{
if (!f) return false;
int sz;
char *er;
char s[256]; //загружаем дополнительно версии
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
lastVersion = s;
er = fgets (s, 255, f);
s[strlen(s)-1] = '\0';
installedVersion = s;
bool fl = Packet::Load (f, dps);
return (er!=NULL && fl);
}

Packet** UtilityPacket::Divide (int count)
{ //делим пакет на несколько, текущий оставляем одним их них
Packet** ps = new Packet* [count];
ps[0] = this;
for (int i=1; i<count; i++)
ps[i] = new Packet (*this);
return ps;
}

PacketManager::PacketManager ()
{ //устанавливаем систему
system.Install (NULL, true);
}

PacketManager::~PacketManager ()
{ //получаем список всех пакетов и удаляем их
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
delete ps[i];
}

void PacketManager::Init (vector<Packet*> &ep)
{ //заполняем систему зависимостями
system.deps.assign (ep.begin(), ep.end());
}

bool PacketManager::Install (string name, string author, string version, bool automat)
{//ищем пакет и устанавливаем, если нашли
Packet* p = Find (name, author, &system);
if (p!=NULL)
p->Install (version.c_str(), automat);
return p!=NULL;
}

bool PacketManager::Uninstall (string name, string autor, bool automat)
{//ищем пакет и удаляем
Packet* p = Find (name, autor, &system);
if (p!=NULL)
p->Uninstall (automat);
return p!=NULL;
}

void PacketManager::Divide (string name, string author, int count)
{//ищем пакет, делим и заменяем его вхождения массивом новых пакетов
Packet* p = Find (name, author, &system);
if (p->GetPacketType()!=Utility) {
cout << "Cannot divide packet of this type";
return;
}
Replace (p, ((UtilityPacket*)p)->Divide (count), &system, count);
}

void PacketManager::Merge (string name1, string author1, string name2, string author2)
{//ищем пакеты, объединяем и заменяем второй первым (т.к. он теперь его содержит)
Packet* p1 = Find (name1, author1, &system);
Packet* p2 = Find (name2, author2, &system);
if (p1->GetPacketType()==Empty || p1->GetPacketType()==UndefinedType) {
cout << "Cannot merge packet of this type";
return;
}
((MainPacket*)p1)->Merge (p2);
Packet** s = new Packet*[1];
s[0] = p1;
Replace (p2, s, &system);
delete [] s;
}

void PacketManager::ClearSystem ()
{//удаляем пакеты, которые можно удалить
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
if (ps[i]->CanDelete()) {
ps[i]->Uninstall (true);
Delete (ps[i], &system);
delete ps[i];
}
}

void PacketManager::Update ()
{//получаем список пакетов и обновляем каждый
vector<Packet*> ps;
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++) {
ps[i]->Update();
cout << ps[i]->name << " updated succesfully\n";
}
}

Packet* PacketManager::Find (string &name, string &author, Packet* begin)
{//рекурсивный поиск по дереву системы
if (begin->name == name && begin->author == author) return begin;
for (int i = 0; i<begin->deps.size(); i++) {
Packet* p = Find (name, author, begin->deps[i]);
if (p!=NULL) return p;
}
return NULL;
}

void PacketManager::Replace (Packet* p, Packet** ps, Packet* begin, int n)
{//рекурсивная замена по дереву системы
for (int i=0; i<begin->deps.size(); i++) {
Replace (p, ps, begin->deps[i], n);
for (vector<Packet*>::iterator j=begin->deps[i]->deps.begin(); j!=begin->deps[i]->deps.end(); j++)
if (*j == p) {
for (int k = 0; k<n; k++)
begin->deps[i]->deps.insert (j, ps[k]);
break;
}
}
}

void PacketManager::Delete (Packet* w, Packet* begin)
{
vector<Packet*>::iterator del = begin->deps.end();
for (vector<Packet*>::iterator i=begin->deps.begin(); i!=begin->deps.end(); i++) {
if (*i==w) {
del = i;
}
else Delete (w, *i);
}
if (del!=begin->deps.end()) begin->deps.erase (del);
}

void PacketManager::ListofPackets (vector<Packet*> & res, Packet* begin)
{//рекурсивное составление списка всех пакетов
for (int i=0; i<begin->deps.size(); i++) {
if (find (res.begin(), res.end(), begin->deps[i])==res.end()) res.push_back (begin->deps[i]);
ListofPackets (res, begin->deps[i]);
}
}

bool PacketManager::Save (string filename)
{
FILE* f = fopen (filename.c_str(), "wt");
if (!f) return false;
vector<Packet*> ps; //получаем список всех пакетов
ListofPackets (ps, &system);
fprintf (f, "%d\n", ps.size()); //сохраняем число пакетов
for (int i=0; i<ps.size(); i++) { //сохраняем каждый пакет последовательно в файле
fprintf (f, "%d\n", ps[i]->GetPacketType());
ps[i]->Save (f);
}
fclose (f); //закрываем файл
return true;
}

bool PacketManager::Load (string filename)
{
FILE* f = fopen (filename.c_str(), "rt");
if (!f) return false;
vector<Packet*> ps; //очищаем систему
ListofPackets (ps, &system);
for (int i=0; i<ps.size(); i++)
delete ps[i];
system.deps.clear();
int sz, type;
fscanf (f, "%d\n", &sz); //получаем число пакетов
system.deps.resize (sz);
vector<strpair> *sp = new vector<strpair> [sz]; //подготавливаем массив для имён зависимостей каждого пакета системы
for (int i=0; i<sz; i++) {
fscanf (f, "%d\n", &type); //получаем тип
switch (type) { //в зависимости от типа выделяем память под пакет
case Empty:
system.deps[i] = new EmptyPacket();
break;
case Utility:
system.deps[i] = new UtilityPacket();
break;
case Main:
system.deps[i] = new MainPacket();
break;
default:
system.deps[i] = new Packet();
break;
}
system.deps[i]->Load (f,sp[i]); //грузим данные пакета (вызовется виртуальная функция нужного типа)
}

for (int i=0; i<sz; i++) //ищем ссылки на зависимости для каждого пакета
if (system.deps[i]->deps.size()==0) { //если ссылки ещё не найдены
if (system.deps[i]->GetPacketType()==Empty) { //если пустой пакет
((EmptyPacket*)system.deps[i])->linked = Find (sp[i][sp[i].size()-1].n, sp[i][sp[i].size()-1].a, &system);
sp[i].pop_back(); //грузим связанный и удаляем из списка зависимостей

}
for (int j=0; j<sp[i].size(); j++) { //ищем для каждого имени реальный пакет
Packet* p = Find (sp[i][j].n, sp[i][j].a, &system);
if (p) system.deps[i]->deps.push_back (p); //грузим в список зависимостей ссылку
}
}
return true;
}

[/code]
[code h=200]
#include "Packets.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
setlocale (LC_ALL, "russian");
PacketManager pm;
vector<Packet*>p(5),d;
bool e = true;
while (e) {
system ("cls");
cout << "1.инициализация списком пакетов, требуемых для первоначальной установки\n";
cout << "2.установка требуемого пользовательского или "пустого" пакета ( с автоматической установкой всех требуемых пакетов)\n";
cout << "3. установка требуемого пользовательского или "пустого" пакета ( с запросом пользователя на установку каждого требуемого пакета)\n";
cout << "4. удаление указанного пользовательского пакета с автоматическим удалением ненужных пакетов со вспомогательным ПО или без него\n";
cout << "5.очистка системы от неиспользуемых вспомогательных пакетов\n";
cout << "6. глобальное обновление системы с выводом данных о каждом обновленном пакете\n";
cout << "7.Выход\nВыбор: ";
int c;
cin >> c;
switch (c) {
case 1:
p[0] = new UtilityPacket ("a", "aa", d, "1.2");
p[1] = new EmptyPacket ("e", "ae", d, p[0]);
d.push_back (p[0]);
p[2] = new MainPacket ("b", "ab", d, "2.3");
p[3] = new UtilityPacket ("c", "ac", d, "1.2");
d.push_back (p[3]);
p[4] = new MainPacket ("d", "ad", d, "2.3");
pm.Init (p);
break;
case 2:
pm.Install ("b", "ab", "2.3", true);
break;
case 3:
pm.Install ("d", "ad", "2.3", false);
break;
case 4:
cout << "С/без (c/b)? ";
char ch;
cin >> ch;
pm.Uninstall ("d", "ad", ch=='c');
break;
case 5:
pm.ClearSystem ();
break;
case 6:
pm.Update ();
break;
case 7:
e = false;
break;
}
}
return 0;
}
[/code]
давно
Посетитель
276566
297
05.01.2012, 10:44
общий
Здравствуйте! скажите как устранить эту ошибку: [Link error]:unresolved external'utility packet::~utility packet()' referenced from D:\L2\unit1.obj
давно
Посетитель
276566
297
10.01.2012, 14:12
общий
Здравствуйте! можете написать функцию которая будет отображать на экран таблицу, в которой будет хранится информация(имя пакета, номер версии, имя автора, флаг установлен/удален, количество зависимостей)
давно
Посетитель
276566
297
11.01.2012, 10:43
общий
Здравствуйте! Вы не могли бы выложить функцию вывода таблицы на экран до 16.00 и также желательно выложить функцию печати содержимого файла.Нужно очень срочно!!!
Неизвестный
11.01.2012, 15:05
общий
Адресаты:
Функция печати, добавьте в класс PacketManager
Код:
void PacketManager::Print ()
{
vector<Packet*> ps; //получаем список всех пакетов
ListofPackets (ps, &system);
cout << endl;
for (int i=0; i<ps.size(); i++) {
switch (ps[i]->GetPacketType()) {
case Empty:
cout << "Empty packet: " << ps[i]->name << " (c)" << ps[i]->author << "\nLinked packet:" << ((EmptyPacket*)ps[i])->linked->name;
break;
case Utility:
cout << "Utility packet: " << ps[i]->name << " (c)" << ps[i]->author << "\nInstalled version:" << ((UtilityPacket*)ps[i])->installedVersion;
cout << "\nLast version:" << ((UtilityPacket*)ps[i])->lastVersion;
break;
case Main:
cout << "Main packet: " << ps[i]->name << " (c)" << ps[i]->author << "\nInstalled version:" << ((UtilityPacket*)ps[i])->installedVersion;
cout << "\nLast version:" << ((UtilityPacket*)ps[i])->lastVersion;
break;
}
cout << "\nDependency count: " << ps[i]->deps.size();
}
}
Неизвестный
11.01.2012, 15:29
общий
Адресаты:
Печать содержимого файла:
Код:
void PacketManager::PrintFile (string filename)
{
FILE* f = fopen (filename.c_str(), "rt");
if (!f) return false;
char *s = new char[256];
while ((s = fgets (s, 255, f))!=NULL)
cout << s;
delete [] s;
fclose (f);
Форма ответа