compito fatto.

I have a problem with the final parte of main() and I don't understand why.
These are the code with main and his header files.
Is there someone who can help me, please?
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
main():

#include "compito.h"
#include <iostream>
using namespace std;

int main(){
   // PRIMA PARTE:
   cout << "--- PRIMA PARTE ---" << endl;
   cout << "Test costruttore e funzione aggiungi" << endl;
   ToDoList tdl;
   tdl.aggiungi("Task1", 2);
   tdl.aggiungi("Task2", 2);
   tdl.aggiungi("Task3", 1);
   tdl.aggiungi("Task4", 3);
   tdl.aggiungi("Task5", 2);
   cout << tdl << endl;

   cout << "Test distruttore" << endl;
   {
       ToDoList tdl2;
       tdl2.aggiungi("Task1", 1);
       tdl2.aggiungi("Task2", 2);
       tdl2.aggiungi("Task3", 3);
   }
   cout << "Distruttore chiamato" << endl;

   // SECONDA PARTE:
   cout << "--- SECONDA PARTE ---" << endl;
   cout << "Test operatore +=" << endl;
   ToDoList tdl3;
   tdl3.aggiungi("Task1", 1);
   tdl3.aggiungi("Task2", 2);
   tdl3.aggiungi("Task3", 3);
   tdl3.aggiungi("Task4", 4);
   tdl += tdl3;
   cout << tdl << endl;

   cout << "Test funzione fai" << endl;
   tdl.fai("Task1");
   tdl.fai("Task2");
   tdl.fai("Task2");
   cout << tdl << endl;

   cout << "Test funzione cancella_fatti" << endl;
   tdl.cancella_fatti();
   cout << tdl << endl;
    // TERZA PARTE:
    cout << "--- TERZA PARTE ---" << endl;
    cout << "Test funzione aggiungi con input non validi" << endl;
    tdl.aggiungi(NULL, 1);
    tdl.aggiungi("Task1", 0);
    tdl.aggiungi("Task2", -1);
    tdl.aggiungi("Task con descrizione troppo lunga, che non sta nei quaranta caratteri specificati nel testo del compito", 1);
    cout << tdl << endl;

    cout << "Test funzione fai con input non validi" << endl;
    tdl.fai(NULL);
    tdl.fai("Task inesistente");
    cout << tdl << endl;

    cout << "Test funzione cancella_fatti con cancellazione in testa e in coda" << endl;
    tdl.fai("Task3");
    tdl.fai("Task4");
    tdl.fai("Task4");
    tdl.cancella_fatti();
    cout << tdl << endl;
   return 0;
}
compito.h:
#include<iostream>
#include<cstring>
using namespace std;
struct elem {
    int info;
    elem *pun;
    bool fatto;
    char*descr;
};
class ToDoList{
private: elem*testa;
    ToDoList(const ToDoList&);
public:
    ToDoList(){testa=NULL;};
    void aggiungi(const char*,int);
    friend ostream& operator<<(ostream &,const ToDoList&);
    ~ToDoList();
    //Seconda parte
     ToDoList& operator +=(const ToDoList &);
     void fai(const char*);
     void cancella_fatti();
};
compito.cpp:
#include "compito.h"
void ToDoList::aggiungi(const char * descr, int prio) {
    //sanitizzazione input:
    if(descr == NULL || strlen(descr)>40 || prio<1) return;
       elem*p=testa,*q;
       for(q=p;q!=NULL && q->info <= prio;q=q->pun)
           p=q;
            elem*r=new elem;
            //attenzione:se non si fa il new char di descr, si va in segmentation fault.
            r->descr = new char[strlen(descr)+1];
            //metto i valori da aggiungere alla lista
            r->info=prio;
            r->fatto=false;
    strcpy(r->descr,descr);
            r->pun=q;
            //caso della massima priorità:inserimento in testa
            if(q!=testa) p->pun = r;
            //inserimento in mezzo, se la priorità non è massima.
            else testa = r;
}

ostream &operator<<(ostream &os, const ToDoList &T) {
    elem*p;
    for(p=T.testa;p!=NULL;p=p->pun) {
        if (p->fatto)
            os << "V "<< p->info << " - " << p->descr << endl;
        else
        os << "  " << p->info << " - " << p->descr << endl;
    }
        return os;
}

