[C++] esercizio ok?

Messaggioda selfmademan » 04/06/2017, 19:03

Devo fare l'esame di informatica per ingegneria meccanica e sto cercando di risolvere alcuni esercizi.
"Siano dati in ingresso due vettori V1 e V2 di numeri interi. Si supponga che entrambi i vettori siano disordinati. Scrivere un programma (in C++) che identifichi la più lunga sequenza di elementi ordinati del vettore V1 (denominata S1) e la più lunga sequenza di elementi ordinati del vettore V2 (denominata S2). Si provveda poi a scambiare tali sequenze: la sequenza S1 trovata nel vettore V1 deve essere inserita nel vettore V2 al posto della sequenza S2 e viceversa. Stampare infine i vettori V1 e V2."
Io l'ho risolto così:
Codice:
#include <iostream>
using namespace std;
int main() {
    cout<<"Scegliere la dimensione del primo vettore:\n";
    int dim1;
    int dim2;
   cin>>dim1;
   cout<<"Scegliere la dimensione del secondo vettore:\n";
   cin>>dim2;
    int vett1[dim1];
    int vett2[dim2];
    int i;
    for (i=0;i<dim1;i++)
    {cout<<"Inserisci l'elemento numero "<<i+1<<" del primo vettore:\n";
    cin>>vett1[i];
    }
    for (i=0;i<dim2;i++)
    {cout<<"Inserisci l'elemento numero "<<i+1<<" del secondo vettore:\n";
    cin>>vett2[i];
    }
    cout<<"Il primo vettore è:\n";
    for(i=0;i<dim1;i++)
    {cout<<" "<<vett1[i];}
    cout<<"\nIl secondo vettore è:\n";
    for(i=0;i<dim2;i++)
    {cout<<" "<<vett2[i];}
    //introduco il vettore lunghezza1 e indpar1 in cui memorizzare le lunghezze e gli indici di partenza delle serie trovate
    int j1=-1; int lunghezza1[dim1]; int uno1=1; int k1=0; int indpar1[dim1];
    //azzero i vettori lunghezza1 e indpar1
    for(i=0;i<dim1;i++)
    {lunghezza1[i]=0;}
    for(i=0;i<dim1;i++)
    {indpar1[i]=0;}
    //memorizzazione di lunghezze e indici nelle componenti dei vettori
    for(i=1;i<dim1;i++)
    {
        if(vett1[i-1]<vett1[i])
        {j1++; lunghezza1[j1]=++uno1; indpar1[j1]=k1;}
        else
        {uno1=1; k1=i;}
    }
    //calcolo dell'elemento massimo e sua posizione
    int massimo1; int posmax1=0;
    massimo1=lunghezza1[0];
    for(i=1;i<dim1;i++)
    {
        if(massimo1<lunghezza1[i])
        {massimo1=lunghezza1[i]; posmax1=i;}
    }
    cout<<"\nLa sequenza crescente più lunga del primo vettore ha lunghezza "<<massimo1<<" e parte dalla posizione "<<indpar1[posmax1]+1;
    cout<<"\nEssa è:\n";
    for(i=indpar1[posmax1];i<indpar1[posmax1]+massimo1;i++)
    {cout<<" "<<vett1[i];}
    //Faccio la stessa cosa per il secondo vettore
int j2=-1; int lunghezza2[dim2]; int uno2=1; int k2=0; int indpar2[dim2];
    for(i=0;i<dim2;i++)
    {lunghezza2[i]=0;}
    for(i=0;i<dim2;i++)
    {indpar2[i]=0;}
    for(i=1;i<dim2;i++)
    {
        if(vett2[i-1]<vett2[i])
        {j2++; lunghezza2[j2]=++uno2; indpar2[j2]=k2;}
        else
        {uno2=1; k2=i;}
    }
    int massimo2; int posmax2=0;
    massimo2=lunghezza2[0];
    for(i=1;i<dim2;i++)
    {
        if(massimo2<lunghezza2[i])
        {massimo2=lunghezza2[i]; posmax2=i;}
    }
    cout<<"\nLa sequenza crescente più lunga del secondo vettore ha lunghezza "<<massimo2<<" e parte dalla posizione "<<indpar2[posmax2]+1;
    cout<<"\nEssa è:\n";
    for(i=indpar2[posmax2];i<indpar2[posmax2]+massimo2;i++)
    {cout<<" "<<vett2[i];}
    //scambio le sequenze ordinate e mostro i risultati
    cout<<"\nSostituendo la sequenza ordinata del primo vettore con quella del secondo, il primo vettore diventa:\n";
    for(i=0;i<indpar1[posmax1];i++)
    {cout<<" "<<vett1[i];}
    for(i=indpar2[posmax2];i<indpar2[posmax2]+massimo2;i++)
    {cout<<" "<<vett2[i];}
    for(i=indpar1[posmax1]+massimo1;i<dim1;i++)
    {cout<<" "<<vett1[i];}
    cout<<"\nSostituendo la sequenza ordinata del secondo vettore con quella del primo, il secondo vettore diventa:\n";
    for(i=0;i<indpar2[posmax2];i++)
    {cout<<" "<<vett2[i];}
    for(i=indpar1[posmax1];i<indpar1[posmax1]+massimo1;i++)
    {cout<<" "<<vett1[i];}
    for(i=indpar2[posmax2]+massimo2;i<dim2;i++)
    {cout<<" "<<vett2[i];}
}

