RISOLTO [C++] Il programma non mi da nessun errore ma si interrompe e non accetta comandi

Stato
Discussione chiusa ad ulteriori risposte.

Mr.Cobra

Nuovo Utente
66
1
Nel main ho creato un modulo di supporto con una funzione Copia che prende dal buffer input una stringa la ricopia in s1 e la inserisce in un oggetto Automobile o Moto dinamicamente però mi si blocca quando inserisco la marca. Gli altri punti del main sembrano funzionare ma non potendo inserire gli oggetti nel vettore non posso saperlo con certezza. Come mai succede questo? Mi date una mano?
Immagine.png
Vi metto sotto le parti principali del programma se vi serve altro ve lo posto.
Main.cpp
C++:
#include <iostream>
#include <cstdlib>
#include <fstream>

#include "Veicololib.h"
#include "Automobilelib.h"
#include "Motolib.h"
#include "Garagelib.h"
#include "Errorelib.h"
#include "Supportolib.h"

using namespace std;
using namespace Parcheggio;

int main(int argc, char** argv) {
    int opzione;
    Garage G;
    buffer b;
    do{
        system("cls");
        Stampa_Menu();
        cin>>opzione;
      
        switch(opzione){
            case(1):
                cout<<"\n Inserisci un Automobile o una Motocicletta [A/M] : ";
                char risp;
                cin>>risp;
                if(!G.Full()){
                    if(risp=='A'){
                        Str s1, s2;
                        cin.ignore();
                        cout<<"\n Inserisci la marca dell'Automobile: ";
                        Copia(b, s1);
                        cout<<"\n Inserisci l'alimentazione dell'Automobile: ";
                        Copia(b, s2);
                        try{
                            G.Immetti(new Automobile("Automobile", s1, s2));
                        }
                        catch(Errore e){
                            cout<<e.what()<<endl;
                        }
                    }else if(risp=='M'){
                        Str s1, s2;
                        cin.ignore();
                        cout<<"\n Inserisci la marca della Motocicletta: ";
                        Copia(b, s1);
                        cout<<"\n Inserisci il tipo di Motocilcetta: ";
                        Copia(b, s2);
                        try{
                            G.Immetti(new Moto("Motocicletta", s1, s2));
                        }
                        catch(Errore e){
                            cout<<e.what()<<endl;
                        }
                    }
                }else{
                    cout<<"\n Il Garage è pieno \n";
                }
            break;
          
            case(2):
                cin.ignore();
                cout<<"\n Inserisci la posizione del veicolo da estrarre: ";
                if(!G.Empty()){
                    int pos;
                    cin>>pos;
                    cin.ignore();
                    cout<<"\n Il veicolo estratto è :";
                    cout<<endl<<G.Estrai(pos)<<endl;
                    cout<<"\n il garage adesso è composto dai seguenti veicoli: ";
                    G.Stampa_Video();
                }else{
                    cout<<"\n Il garage è vuoto \n ";
                }
            break;
          
            case(3):
                cout<<"\n Lista dei veicoli presenti nel garage: ";
                if(!G.Empty()){
                    G.Stampa_Video();
                }else cout<<"\n Il garage è vuoto \n ";
                break;
          
            case(4):
                cin.ignore();
                cout<<"\n Inserisci il Percorso del file: ";
                cin.getline(b, DIM-1, '\n');
                try{
                    G.Stampa_File(b);
                }catch(const char *b){
                    cout<<b<<endl;
                }
                break;
              
        }
        system("pause");
    }while(opzione!=0);
    return 0;
}
Supportolib.h
C++:
#ifndef SUPPORTOLIB_H
#define SUPPORTOLIB_H

#include "Veicololib.h"

namespace Parcheggio{
  
    typedef char *Str;
    void Stampa_Menu();
    void Copia(char *, char *);
  
}
#endif
Supportofun.cpp
C++:
#include "Supportolib.h"

namespace Parcheggio{
  
    void Stampa_Menu(){
        cout<<"/***Benvenuti all'interno del garage**/\n\n";
        cout<<"[0] Uscita \n";
        cout<<"[1] Insersci un veicolo nel garage \n";
        cout<<"[2] Estrai un veicolo dal garage \n";
        cout<<"[3] Stampa a video la lista dei veicoli \n";
        cout<<"[4] Stampa su file la lista dei veicoli \n";
        cout<<"Premi il tasto per scegliere l'operazione da svolgere : ";
    }
  
