1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
|
#include <cstring>
#include <iostream>
#ifndef CLASS_ELEM_HPP
#define CLASS_ELEM_HPP
struct Elem {
int info {};
Elem* next { nullptr };
bool fatto { false };
char* descr {};
Elem(int, Elem*, bool, const char*);
~Elem();
};
#endif // CLASS_ELEM_HPP
Elem::Elem(int info_arg, Elem* next_arg, bool fatto_arg, const char* descr_arg)
: info { info_arg }
, next { next_arg }
, fatto { fatto_arg }
, descr { new char[std::strlen(descr_arg) + 1] }
{
std::strcpy( descr, descr_arg );
}
Elem::~Elem()
{
// // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
// // TODO: delete this after debugging
std::cout << "Deleting element -> info: " << info
<< "; fatto: " << std::boolalpha << fatto
<< "; descr: " << descr << '\n';
// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
delete[] descr;
}
#ifndef CLASS_TODOLIST_HPP
#define CLASS_TODOLIST_HPP
class ToDoList {
public:
ToDoList() = default;
ToDoList(const ToDoList&);
// // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
// // You need to implement the following methods; see rule of 3/5/0:
// ToDoList(ToDoList&&) = default;
// ToDoList& operator= (const ToDoList&) = default;
// ToDoList& operator= (ToDoList&&) = default;
// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~ToDoList();
void aggiungi(const char*, int);
void fai(const char*);
void cancella_fatti();
ToDoList& operator +=(const ToDoList&);
private:
Elem* testa { nullptr };
//friend:
friend std::ostream& operator<<(std::ostream&, const ToDoList&);
};
#endif // CLASS_TODOLIST_HPP
ToDoList::~ToDoList()
{
// // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
// // TODO: delete this after debugging
std::cout << "Deleting list...\n";
// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (testa != nullptr) {
for (Elem* p { testa }, *r { p }; p->next != nullptr; p = r){
r = p->next;
delete p;
p = nullptr;
}
}
}
// // You should return something that says: "Node not ready!"
void ToDoList::aggiungi(const char * descr, int priority)
{
if (descr == nullptr || std::strlen(descr) > 40 || priority < 1) {
return;
}
Elem* p { testa };
Elem* q { p };
for (/**/; q != nullptr && q->info <= priority; q = q->next) {
p = q;
}
Elem* r = new Elem { priority, q, false, descr };
// // The following logic is not clear to me. I assume you know what you're
// // doing:
//caso della massima priorità:inserimento in testa
if ( q != testa ) {
p->next = r;
}
//inserimento in mezzo, se la priorità non è massima.
else {
testa = r;
}
}
void ToDoList::fai(const char *descr)
{
//gestisco l'input:
if(descr == nullptr || std::strlen(descr) > 40) {
return;
}
for(Elem* p { testa }; p != nullptr; p = p->next) {
if( (std::strcmp(p->descr, descr) == 0) && (!p->fatto) ) {
p->fatto = true;
}
}
}
void ToDoList::cancella_fatti()
{
for (Elem* p { testa }, *q { p }; p != nullptr; /**/) {
if (p->fatto) {
if (p->info >= 4) {
break;
}
// elemento trovato, cancella
if (p == testa) { // caso eliminazione in testa
q = testa = testa->next;
} else { // caso eliminazione in mezzo
q->next = p->next;
}
// deallocazione della memoria dinamica
delete p;
p = q;
}
else {
q = p;
p = p->next;
}
}
}
ToDoList& ToDoList::operator+= (const ToDoList& rhs)
{
// // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
// // I'd say this is not canonical. Maybe the user wants to double the
// // current list. Compare std::string::operator+=()
// // std::string s { "my text" };
// // s += s; // legal!
// affronto problema aliasing:
if (&rhs == this) {
return *this;
}
// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// inserisco tutti gli elementi della seconda lista
for(Elem* p { rhs.testa }; p != nullptr; p = p->next) {
//chiamo la funzione che inserisce ordinatamente gli elementi della lista;
aggiungi(p->descr, p->info);
}
return *this;
}
std::ostream& operator<< (std::ostream& os, const ToDoList& rhs)
{
for (Elem* p = rhs.testa; p != nullptr; p = p->next) {
if (p->fatto) {
os << "V " << p->info << " - " << p->descr << '\n';
} else {
os << " " << p->info << " - " << p->descr << '\n';
}
}
return os;
}
int main()
{
// PRIMA PARTE:
std::cout << "--- PRIMA PARTE ---\n"
"Test costruttore e funzione aggiungi\n";
ToDoList tdl_1;
tdl_1.aggiungi("tdl_1.Task1", 2);
tdl_1.aggiungi("tdl_1.Task2", 2);
tdl_1.aggiungi("tdl_1.Task3", 1);
tdl_1.aggiungi("tdl_1.Task4", 3);
tdl_1.aggiungi("tdl_1.Task5", 2);
std::cout << tdl_1 << '\n';
std::cout << "Test distruttore\n";
{
ToDoList tdl_2;
tdl_2.aggiungi("tdl_2.Task1", 1);
tdl_2.aggiungi("tdl_2.Task2", 2);
tdl_2.aggiungi("tdl_2.Task3", 3);
}
std::cout << "Distruttore chiamato\n";
// SECONDA PARTE:
std::cout << "--- SECONDA PARTE ---\n"
"Test operatore +=\n";
ToDoList tdl_3;
tdl_3.aggiungi("tdl_3.Task1", 1);
tdl_3.aggiungi("tdl_3.Task2", 2);
tdl_3.aggiungi("tdl_3.Task3", 3);
tdl_3.aggiungi("tdl_3.Task4", 4);
tdl_1 += tdl_3;
std::cout << tdl_1 << '\n';
std::cout << "Test funzione fai\n";
tdl_1.fai("tdl_1.Task1");
tdl_1.fai("tdl_1.Task2");
tdl_1.fai("tdl_1.Task2");
std::cout << tdl_1 << '\n';
std::cout << "Test funzione cancella_fatti\n";
tdl_1.cancella_fatti();
std::cout << tdl_1 << '\n';
// TERZA PARTE:
std::cout << "--- TERZA PARTE ---\n"
"Test funzione aggiungi con input non validi\n";
tdl_1.aggiungi(nullptr, 1);
tdl_1.aggiungi("tdl_1.Task1", 0);
tdl_1.aggiungi("tdl_1.Task2", -1);
tdl_1.aggiungi("tdl_1.Task con descrizione troppo lunga, che non sta nei "
"quaranta caratteri specificati nel testo del compito", 1);
std::cout << tdl_1 << '\n';
std::cout << "Test funzione fai con input non validi\n";
tdl_1.fai(nullptr);
tdl_1.fai("tdl_1.Task inesistente");
std::cout << tdl_1 << '\n';
std::cout << "Test funzione cancella_fatti con cancellazione in testa e in "
"coda\n";
tdl_1.fai("tdl_1.Task3");
tdl_1.fai("tdl_1.Task4");
tdl_1.fai("tdl_1.Task4");
tdl_1.cancella_fatti();
std::cout << tdl_1 << '\n';
return 0;
}
|