Pare che funzioni, voi che dite? Grazie
Ultima modifica di selfmademan il 26/06/2017, 17:50, modificato 2 volte in totale.
selfmademan
Junior Member
Junior Member
 
Messaggio: 2 di 152
Iscritto il: 30/03/2017, 09:15

Re: [C++] esercizio ok?

Messaggioda apatriarca » 04/06/2017, 20:27

La colpa è certamente del tuo professore, ma il codice che hai scritto fa uso di estensioni disponibili in un particolare compilatore che non sono in generale portabili ad altri compilatori in quanto al di fuori dello standard. In effetti è possibile che il codice non compili neanche nei compilatori che supportano tale estensione a seconda della scelta degli argomenti passati al compilatore.

La dimensione di un array DEVE essere una costante a tempo di compilazione in base allo standard. Non può essere una variabile come nel tuo codice. Oltretutto non stai neanche verificando che i valori passati dall'utente abbiano senso. Cosa succede nel tuo codice se l'utente inserisce un valore negativo? Cosa succede se inserisce un valore molto grande?

Nel corso ti sono state insegnate le funzioni? Ci sono un sacco di ripetizioni nel tuo codice che andrebbero probabilmente estratte in funzioni.

Per il resto ad una occhiata veloce mi sembra corretto.
apatriarca
Moderatore
Moderatore
 
Messaggio: 4651 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C++] esercizio ok?

Messaggioda selfmademan » 04/06/2017, 20:48

Non ho seguito il corso, mi servo delle dispense del professore e di un libro di scuola superiore del 1993. Sono agli inizi, non ho mai progammato prima d'ora. Come IDE uso Netbeans.
Il controllo dell'input serve per impedire di invadere zone di memoria al di fuori di quella "prenotata" dal tipo int?
Le funzioni le uso per indicare blocchi di programma ricorrenti in modo da allegerire il codice e velocizzare il lavoro?
Non ho capito invece il discorso sulla dimensione variabile. Quali sarebbero le estensioni di cui parli?
Questo è un esercizio d'esame. Scrivendo il codice che ho postato secondo te sarei risultato sufficiente?
Grazie.
selfmademan
Junior Member
Junior Member
 
Messaggio: 3 di 152
Iscritto il: 30/03/2017, 09:15

Re: [C++] esercizio ok?

Messaggioda apatriarca » 05/06/2017, 12:10