ToDoList::~ToDoList() {
   elem*r;
   if(testa!=NULL)
       for (elem*p = testa; p->pun != NULL;p=r){
           r=p->pun;
           delete[]p->descr;
           delete p;
   }
}

ToDoList &ToDoList::operator+=(const ToDoList &T2) {
    // affronto problema aliasing:
    if(&T2 == this)
        return *this;

    // inserisco tutti gli elementi della seconda lista

    elem* p;
    for(p = T2.testa; p != NULL; p = p->pun)
       //chiamo la funzione che inserisce ordinatamente gli elementi della lista;
        aggiungi(p->descr, p->info);
    return *this;
}


void ToDoList::fai(const char *descr) {
 //gestisco l'input:
if(descr == NULL || strlen(descr)>40) return;
elem*p;
for(p=testa;p!=NULL;p=p->pun){
    if( (strcmp(p->descr,descr) == 0) && (!p->fatto) ) {
        p->fatto = true;
    }
}

}
void ToDoList::cancella_fatti() {
    elem*p,*q;
    for (p=testa,q=p;p!=NULL;) {
        if (p->fatto) {
            if(p->info>=4)break;
            // elemento trovato, cancella
            if (p == testa)  // caso eliminazione in testa
                testa=testa->pun;
            else             // caso eliminazione in mezzo
                q->pun = p->pun;
                // deallocazione della memoria dinamica
                delete[]p->descr;
                delete p;
                p=q;
        }
        else {
            q = p;
            p = p->pun;
        }
    }
    }
Last edited on
Can't help you without more information. What's the problem? On which line? No one here can even run your code because we'd need to the class in your compito.h header file.
pretend that translating bits of code does not go well and that most of us have no idea what the comments or variable names etc mean. I think I got 30% of it but not enough to unravel what you want.
I'll describe you the code:
in the class we have public functions:
- function ToDoList to create a default costructor(the list is NULL);
-void fuction aggiungi which thread a string(it is the name of the exame) and you have to consider the int prio: if prio <1 return, else thread it according to prio, which indicates the increasing numeric order(from 1 to 4). All the exams are uncomplete;
- friend ostream& operator, which is used to definite the cout of the class(it writes a "V " chapter to say the exam is completed, number of priority, this character "-", string and end line.
-the distruttor of ToDoList;
-ToDolist& operator += which adds a list in the first list(tdl gets list of tdl 3)
-void fai to establish that a certain exam(with a certain name or string) is completed.
-void cancella_fatti, a fuction which deletes the exams which are completed.

In the class there is also a struct to create a list(attention: there is a bool fatto, which would be essential to establish if an exam is completed(true) or uncompleted(false).
The main() is beetween 1-69.
the header h is beetween 70-92.
the header cpp is beetween 93-182.

You can copy the code to write the header.

The problem is this: the file runs correctly, unless you don't consider tdl.cancella_fatti() in the last part of the main(): the file crusches in that point and I don't understand why.
Last edited on
the list contains information about the name of exams, priority and a state which represents the state of exams ,namely, if are completed or not.
So I am asking you what I have to do to edit the code, with the purpose to write correctly the names of the exams, with the correct state which I already spoke about.
Didn't run your code, but the glaring issue I see is that your indentation is misleading/wrong.
1
2
3
4
5
6
7
8
            if (p == testa)  // caso eliminazione in testa
                testa=testa->pun;
            else             // caso eliminazione in mezzo
                q->pun = p->pun;
                // deallocazione della memoria dinamica
                delete[]p->descr;
                delete p;
                p=q;

Lines 5, 6, 7, 8 are NOT part of your else statement.
Get in the habit of putting { } around your if/else blocks!
Last edited on
This is another bullshit plagiarism exercise with no merit.
> From 2018:
> https://www.iprogrammatori.it/forum-programmazione/cplusplus/costruttore-copia-t34966.html
«and now for something completely different»
there they ask for a problem regarding a copy-constructor (actually, assignment operator) and the internal representation is a dynamic array, not a linked list

@OP:
I recommend you to run your code through valgrind to detect memory leaks
also, use a debugger and go step-by-step in your `cancella_fatti()'
pay close attention to the first and second iterations (look your pointers and what you delete)
I’d go with Ganado’s advice: do improve your code readability.
You have at least one error in your cancella_fatti() function:
1
2
if (p == testa)  // caso eliminazione in testa
    testa=testa->pun;

You assign a new address to ‘testa’, but not to ‘q’, but later you update ‘p’ by the value of ‘q’:
 
p=q;

‘q’ here is still bound to the old address stored in ‘testa’.

The following version seems to work. I’ve added some comments from my point of view, preceeded by // //
(There could be many other issues: I’m not good at these tedious C-style exercises with raw pointers.)
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;
}

Output:
--- PRIMA PARTE ---
Test costruttore e funzione aggiungi
  1 - tdl_1.Task3
  2 - tdl_1.Task1
  2 - tdl_1.Task2
  2 - tdl_1.Task5
  3 - tdl_1.Task4

Test distruttore
Deleting list...
Deleting element -> info: 1; fatto: false; descr: tdl_2.Task1
Deleting element -> info: 2; fatto: false; descr: tdl_2.Task2
Distruttore chiamato
--- SECONDA PARTE ---
Test operatore +=
  1 - tdl_1.Task3
  1 - tdl_3.Task1
  2 - tdl_1.Task1
  2 - tdl_1.Task2
  2 - tdl_1.Task5
  2 - tdl_3.Task2
  3 - tdl_1.Task4
  3 - tdl_3.Task3
  4 - tdl_3.Task4

Test funzione fai
  1 - tdl_1.Task3
  1 - tdl_3.Task1
V 2 - tdl_1.Task1
V 2 - tdl_1.Task2
  2 - tdl_1.Task5
  2 - tdl_3.Task2
  3 - tdl_1.Task4
  3 - tdl_3.Task3
  4 - tdl_3.Task4

Test funzione cancella_fatti
Deleting element -> info: 2; fatto: true; descr: tdl_1.Task1
Deleting element -> info: 2; fatto: true; descr: tdl_1.Task2
  1 - tdl_1.Task3
  1 - tdl_3.Task1
  2 - tdl_1.Task5
  2 - tdl_3.Task2
  3 - tdl_1.Task4
  3 - tdl_3.Task3
  4 - tdl_3.Task4

--- TERZA PARTE ---
Test funzione aggiungi con input non validi
  1 - tdl_1.Task3
  1 - tdl_3.Task1
  2 - tdl_1.Task5
  2 - tdl_3.Task2
  3 - tdl_1.Task4
  3 - tdl_3.Task3
  4 - tdl_3.Task4

Test funzione fai con input non validi
  1 - tdl_1.Task3
  1 - tdl_3.Task1
  2 - tdl_1.Task5
  2 - tdl_3.Task2
  3 - tdl_1.Task4
  3 - tdl_3.Task3
  4 - tdl_3.Task4

Test funzione cancella_fatti con cancellazione in testa e in coda
Deleting element -> info: 1; fatto: true; descr: tdl_1.Task3
Deleting element -> info: 3; fatto: true; descr: tdl_1.Task4
  1 - tdl_3.Task1
  2 - tdl_1.Task5
  2 - tdl_3.Task2
  3 - tdl_3.Task3
  4 - tdl_3.Task4

Deleting list...
Deleting element -> info: 1; fatto: false; descr: tdl_3.Task1
Deleting element -> info: 2; fatto: false; descr: tdl_3.Task2
Deleting element -> info: 3; fatto: false; descr: tdl_3.Task3
Deleting list...
Deleting element -> info: 1; fatto: false; descr: tdl_3.Task1
Deleting element -> info: 2; fatto: false; descr: tdl_1.Task5
Deleting element -> info: 2; fatto: false; descr: tdl_3.Task2
Deleting element -> info: 3; fatto: false; descr: tdl_3.Task3

Oh, yes, looking at the output it’s clear there’s at least another error: the destructor doesn’t delete all the elements.
I leave it to you to solve it :-)
Topic archived. No new replies allowed.