    void Copia(char *buffer, char *s){
        cin.getline(buffer, DIM-1, '\n');
        delete [] s;
        s=new char [strlen(buffer)+1];
        strcpy(s, buffer);
        strcpy(buffer, "");
        cin.ignore();
    }
  
}
Errorelib.h
C++:
#ifndef ERRORELIB_H
#define ERRORELIB_H

#include <cstring>

using namespace std;
namespace Parcheggio{

    class Errore{
      
        private :
            char * error;
      
        public:
            Errore(char *E): error(E){};
            const char *what() const;
      
    };

}

#endif
Errorefun.cpp
C++:
#include "Errorelib.h"

namespace Parcheggio{

const char *Errore::what() const {
    char stringa[]= "\n Errore! Il veicolo inserito non è valido: ";
    char *msg= new char [strlen(error)+strlen(stringa)+1];
    strcat(msg,stringa);
    strcat(msg, stringa);
    return msg;
}

}
 
Ultima modifica da un moderatore:

Mr.Cobra

Nuovo Utente
66
1
cioè si blocca?

Inviato da SM-J530F tramite App ufficiale di Tom\'s Hardware Italia Forum
Si l'ho anche scritto, non va avanti e non so perchè.
Dovrebbe dopo "Inserisci la marca dell'Automobile: " far avviare la funzione Copia, che inserisce la stringa in input da cin nel buffer e copiare buffer nel s1, e poi stampare a video "Inserisci l'alimentazione dell'Automobile: " e riattivare la funzione Copia e infine creare un oggetto Automobile dinamicamente in cui da costruttore copia la stringa s1 e s2.
Ma si ferma a Inserisci l'alimentazione dell'Automobile: Ferrari.

Sai come posso fare? Idee?
 

_Achille

Utente Èlite
3,065
722
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
Sistema Operativo
Windows 10 Pro
Ecco cosa succede quando invece di utilizzare delle stringhe che la STL mette comodamente in servizio, vengono utilizzati i puntatori a char o array di char :cav:

Analizziamo bene un po di codice:
C++:
char *str = "Ciao";
Dichiaro il puntatore a caratteri str, inizializzato con l’indirizzo del primo carattere della stringa Ciao sullo stack.
Ora una funzione Copia
C++:
void Copia(char *s);

Copia(str);
Quel che passiamo non è l’indirizzo di str, ma l’indirizzo di 'C'. Ora roba tipo
C++:
delete[] s;
s = new char[10000];
Va a causare gravi problemi. Per prima cosa stiamo HeapFree (e parlo di HeapFree visto che è ben evidente la compilazione su Windows visto system(“cls”)) roba sullo stack (ma non è il tuo caso) e stiamo allocando memoria per un parametro di una funzione che, terminata, è perso. Di str rimane ciò che rimane dell'indirizzo di memoria di 'C' e nessuna memoria gli viene allocata

Perciò meglio iniziare a lasciare perdere i puntatori e iniziare ad utilizzare std::string oppure utilizzare ancora i puntatori, con i puntatori a puntatori e puntatori di puntatori a puntatori ecc... e magari pure mischiarli coi reference...
Oltre al fatto che l'intera funzione Copia è priva di senso visto che un buffer lo hai già, ed è STDIN
 
Ultima modifica:
  • Mi piace
Reactions: Mr.Cobra

Mr.Cobra

Nuovo Utente
66
1
Ecco cosa succede quando invece di utilizzare delle stringhe che la STL mette comodamente in servizio, vengono utilizzati i puntatori a char o array di char :cav:

Analizziamo bene un po di codice:
C++:
char *str = "Ciao";
Dichiaro il puntatore a caratteri str, inizializzato con l’indirizzo del primo carattere della stringa Ciao sullo stack.
Ora una funzione Copia
C++:
void Copia(char *s);