Un libro di scuola superiore del 1993 è un reperto storico, non una fonte attendibile su cui studiare. Il primo standard del C++ è successivo a tale data (1997-1998) e il linguaggio è cambiato così tanto che anche un buon libro dei primi anni di questo secolo è molto datato. Quel libro ha quasi 25 anni e nel mondo dell'informatica è un'eternità. Oltretutto i libri di scuola superiore nascono necessariamente già vecchi.

Su Windows l'IDE standard, usato da praticamente ogni società che lavora su tale piattaforma, è Visual Studio. È gratuito per scopi non commerciali e nel caso di società di piccole dimensioni (sia come numero di programmatori che come fatturato). Il compilatore in tale IDE non compila il codice che hai scritto. Richiede infatti, come fa lo standard C++, che la dimensione di un array sia conosciuta in tempo di compilazione. Deve quindi essere un valore numerico o una espressione costante. NON può quindi in particolare essere una variabile letta da console. Ci sono buone ragioni per non permetterlo. La principale risiede nel fatto che non tutti i valori di una variabile intera (anche una senza segno) sono validi. E quelli che sono validi potrebbero dipendere dalla particolare implementazione scelta. Questa estensione dello standard non permette inoltre di gestire facilmente eventuali problemi, cosa possibile nelle alternative. Il controllare tali valori di ingresso ha lo scopo di evitare che valori senza senso (come -1) possano essere inseriti. Questo tipo di funzionalità ha un suo senso in alcune situazioni, ma non in questo. Il metodo corretto sarebbe quello di usare std::vector<int> o l'allocazione dinamica della memoria.

Che tu sia sufficiente o meno dipende dal tuo professore. Probabilmente sì, soprattutto se tali errori sono anche presenti nelle dispense del tuo professore (cosa abbastanza probabile*). Per essere un autodidatta, completamente nuovo alla programmazione, il tuo codice è decisamente buono. Hai chiaramente appreso la parte più difficile della programmazione, quella legata alla definizione di un algoritmo che risolve il problema dato. I problemi del codice sono legati piuttosto alle fonti che hai usato per apprendere il C++, che andrebbero cambiate e aggiornate.

* Sono anni che osservo e mi lamento della cattiva qualità dell'insegnamento del C e C++ ma continuo ad osservare gli stessi errori ripetuti e dispense datate di decenni che vengono ancora riproposte come corrette.
apatriarca
Moderatore
Moderatore
 
Messaggio: 4652 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C++] esercizio ok?

Messaggioda selfmademan » 05/06/2017, 21:30

Grazie apatriarca. Ci sono ancora cose che non mi sono chiare ma è inutile che faccio domande ora, mi metterò a studiare (la parte sui puntatori mi manca ad esempio) e mi farò vivo fra un pò.
selfmademan
Junior Member
Junior Member
 
Messaggio: 4 di 152
Iscritto il: 30/03/2017, 09:15

Re: [C++] esercizio ok?

Messaggioda Super Squirrel » 06/06/2017, 12:31

Ti consiglio anche io di usare le funzioni e di utilizzare gli array statici nel modo corretto.

Per quanto riguarda la forma ti consiglio di scrivere il codice in modo indentato e di inserire una sola istruzione per riga.

