View Full Version : Esercizio C++
morpheus89
18-08-2011, 13:45
Salve a tutti, mi sto esercitando con alcuni esercizi proposti da un libro per un esame di C++, dato che non ho trovato un thread ufficiale di questo linguaggio di programmazione vi chiedo qualche aiuto da qui.
Ho appena finito di leggere la teoria e sto cominciando a cimentarmi con un po' di esercizi.
In questo esercizio devo leggere un numero intero da tastiera e determinare se si tratta di un numero perfetto (http://it.wikipedia.org/wiki/Numero_perfetto). Questo è quello che sono riuscito a combinare fino ad ora
#include <iostream>
#include <math.h>
using namespace std;
bool perf (int a)
{
int i=1;
double p;
vero: return true;
while (i==a)
{
p = pow(2,i)*(pow(2,(i+1))-1);
if (p==a) goto vero; break;
i++;
}
}
int main ()
{
int n;
bool v;
cout << "Inserire un numero intero: ";
cin >> n;
v = perf(n);
if (v == true) cout << "Il numero " << n << " e' un numero perfetto!\n";
if (v == false) cout << "Il numero " << n << " NON e' un numero perfetto\n";
system ("pause");
return 0;
}
Ovviamente manca la parte in cui il programma avverte che la stringa digitata non è un numero (nel caso in cui si digitasse per sbaglio una lettera) e il return false nel caso non si riesca a trovare un valore 2^n · (2^(n+1) - 1) corrispondente.
Il programma restituisce come output "Il numero n e' un numero perfetto!" anche se questo non lo è.
Quali errori logici e di programmazione ho fatto?
Gimli[2BV!2B]
18-08-2011, 14:12
In primo luogo direi che il break nel ciclo while della funzione perf è nel posto sbagliato, oltre ad essere superfluo: in assenza di graffe non si trova nello scope dell'if, ma in quello del while, quindi interrompe incondizionatamente l'esecuzione al primo ciclo (se non si avvera l'if con relativo goto).
La sua necessità poi mi risulta nulla, visto che a causa del goto l'esecuzione si sposta definitivamente alla relativa flag, quindi anche se lo scope fosse definito non mi risulta che quel break possa esser mai eseguito.
Cosa ritorna la funzione perf se p non è mai uguale ad a?
La risposta non mi risulta esista, immagino sia un caso indefinito (ora non ho rintracciato un documento semi-ufficiale che lo contenga...).
In pratica credo che il valore sarà quello già presente nella zona di memoria dove il main va a cercare il risultato, quindi o vero o falso, potenzialmente anche in modo consistente a seconda dello stato dei registri della CPU in quel punto dell'esecuzione.
Solitamente errori di questo tipo possono essere segnalati dal compilatore come warning se è presente almeno un return, errori se non ce n'è nessuno.
Ultimo appunto: quel goto è veramente, veramente superfluo, come nel 99.99% dei casi in cui ti potrà venir in mente di usare un goto.
Concludendo: un bel return con valore statico alla fine ed un altro all'interno del while al posto del goto.
ESSE-EFFE
18-08-2011, 17:17
;35758618']
Cosa ritorna la funzione perf se p non è mai uguale ad a?
Non importa. La funzione perf ritorna sempre true visto che la terza riga è un bel "return true;". Nel while neanche ci entra e il compilatore sicuramente segnala qualche warning...
Gimli[2BV!2B]
18-08-2011, 17:36
Hai proprio ragione ESSE-EFFE, non ho notato questo trascurabile dettaglio! :D
Ok, lo ammetto, non ho mai usato un goto nella mia carriera di programmatore, ma ho trovato un paio di casi (il famoso 0.01% di cui sopra) in cui erano troppo geniali per non ammirarne la grazia.
morpheus89
18-08-2011, 20:28
Innanzitutto grazie per le risposte :)
Allora in effetti il goto l'ho utilizzato come ultima spiaggia a causa del fatto che il programma non funzionava correttamente. Dunque ho levato il break e ho risistemato un po' la funzione, introducendo una nuova variabile bool e inizializzandola come false, poi parte il ciclo che, se soddisfa la condizione a == p cambia la variabile in true, e infine un bel return w
bool perf (int a)
{
bool w = false;
int i=1;
double p;
while (i==a)
{
p = pow(2,i)*(pow(2,(i+1))-1);
if (p==a) w = true;
i++;
}
return w;
}
Questa volta però il programma dice sempre che il numero inserito NON è un numero perfetto, anche se inserisco numeri che lo sono come il 6 o il 28. In pratica è come se la funzione perf restituisse sempre false...
Gimli[2BV!2B]
18-08-2011, 21:28
Meglio, ora il primo problema è la condizione del while: se, per esempio, a = 6 ed i = 1, quante volte eseguirà il ciclo mentre i == a?
Indizi sulle condizioni da impostare:
Se p diventa maggiore di a potrà diminuire nuovamente, con i che si incrementa?
Se p == a è necessario continuare a cercare?
morpheus89
19-08-2011, 08:51
;35760982']Meglio, ora il primo problema è la condizione del while: se, per esempio, a = 6 ed i = 1, quante volte eseguirà il ciclo mentre i == a?
Indizi sulle condizioni da impostare:
Se p diventa maggiore di a potrà diminuire nuovamente, con i che si incrementa?
Se p == a è necessario continuare a cercare?
Ho impostato i==a poiché il ciclo deve in qualche modo interrompersi e poiché l'indice i nella formula è sempre minore del numero perfetto mi sembrava un'assegnazione lecita. Ad esempio per avere 6 i deve essere 1, per avere 28 i deve essere 2 e così via. Certo sarebbe bastato molto meno di i==a per ottenere il risultato, ma non so come impostare la cosa...
Se p==a non è necessario continuare perché il numero verifica la condizione, per cui il ciclo dovrebbe finire, Ecco perché avevo messo quel break
morpheus89
19-08-2011, 09:12
Ho fatto un altro esercizio analogo, dove mi chiede di trovare se il numero è primo (divisibile solo per 1 e per se stesso) e pare che funzioni :D
#include <iostream>
using namespace std;
bool primo (int p)
{
bool f=true;
for (int i=2; i<p; i++)
{
int q;
q = p%i;
if (q==0) f = false;
}
return f;
}
int main ()
{
int a;
bool g;
cout << "Scrivere un numero intero positivo: ";
cin >> a;
if (a<0 || a==0)
{
cerr << "Il numero deve essere intero positivo.\n";
return 0;
}
else
{
g = primo (a);
if (g==true) cout << "Il numero " << a << " e' un numero primo!\n";
if (g==false) cout << "Il numero " << a << " NON e' un numero primo\n";
}
system ("pause");
return 0;
}
Strano che invece l'altro non vada...
clockover
19-08-2011, 10:39
Strano che invece l'altro non vada...
te l'hanno già detto perchè non va l'altro esercizio
cambia
while(i == a)conwhile(i < a)
inoltre, sempre come già ti avevano consigliato, all'interno del ciclo c'è una condizione per cui è inutile andare avanti: quando p == a! Quando è così il resto delle iterazioni del ciclo sono inutili quindi puoi ritornare subito true. Quindi potresti cambiare con
while (i < a)
{
p = pow(2,i)*(pow(2,(i+1))-1);
if (p==a) return true;
i++;
}
ovviamente questo vale anche per il codice dei numeri primi
if (q==0) return false;
morpheus89
19-08-2011, 13:32
Ah ecco, non avevo capito il fatto del while :) ora è perfetto, grazie mille :D
ESSE-EFFE
19-08-2011, 14:52
ora è perfetto, grazie mille :D
Sei sicuro? Prova con 120...
morpheus89
19-08-2011, 22:26
Sei sicuro? Prova con 120...cavolo...perché? :confused:
Gimli[2BV!2B]
20-08-2011, 01:15
Occorre aggiungere una condizione.
Questa breve enunciazione del teorema di Euclide-Eulero evidenzia ciò che manca: ogni numero perfetto pari è della forma 2ⁿ⁻¹ * ( 2ⁿ - 1 ), ove il numero tra parentesi è un numero, detto di Mersenne, primo.
Quindi ti torna utile la funzione che testa numeri primi che hai postato...
P.S. non star lì a guardare gli esponenti, il tuo calcolo con i pow è corretto per quel test: prendi il pezzo della formula, pensa che variabile è per te l'n ed aggiungi un test prima di dichiarare vero il bool/ritornare true.
morpheus89
24-08-2011, 11:21
Ok perfetto, grazie mille :)
Oggi mi sto cimentando con gli array, in particolare devo realizzare un programma che immagazzini n elementi in un vettore e stabilisca se esso è maggioritario, ovvero se contiene almeno 1 elemento che appare nel vettore n/2 volte
#include <iostream>
using namespace std;
void leggi (int vett[], int n)
{
for (int i=0; i<n; i++)
{
cout << "Elemento " << (i+1) << " di " << n << " : ";
cin >> vett[i];
}
}
bool mag (int vett[], int n)
{
int m;
for (int i=0; i<n; i++)
{
for (int k=0; k<n; k++)
{
if (vett[i]==vett[k]) m++;
}
if ( m > (n/2) ) return true;
}
return false;
}
int main ()
{
int n;
bool v;
cout << "Di quanti elementi e' composto il vettore?: ";
cin >> n;
int a[n];
leggi (a,n);
v = mag (a,n);
if (v==true) cout << "Il vettore e' maggioritario!\n";
if (v==false) cout << "Il vettore NON e' maggioritario\n";
system ("pause");
return 0;
}
ovviamente non funziona, restituisce sempre true :fagiano:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.