Copia(str);
Quel che passiamo non è l’indirizzo di str, ma l’indirizzo di 'C'. Ora roba tipo
C++:
delete[] s;
s = new char[10000];
Va a causare gravi problemi. Per prima cosa stiamo HeapFree (e parlo di HeapFree visto che è ben evidente la compilazione su Windows visto system(“cls”)) roba sullo stack (ma non è il tuo caso) e stiamo allocando memoria per un parametro di una funzione che, terminata, è perso. Di str rimane ciò che rimane dell'indirizzo di memoria di 'C' e nessuna memoria gli viene allocata

Perciò meglio iniziare a lasciare perdere i puntatori e iniziare ad utilizzare std::string oppure utilizzare ancora i puntatori, con i puntatori a puntatori e puntatori di puntatori a puntatori ecc... e magari pure mischiarli coi reference...
Oltre al fatto che l'intera funzione Copia è priva di senso visto che un buffer lo hai già, ed è STDIN
Achille sfondi una porta aperta sulle string io le userei sempre! Ma non ce le fa usare le string all'esame, non potrò usarle purtroppo... Quindi come posso fare a rendere il mio programma "meno problematico" possibile?
P.S.
Sul mio libro non c'è molto mi potresti passare qualche link su le varie funzioni della libreria string così me le leggo per conto mio?
 

_Achille

Utente Èlite
3,065
722
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
Sistema Operativo
Windows 10 Pro
Achille sfondi una porta aperta sulle string io le userei sempre! Ma non ce le fa usare le string all'esame, non potrò usarle purtroppo... Quindi come posso fare a rendere il mio programma "meno problematico" possibile?
Ahhhhh ahia ahia.
Allora devi ricordarti che una funzione che deve operare su un parametro ha un * in più rispetto al tipo della variabile su cui deve lavorare.
Quindi se devi lavorare su una char * il parametro è char ** oppure char *& (se ti è permesso usare i reference).

Ecco qui https://it.cppreference.com/w/cpp/string/basic_string + le nuove string_view https://en.cppreference.com/w/cpp/string/basic_string_view
 
  • Mi piace
Reactions: Mr.Cobra

Mr.Cobra

Nuovo Utente
66
1
Ahhhhh ahia ahia.
Allora devi ricordarti che una funzione che deve operare su un parametro ha un * in più rispetto al tipo della variabile su cui deve lavorare.
Quindi se devi lavorare su una char * il parametro è char ** oppure char *& (se ti è permesso usare i reference).

Ecco qui https://it.cppreference.com/w/cpp/string/basic_string + le nuove string_view https://en.cppreference.com/w/cpp/string/basic_string_view
Grazie per i link Achille si posso usare il reference quindi il main devo farlo così vedi se ti trovi su Copia:
C++:
#include <iostream>
#include <cstdlib>
#include <fstream>

#include "Veicololib.h"
#include "Automobilelib.h"
#include "Motolib.h"
#include "Garagelib.h"
#include "Errorelib.h"
#include "Supportolib.h"

using namespace std;
using namespace Parcheggio;

int main(int argc, char** argv) {
    int opzione;
    Garage G;
    buffer b;
    do{
        system("cls");
        Stampa_Menu();
        cin>>opzione;
      
        switch(opzione){
            case(1):
                cout<<"\n Inserisci un Automobile o una Motocicletta [A/M] : ";
                char risp;
                cin>>risp;
                if(!G.Full()){
                    if(risp=='A'){
                        Str s1, s2;
                        cin.ignore();
                        cout<<"\n Inserisci la marca dell'Automobile: ";
                        Copia(b, &s1); //qui metto per reference giusto?
                        cout<<"\n Inserisci l'alimentazione dell'Automobile: ";
                        Copia(b, &s2); //qui metto per reference giusto?
                        try{
                            G.Immetti(new Automobile("Automobile", s1, s2));
                        }
                        catch(Errore e){
                            cout<<e.what()<<endl;
                        }
                    }else if(risp=='M'){
                        Str s1, s2;
                        cin.ignore();
                        cout<<"\n Inserisci la marca della Motocicletta: ";
                        Copia(b, &s1); //qui metto per reference giusto?
                        cout<<"\n Inserisci il tipo di Motocilcetta: ";
                        Copia(b, &s2); //qui metto per reference giusto?
                        try{
                            G.Immetti(new Moto("Motocicletta", s1, s2));
                        }
                        catch(Errore e){
                            cout<<e.what()<<endl;
                        }
                    }
                }else{
                    cout<<"\n Il Garage è pieno \n";
                }
            break;
...
}
Post automaticamente unito:

Nemmeno i template mi fa usare, li devo assolutamente studiare ho visto dei programmi escono facilissimi.
Post automaticamente unito:

Poi la funzione Copia rimane invariata giusto?

C++:
#ifndef SUPPORTOLIB_H
#define SUPPORTOLIB_H

#include "Veicololib.h"

namespace Parcheggio{
 
    typedef char *Str;
    void Stampa_Menu();
    void Copia(char *, char *);
 
}
#endif
Supportofun.cpp
C++:
#include "Supportolib.h"

namespace Parcheggio{
 
    ....
 
    void Copia(char *buffer, char *s){
        cin.getline(buffer, DIM-1, '\n');
        delete [] s;
        s=new char [strlen(buffer)+1];
        strcpy(s, buffer);
        strcpy(buffer, "");
        cin.ignore();
    }
 

_Achille

Utente Èlite
3,065
722
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
Sistema Operativo
Windows 10 Pro
No, non può rimanere invariata per motivi che ti ho detto sopra. E va pure controllato che tu possa effettivamente liberare l’heap da s. Perciò dovresti controllare che esse non sia nullptr e una volta liberata andrebbe messa appunto a nullptr. Perciò pure le due str vanno inizializzate a nullptr
 
  • Mi piace
Reactions: Mr.Cobra

Mr.Cobra

Nuovo Utente
66
1
No, non può rimanere invariata per motivi che ti ho detto sopra. E va pure controllato che tu possa effettivamente liberare l’heap da s. Perciò dovresti controllare che esse non sia nullptr e una volta liberata andrebbe messa appunto a nullptr. Perciò pure le due str vanno inizializzate a nullptr
Non ho capito bene come dovrei dichiarare Copia puoi farmi vedere come faresti? Così per caso? E nel main la lascio uguale?

C++:
#ifndef SUPPORTOLIB_H
#define SUPPORTOLIB_H

#include "Veicololib.h"

namespace Parcheggio{
    typedef char *Str;
    void Stampa_Menu();
    void Copia(char *, char **);
}

#endif
Supportofun.cpp

C++:
#include "Supportolib.h"
namespace Parcheggio{
    ....
    void Copia(char *buffer, char **s){
        cin.getline(buffer, DIM-1, '\n');
        delete [] s;
        s=new char [strlen(buffer)+1];
        strcpy(s, buffer);
        strcpy(buffer, "");
        cin.ignore();

    }
Al posto di nullptr nel main posso fare così?
C++:
 Str s1=""; Str s2="";
Concatenati in una dichiarazione non glie l'ho mai visto fare tipo char *& quindi non so se lo posso usare
Post automaticamente unito:

Comunque grazie Achille di tutti se sei sempre disponibile, comunque hai ragione su tutto, infatti se tolgo da mezzo la funzione copia funziona, ma come posso usare la funzione Copia?
C++:
#include <iostream>
#include <cstdlib>
#include <fstream>

#include "Veicololib.h"
#include "Automobilelib.h"
#include "Motolib.h"
#include "Garagelib.h"
#include "Errorelib.h"
#include "Supportolib.h"

using namespace std;
using namespace Parcheggio;


int main(int argc, char** argv) {
    int opzione;
    Garage G;
    buffer b;
    do{
        system("cls");
        Stampa_Menu();
        cin>>opzione;
        
        switch(opzione){
        
            case(1):
                cout<<"\n Inserisci un Automobile o una Motocicletta [A/M] : ";
                char risp;
                cin>>risp;
                if(!G.Full()){
                    if(risp=='A'){
                        Str s1="";
                        Str s2="";
                        cin.ignore();
                        cout<<"\n Inserisci la marca dell'Automobile: ";
                        cin.getline(b, DIM-1, '\n');
                        s1=new char [strlen(b)+1];   
                        strcpy(s1, b);   
                        strcpy(b, "");
                        cin.ignore();
                        cout<<"\n Inserisci l'alimentazione dell'Automobile: ";
                        cin.getline(b, DIM-1, '\n');
                        s2=new char [strlen(b)+1];
                        strcpy(s2, b);
                        strcpy(b, "");
                        cin.ignore();
                        try{
                            G.Immetti(new Automobile("Automobile", s1, s2));
                        }
                        catch(Errore e){
                            cout<<e.what()<<endl;
                        }
                    }else if(risp=='M'){
                        Str s1, s2;
                        cin.ignore();
                        cout<<"\n Inserisci la marca della Motocicletta: ";
                        cin.getline(b, DIM-1, '\n');
                        s1=new char [strlen(b)+1];   
                        strcpy(s1, b);   
                        strcpy(b, "");
                        cin.ignore();
                        cout<<"\n Inserisci il tipo di Motocilcetta: ";
                        cin.getline(b, DIM-1, '\n');
                        s2=new char [strlen(b)+1];
                        strcpy(s2, b);
                        strcpy(b, "");
                        cin.ignore();
                        try{
                            G.Immetti(new Moto("Motocicletta", s1, s2));
                        }
                        catch(Errore e){
                            cout<<e.what()<<endl;
                        }
                    }
                }else{
                    cout<<"\n Il Garage è pieno \n";
                }
            break;
....
Infatti mi va ma non riesco a capire perchè dopo 2 invii mi fa inserire l'alimentazione sai perchè?
Immagine 2.png
 
Ultima modifica:

_Achille

Utente Èlite
3,065
722
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
Sistema Operativo
Windows 10 Pro
Intato togli tutti i cin.ignore() che sono inutili.

Se vuoi utilizzare la funzione Copia questa deve controllare che effettivamente la stringa sia alloccata dinamicamente.
Quindi:
C++:
void Copia(char* &s) //o char **s
{
    if(s != nullptr)
        delete[] s; //o delete[] *s;
    s = new char[100]; //o *s = ...
}
Nel main le stringhe vanno inizializzate a nullptr altrimenti subiscono l’HeapFree.
 

BrutPitt

Utente Attivo
299
300
Ciao.

La dichiarazione:
Codice:
char *s1=nullptr;
char *s2="";
Non e' equivalente.
Alla prima si assegna un valore nullptr == 0 all'indirizzo s1.
Nella seconda invece: prima si alloca la stringa "" , al cui UNICO carattere '\0' == 0 il compilatore assegna comunque una locazione di memoria nella quale inserisce quell'unico carattere, ed infine, l'indirizzo di '\0' (del primo e unico carattere della stringa) viene assegnato a s2, ed e' un indirizzo != 0 ossia != nullptr.

Ed oltretutto le stringhe allocate staticamente char *s2=""; (che equivale a const char *s = "pincopallino";) non "dovrebbero" (!) essere reallocate/deallocate:
Se avessi avuto tutti i warnings attivi nel compilatore, avresti avuto un messaggio di questo tipo
--- warning: ISO C++ forbids converting a string constant to ‘char*’
che ti avvsiava che quella dichiarazione avrebbe dovuto essere una "const char *".

Intato togli tutti i cin.ignore() che sono inutili.
Non e' proprio vero che sia completamente inutili... servirebbe ad ignorare una eventuale newline rimasta nel buffer... e a garantire di non dover ricominciare tutta la fase di input da capo, nel caso, per esempio, ci fosse un doppio 'newline' nelle varie sequenze di input.

C++:
    if(s != nullptr)
        delete[] s; //o delete[] *s;
Questo invece e' inutile if(s != nullptr) prima del delete
Non e' un errore, e' solo un codice ridondante.
In un programma non succede assolutamente nulla, ma in sede di esame sicuramente toglierei qualche punto in quanto non si e' fatta attenzione al paragrafo relativo ;-) e al fatto che delete non fa alcuna operazione in caso di nullptr... insomma quel codice e' gia' interno all'operatore delete.

Secondo me state complicando un po' le cose...
Non servono riverimenti a puntatori o puntatori a putatori, basterebbero solo dei buffers ben allocati...

Nella funzione Copia:
buffer
(che fa riferimento al parametro 'b' dichiarato come buffer b; ), che tipo di dato e' (immagino typedef char* buffer;) e dove e' allocato?
E perche' poi gli copi una stringa vuota ( strcpy(buffer, ""); ) ?
Che tra l'altro equvarrebbe a scrivere buffer[0]='\0'; ... e' un altro NON errore, ma cosi' il professore capisce che non ti e' ben chiaro il meccanismo delle stringhe.
 
Ultima modifica:
  • Mi piace
Reactions: Mr.Cobra

_Achille

Utente Èlite
3,065
722
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
Sistema Operativo
Windows 10 Pro
Ciao.

La dichiarazione:
Codice:
char *s1=nullptr;
char *s2="";
Non e' equivalente.
Alla prima si assegna un valore nullptr == 0 all'indirizzo s1.
Nella seconda invece: prima si alloca la stringa "" , al cui UNICO carattere '\0' == 0 il compilatore assegna comunque una locazione di memoria nella quale inserisce quell'unico carattere, ed infine, l'indirizzo di '\0' (del primo e unico carattere della stringa) viene assegnato a s2, ed e' un indirizzo != 0 ossia != nullptr.

Ed oltretutto le stringhe allocate staticamente char *s2=""; (che equivale a const char *s = "pincopallino";) non "dovrebbero" (!) essere reallocate/deallocate:
Se avessi avuto tutti i warnings attivi nel compilatore, avresti avuto un messaggio di questo tipo
--- warning: ISO C++ forbids converting a string constant to ‘char*’
che ti avvsiava che quella dichiarazione avrebbe dovuto essere una "const char *".


Non e' proprio vero che sia completamente inutili... servirebbe ad ignorare una eventuale newline rimasta nel buffer... e a garantire di non dover ricominciare tutta la fase di input da capo, nel caso, per esempio, ci fosse un doppio 'newline' nelle varie sequenze di input.



Questo invece e' inutile if(s != nullptr) prima del delete
Non e' un errore, e' solo un codice ridondante.
In un programma non succede assolutamente nulla, ma in sede di esame sicuramente toglierei qualche punto in quanto non si e' fatta attenzione al paragrafo relativo ;-) e al fatto che delete non fa alcuna operazione in caso di nullptr... insomma quel codice e' gia' interno all'operatore delete.

Secondo me state complicando un po' le cose...
Non servono riverimenti a puntatori o puntatori a putatori, basterebbero solo dei buffers ben allocati...

Nella funzione Copia:
buffer
(che fa riferimento al parametro 'b' dichiarato come buffer b; ), che tipo di dato e' (immagino typedef char* buffer;) e dove e' allocato?
E perche' poi gli copi una stringa vuota ( strcpy(buffer, ""); ) ?
Che tra l'altro equvarrebbe a scrivere buffer[0]='\0'; ... e' un altro NON errore, ma cosi' il professore capisce che non ti e' ben chiaro il meccanismo delle stringhe.
Sisi, so che delete e delete[] non fanno nulla in caso di nullptr, era solo per introdurgli il fatto che deve inizializzare le stringhe a NULL.

Inoltre in una funzione che opera direttamente su una variabile richiede un puntatore o un reference, e visto che parliamo di char * i corrispettivi tipi sono char ** e char* &, che sono proprio puntatore a puntatore e reference di puntatore...

E i cin.ignore() vanno tolti perché appunto richiedono la pressione del tasto ENTER due volte, cosa da lui non gradita.
 

Mr.Cobra

Nuovo Utente
66
1
Ciao.

La dichiarazione:
Codice:
char *s1=nullptr;
char *s2="";
Non e' equivalente.
Alla prima si assegna un valore nullptr == 0 all'indirizzo s1.
Nella seconda invece: prima si alloca la stringa "" , al cui UNICO carattere '\0' == 0 il compilatore assegna comunque una locazione di memoria nella quale inserisce quell'unico carattere, ed infine, l'indirizzo di '\0' (del primo e unico carattere della stringa) viene assegnato a s2, ed e' un indirizzo != 0 ossia != nullptr.

Ed oltretutto le stringhe allocate staticamente char *s2=""; (che equivale a const char *s = "pincopallino";) non "dovrebbero" (!) essere reallocate/deallocate:
Se avessi avuto tutti i warnings attivi nel compilatore, avresti avuto un messaggio di questo tipo
--- warning: ISO C++ forbids converting a string constant to ‘char*’
che ti avvsiava che quella dichiarazione avrebbe dovuto essere una "const char *".


Non e' proprio vero che sia completamente inutili... servirebbe ad ignorare una eventuale newline rimasta nel buffer... e a garantire di non dover ricominciare tutta la fase di input da capo, nel caso, per esempio, ci fosse un doppio 'newline' nelle varie sequenze di input.



Questo invece e' inutile if(s != nullptr) prima del delete
Non e' un errore, e' solo un codice ridondante.
In un programma non succede assolutamente nulla, ma in sede di esame sicuramente toglierei qualche punto in quanto non si e' fatta attenzione al paragrafo relativo ;-) e al fatto che delete non fa alcuna operazione in caso di nullptr... insomma quel codice e' gia' interno all'operatore delete.

Secondo me state complicando un po' le cose...
Non servono riverimenti a puntatori o puntatori a putatori, basterebbero solo dei buffers ben allocati...

Nella funzione Copia:
buffer
(che fa riferimento al parametro 'b' dichiarato come buffer b; ), che tipo di dato e' (immagino typedef char* buffer;) e dove e' allocato?
E perche' poi gli copi una stringa vuota ( strcpy(buffer, ""); ) ?
Che tra l'altro equvarrebbe a scrivere buffer[0]='\0'; ... e' un altro NON errore, ma cosi' il professore capisce che non ti e' ben chiaro il meccanismo delle stringhe.
Ho capito grazie pre la spiegazione Bruttpitt :ok:
Ora ricapitolando ciò che devo fare è:
nel buffer cheho allocata nella classe base Veicolo che richiamo nella libreria supportolib.h, quindi devo allocarla a nullptr?
E inizializzo s1 e s2 nel main a nullptr?
Per quanto riguarda Copia la lascio come l'originale non uso nessun puntatore a reference?
E poi mi rileggo puntatori e allocazione dinamica :D

Veicololib.h

C++:
#ifndef VEICOLOLIB_H
#define VEICOLOLIB_H

#include <iomanip>
#include <cstring>
#include <iostream>
#include <cstdlib>

#define DIM 100

using namespace std;

namespace Parcheggio{

    typedef char buffer [DIM]=nullptr; //posso farlo?

    class Veicolo{
   
      ......
       
    };  
   
}
#endif
main.cpp

C++:
#include <iostream>
#include <cstdlib>
#include <fstream>

#include "Veicololib.h"
#include "Automobilelib.h"
#include "Motolib.h"
#include "Garagelib.h"
#include "Errorelib.h"
#include "Supportolib.h"

using namespace std;
using namespace Parcheggio;


int main(int argc, char** argv) {
    int opzione;
    Garage G;
    buffer b;
    do{
        system("cls");
        Stampa_Menu();
        cin>>opzione;
       
        switch(opzione){
       
            case(1):
                cout<<"\n Inserisci un Automobile o una Motocicletta [A/M] : ";
                char risp;
                cin>>risp;
                if(!G.Full()){
                    if(risp=='A'){
                        Str s1=nullptr;
                        Str s2=nullptr;
                        cin.ignore();
                        cout<<"\n Inserisci la marca dell'Automobile: ";
                        cin.getline(b, DIM-1, '\n');
                        s1=new char [strlen(b)+1];  
                        strcpy(s1, b);  
                        strcpy(b, "");
                        cin.ignore();
                        cout<<"\n Inserisci l'alimentazione dell'Automobile: ";
                        cin.getline(b, DIM-1, '\n');
                        s2=new char [strlen(b)+1];
                        strcpy(s2, b);
                        strcpy(b, "");
                        cin.ignore();
                        try{
                            G.Immetti(new Automobile("Automobile", s1, s2));
                        }
                        catch(Errore e){
                            cout<<e.what()<<endl;
                        }
                    }else if(risp=='M'){
                        Str s3=nullptr;
                        Str s4=nullptr
                        cin.ignore();
                        cout<<"\n Inserisci la marca della Motocicletta: ";
                        cin.getline(b, DIM-1, '\n');
                        s1=new char [strlen(b)+1];  
                        strcpy(s3, b);  
                        strcpy(b, "");
                        cin.ignore();
                        cout<<"\n Inserisci il tipo di Motocilcetta: ";
                        cin.getline(b, DIM-1, '\n');
                        s2=new char [strlen(b)+1];
                        strcpy(s4, b);
                        strcpy(b, "");
                        cin.ignore();
                        try{
                            G.Immetti(new Moto("Motocicletta", s1, s2));
                        }
                        catch(Errore e){
                            cout<<e.what()<<endl;
                        }
                    }
                }else{
                    cout<<"\n Il Garage è pieno \n";
                }
            break;
....
Supportolib.h

C++:
#include "Supportolib.h"
namespace Parcheggio{
    ....
    void Copia(char *buffer, char *s){
        cin.getline(buffer, DIM-1, '\n');
        delete [] s;
        s=new char [strlen(buffer)+1];
        strcpy(s, buffer);
           buffer[]=nullptr;
        cin.ignore();

    }
Se avete consigli su cosa ripetermi o consigli su cosa leggermi mi fate un piacere
 

_Achille

Utente Èlite
3,065
722
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
Sistema Operativo
Windows 10 Pro
Veicololib.h

C++:
#ifndef VEICOLOLIB_H
#define VEICOLOLIB_H

#include <iomanip>
#include <cstring>
#include <iostream>
#include <cstdlib>

#define DIM 100

using namespace std;

namespace Parcheggio{

    typedef char buffer [DIM]=nullptr; //posso farlo?

    class Veicolo{
 
      ......
     
    };
 
}
#endif
Assolutamente no. Un vettore è un puntatore costante e non puoi dargli alcun indirizzo tu. Oltre al fatto che non ha senso una typedef simile.

Per quanto Copia, ripeto, devi utilizzare puntatore a puntatore o reference di puntatore. La vedo ben ardua modificare il contenuto di una variabile puntatore senza un puntatore a puntatore...
 
  • Mi piace
Reactions: Mr.Cobra

Mr.Cobra

Nuovo Utente
66
1
Assolutamente no. Un vettore è un puntatore costante e non puoi dargli alcun indirizzo tu. Oltre al fatto che non ha senso una typedef simile.

Per quanto Copia, ripeto, devi utilizzare puntatore a puntatore o reference di puntatore. La vedo ben ardua modificare il contenuto di una variabile puntatore senza un puntatore a puntatore...
Infatti Achille volevo farmi correggere perché non ho capito molto come fare, come lo devo inizializzare buffer?Forse Bruttpitt ha una soluzione migliore aspetto la sua risposta, se mi scrive solo quelle parte di codice così capisco cosa non devo sbagliare nei prossimi programmi mi farebbe un grosso piacere
 
Ultima modifica:

_Achille

Utente Èlite
3,065
722
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
Sistema Operativo
Windows 10 Pro
Infatti Achille volevo farmi correggere perché non ho capito molto come fare, come lo devo inizializzare buffer? Vabbè forse Bruttpitt ha una soluzione migliore aspetto la sua risposta, se mi scrive solo quelle parte di codice così capisco cosa non devo sbagliare nei prossimi programmi mi farebbe un grosso piacere
Bruttpitt ti diceva giustamente che stavi copiando dati nel buffer, che è una stringa che non avevi allocato.
Ti basta dichiarare buffer come char [DIM] ed averlo quindi allocato sullo stack. Poi la funzione Copia prende l’indirizzo della memoria che punta buffer e l’indirizzo di una stringa per poterla allocare.

Ci sono alternative, come allocare direttamente le stringhe nel main e fregarsene se del spazio non viene sfruttato. Questa evita l’uso di puntatore a puntatore.

Il codice puoi scrivertelo da solo, ora che sai semplicemente che devi cambiare il tipo dell’argomento da char * a char* &
 
Ultima modifica:
  • Mi piace
Reactions: Mr.Cobra
Stato
Discussione chiusa ad ulteriori risposte.

Entra

oppure Accedi utilizzando

Discussioni Simili