Dal punto di vista logico (ossia dell'algoritmo) secondo me c'è un ampio margine di miglioramento, nel senso che il problema può essere risolto scorrendo il vettore una sola volta e ricorrendo ad un minor numero di variabili. Per esempio io avrei pensato ad una cosa del genere:

Codice:
#include <iostream>

using namespace std;

void riempi_vettore(int* v, int dim)
{
    for(int i = 0; i < dim; i++)
    {
        cout << "ELEMENTO " << i + 1 << ": ";
        cin >> v[i];
    }
}

void trova_sequenza(int* v, int dim, int& ind, int& lun)
{
    int ind_, lun_;
    bool flag = true;
    for(int i = 0; i < dim - 1; i++)
    {
        if(flag)
        {
            ind_ = i;
            lun_ = 1;
            flag = false;
        }
        if(v[i] < v[i + 1])
        {
            ++lun_;
            if(i < dim - 2)
            {
                continue;
            }
        }
        if(lun_ > lun)
        {
            ind = ind_;
            lun = lun_;
        }
        flag = true;
    }
}

int main()
{
    int v1[100], dim1, ind1, lun1 = 1;
    cout << "DIMENSIONE VETTORE 1: ";
    cin >> dim1;
    riempi_vettore(v1, dim1);
    trova_sequenza(v1, dim1, ind1, lun1);
    if(lun1 > 1)
    {
        cout << "LA SEQUENZA CRESCENTE PIU' LUNGA E' COSTITUITA DA " << lun1 << " NUMERI E PARTE DALL'ELEMENTO " << ind1 + 1;
    }
    else
    {
        cout << "NON ESISTE UNA SEQUENZA CRESCENTE";
    }
}


Sembra funzionare, ma credo che anche questo algoritmo possa essere ulteriormente ottimizzato.

Inoltre stando al testo dell'esercizio credo che tu non debba solo mostrare quello che sarebbe il risultato a scambio avvenuto, ma modificare fisicamente i due vettori. Per farlo o utilizzi gli array statici fissando dei limiti per le dimensioni scelte in fase di esecuzione oppure utilizzi l'allocazione dinamica della memoria.

Infine se ti può essere utile ti consiglio il seguente corso di C++ che ritengo molto ben fatto:
http://www.bo.cnr.it/corsi-di-informatica/corsoCstandard/Lezioni/01Indice.html#virtual
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 124 di 1486
Iscritto il: 16/05/2013, 22:05

Re: [C++] esercizio ok?

Messaggioda apatriarca » 06/06/2017, 12:54

Si può anche fare qualcosa come segue (in cui ho introdotto una struttura per restituire i valori ma non ha granché importanza):
Codice:
struct Sequence {
  int start;
  int length;
};

Sequence find_sequence(int *v, int n)
{
  Sequence result = { 0, 0 };
  if (n <= 0) { return result;  }

  result.length = 1;
  int max_end = 1;
  for (int i = 1; i < n; ++i) {
    if (v[i-1] < v[i]) {
      ++max_end;
      if (max_end > result.length) {
        result.length = max_end;
        result.start = i-max_end+1;
      }
    }
  }

  return result;
}
apatriarca
Moderatore
Moderatore
 
Messaggio: 4655 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C++] esercizio ok?

Messaggioda selfmademan » 18/06/2017, 21:07

Grazie a entrambi. E' dal giorno del topic che non tocco informatica causa preparazione di altri esami, ma a breve mi ci rimetto e se avrò dubbi (come è probabile) mi faccio risentire.
selfmademan
Junior Member
Junior Member
 
Messaggio: 5 di 152
Iscritto il: 30/03/2017, 09:15

Re: [C++] esercizio ok?

Messaggioda selfmademan » 22/06/2017, 19:11

Non ho capito perchè netbeans non mi segnala alcun errore quando riservo un'area di memoria variabile a un vettore. Devo cambiare qualche impostazione? Se me l'avesse segnalato da subito non sarei andato avanti con questo concetto sbagliato. Grazie.
selfmademan
Junior Member
Junior Member
 
Messaggio: 6 di 152
Iscritto il: 30/03/2017, 09:15

Re: [C++] esercizio ok?

Messaggioda apatriarca » 22/06/2017, 19:29

Perché ogni compilatore implementa un certo numero di estensioni allo standard C++ che attiva di default. Quel codice è valido per il compilatore che usi. Il problema è che non lo è passando ad altri compilatori. Sinceramente non ho mai usato NetBeans e non saprei aiutarti nel settare l'opzione corretta.
apatriarca
Moderatore
Moderatore
 
Messaggio: 4688 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Prossimo

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite