[C++] Trovare il massimo tra n numeri
Salve,a scuola(al liceo) ho appena incominciato la programmazione in c++,ma la professoressa,vedendo che mi piaceva la materia,mi ha assegnato il compito,di trovare il massimo tra n numeri con una funzione(argomento non ancora trattato).Io ho provato a fare l'esercizio,ma l'algoritmo funziona solo se devo trovare il massimo tra n numeri con $n<=8$(se infatti inserisco più di 8 numeri,mi esce scritto:program received signal sigsegv segmentation fault) e onestamente non so il perchè.Se non vi reca disturbo,mi potreste spiegare dove sbaglio?
Ecco come ho provato a svolgere l'esercizio:
Ecco come ho provato a svolgere l'esercizio:
#include<iostream> using namespace std; float max(float a,float b) { float m; if(a>=b) { m=a; } else { m=b; } } int main() { int k; float l,s,a[k]; cout<<"Inserisci il numero di valori di cui si vuole il massimo"<<endl; cin>>k; for(int i=1;i<=k;i++){ cout<<"Inserisci un numero"<<endl; cin>>a[i]; } for(int i=1;i<=k;i++){ a[i]=max(a[i],a[i++]); } cout<<"Il valore massimo:"<<a[k]<<endl; system("PAUSE"); return 0; }
Risposte
Sono anni che non faccio c++ quindi la sintassi non me la ricordo completamente.
Comunque per prima cosa manca il valore di ritorno della funzione max(). Se dichiari una funziona 'float', il main si aspetta un valore float. Infatti fai bene a scrivere a=max(...) ma devi mettere nella funzione 'return m'.
Seconda cosa, gli indici dei vettori partono da 0 e arrivano a N-1. Per esempio: un vettore lungo 8 dovrà essere scandito come a[0] per il primo elemento, a[1] per il secondo, ..., a[7] per l'ultimo elemento.
Tu fai dei cicli for che scandiscono il vettore da 1 (secondo elemento) a k (elemento che non esiste, quindi sfori il vettore).
Poi c'è un problema se dichiari il a[k] ma chiedi la grandezza di k solo dopo che il vettore è stato creato.
Ti lascio il codice corretto, mi pare funzioni adesso:
Comunque per prima cosa manca il valore di ritorno della funzione max(). Se dichiari una funziona 'float', il main si aspetta un valore float. Infatti fai bene a scrivere a=max(...) ma devi mettere nella funzione 'return m'.
Seconda cosa, gli indici dei vettori partono da 0 e arrivano a N-1. Per esempio: un vettore lungo 8 dovrà essere scandito come a[0] per il primo elemento, a[1] per il secondo, ..., a[7] per l'ultimo elemento.
Tu fai dei cicli for che scandiscono il vettore da 1 (secondo elemento) a k (elemento che non esiste, quindi sfori il vettore).
Poi c'è un problema se dichiari il a[k] ma chiedi la grandezza di k solo dopo che il vettore è stato creato.
Ti lascio il codice corretto, mi pare funzioni adesso:
#include<iostream> using namespace std; float max(float a,float b) { float m; if(a>=b) { m=a; } else { m=b; } return m; } int main() { int k; cout<<"Inserisci il numero di valori di cui si vuole il massimo"<<endl; cin>>k; float a[k]; for(int i=0;i<k;i++){ cout<<"Inserisci un numero"<<endl; cin>>a[i]; } float massimo = a[1]; for(int i=1;i<k;i++){ massimo=max(massimo,a[i]); } cout<<"Il valore massimo:"<<massimo<<endl; system("PAUSE"); return 0; }
Grazie della risposta.
@iggy
Una curiosità da profano:
Nel codice di mklplo, quel "i++" all'interno di "a=max(a,a[i++]);" non è sbagliato?
Nel senso che mklplo vuole confrontare un valore con il successivo nella lista ma così facendo modifica effettivamente l'indice "i", sballando tutto ... no?
Cordialmente, Alex
Una curiosità da profano:
Nel codice di mklplo, quel "i++" all'interno di "a=max(a,a[i++]);" non è sbagliato?
Nel senso che mklplo vuole confrontare un valore con il successivo nella lista ma così facendo modifica effettivamente l'indice "i", sballando tutto ... no?
Cordialmente, Alex
"axpgn":
@iggy
Una curiosità da profano:
Nel codice di mklplo, quel "i++" all'interno di "a=max(a,a[i++]);" non è sbagliato?
Nel senso che mklplo vuole confrontare un valore con il successivo nella lista ma così facendo modifica effettivamente l'indice "i", sballando tutto ... no?
Cordialmente, Alex
Sì, è vero, sarebbe da utilizzare i[i+1] perchè i++ incrementa la variabile e questo lo fa già il ciclo for. Se si utilizzasse un ciclo while (dove la i andrebbe incrementata "a mano") avrebbe senso utilizzarlo.
Al di là di questo, la chiamata di funzione così come è scritta è sbagliata perché bisogna confrontare ogni elemento con il massimo fin'ora trovato e non confrontare coppie di elementi.
Questa pratica
sebbene supportata da molti compilatori, è scorretta secondo lo standard del linguaggio.
So che per l'OP è presto e questo è l'approccio "didatticamente meno peggio", però per conoscenza sappiate che per questo tipo di cose in C si scrivono le liste e in C++ si usa [inline]std::vector[/inline].
Il metodo 100% corretto di fare questa cosa in C senza complicarsi la vita è
"iggy":
int k; cout<<"Inserisci il numero di valori di cui si vuole il massimo"<<endl; cin>>k; float a[k];
sebbene supportata da molti compilatori, è scorretta secondo lo standard del linguaggio.
So che per l'OP è presto e questo è l'approccio "didatticamente meno peggio", però per conoscenza sappiate che per questo tipo di cose in C si scrivono le liste e in C++ si usa [inline]std::vector[/inline].
Il metodo 100% corretto di fare questa cosa in C senza complicarsi la vita è
int maxK = 10000; // O qualunque cosa float a[maxK]; int k; cout<<"Inserisci il numero di valori di cui si vuole il massimo"<<endl; cin>>k; if (k > maxK) { // errore }
"Raptorista":
Il metodo 100% corretto di fare questa cosa in C senza complicarsi la vita è
int maxK = 10000; // O qualunque cosa float a[maxK]; int k; cout<<"Inserisci il numero di valori di cui si vuole il massimo"<<endl; cin>>k; if (k > maxK) { // errore }
Volendo essere più precisi, secondo lo standard del linguaggio la dimensione di un array statico deve essere una costante.
Questa regola credo dipenda dal fatto che la dimensione di un array statico deve essere nota in fase di compilazione, e nel momento in cui la dimensione è una costante (utilizzando un numero, la direttiva define o lo specificatore const) essa sarà sicuramente nota. Giusto?
Invece se la dimensione fosse una variabile potrebbero esserci casi come il seguente in cui la dimensione sarebbe nota solo in fase di esecuzione:
int dim; cin >> dim; float v[dim];
Al di là dello standard come si comporta invece il compilatore nel seguente caso:
int dim = 100; float v[dim];
La dimensione sarà nota in fase di compilazione oppure il valore 100 sarà assegnato alla variabile dim solo in fase di esecuzione? E se invece di una dichiarazione con inizializzazione ci fosse stata una dichiarazione con successiva assegnazione?
Personalmente non penso che il modo di fare questo tipo di cose in C sia di usare le liste. Nello stesso modo in cui implementi una lista puoi implementare un array dinamico. Lo standard C possiede persino qualche strano oggetto come https://en.wikipedia.org/wiki/Flexible_array_member e i compilatori possono decidere di ammettere l'uso dei VLA (esiste una macro per controllarlo).
Detto questo, la possibilità di definire con variabili le dimensioni degli array risulta molto comodo quando si passano array multidimensionali a funzioni. E' importante comunque notare che cambiare la variabile non cambia la dimensione dell'array. La dimensione dell'array è definito dal valore della variabile nel momento in cui l'array è definito ed è compito del programmatore l'assicurare che la variabile continui a contenere la dimensione dell'array.
Detto questo, la possibilità di definire con variabili le dimensioni degli array risulta molto comodo quando si passano array multidimensionali a funzioni. E' importante comunque notare che cambiare la variabile non cambia la dimensione dell'array. La dimensione dell'array è definito dal valore della variabile nel momento in cui l'array è definito ed è compito del programmatore l'assicurare che la variabile continui a contenere la dimensione dell'array.
Grazie anche agli altri per le risposte,ma che vuol dire "std::vector"?Pechè poi devo imporre un valore massimo all'array?Ma gli array(che da quel che ho capito sono unidimensionali) sono vettori,giusto?Se così fosse significa che in c++ si possono definire anche delle matrici?
Scusate per le domande,ma stando veramente agli inizi,molte cose non le capisco ancora.
Scusate per le domande,ma stando veramente agli inizi,molte cose non le capisco ancora.
"Super Squirrel":
Volendo essere più precisi, secondo lo standard del linguaggio la dimensione di un array statico deve essere una costante.
Questa regola credo dipenda dal fatto che la dimensione di un array statico deve essere nota in fase di compilazione, e nel momento in cui la dimensione è una costante (utilizzando un numero, la direttiva define o lo specificatore const) essa sarà sicuramente nota. Giusto?
Giusto, quello che ho scritto è più uno pseudo-codice per far capire l'ordine delle cose. [inline]#define[/inline] è il modo usuale di definire costanti in C.
"Super Squirrel":
Invece se la dimensione fosse una variabile potrebbero esserci casi come il seguente in cui la dimensione sarebbe nota solo in fase di esecuzione:
int dim; cin >> dim; float v[dim];
Questo è quello che dicevamo sopra, infatti.
"Super Squirrel":
Al di là dello standard come si comporta invece il compilatore nel seguente caso:
int dim = 100; float v[dim];
La dimensione sarà nota in fase di compilazione oppure il valore 100 sarà assegnato alla variabile dim solo in fase di esecuzione? E se invece di una dichiarazione con inizializzazione ci fosse stata una dichiarazione con successiva assegnazione?
In questo caso il compilatore sa che [inline]dim[/inline] non sarà modificata e che avrà quel valore nel momento di inizializzare l'array.
"vict85":
Personalmente non penso che il modo di fare questo tipo di cose in C sia di usare le liste. Nello stesso modo in cui implementi una lista puoi implementare un array dinamico.
Per array dinamico intendi una cosa il cui spazio di allocazione cresce secondo necessità? Questo sarebbe l'equivalente di [inline]std::vector[/inline], ed è un altro possibile modo di fare. Concettualmente non c'è molta differenza.
"vict85":
Lo standard C possiede persino qualche strano oggetto come https://en.wikipedia.org/wiki/Flexible_array_member
Questo è così esotico che non ne avevo mai sentito parlare XD
"mklplo":
Grazie anche agli altri per le risposte,ma che vuol dire "std::vector"?
In C++ sono disponibili un gran numero di tipi di dato più sofisticati di quelli base del C. Siccome gli array/vettori/collezioni di numeri sono così comuni, il linguaggio fornisce un tipo di dato che li gestisce in maniera automatica. Questo tipo di dato si chiama [inline]std::vector[/inline]. Se stai ancora imparando, è meglio che ti faccia le ossa con array e implementazioni di basso livello per capire bene cosa succede.
"mklplo":
Pechè poi devo imporre un valore massimo all'array?
Perché il computer deve sapere in anticipo quanta ram mettere da parte per gli elementi di quell'array.
"mklplo":
Ma gli array(che da quel che ho capito sono unidimensionali) sono vettori,giusto?
Sì, array o vettore o lista sono la stessa cosa concettualmente: oggetti che collegano un numero [l'indice] ad un elemento.
"mklplo":
Se così fosse significa che in c++ si possono definire anche delle matrici?
Anche in C si possono definire array multidimensionali, cioè oggetti con più indici, che per esempio possono modellizzare matrici.
"mklplo":
Scusate per le domande,ma stando veramente agli inizi,molte cose non le capisco ancora.
No problem!
@Raptorista:Grazie nuovamente per le risposte.
Al contrario del C, il C++ fornisce all'utente un numero notevole di implementazioni "standard" di numerosi algoritmi e strutture dati. Non puoi dire di conoscere il C++ senza conoscere almeno i concetti basi su di loro. Per esempio in queste pagine puoi vedere le strutture dati (le stringhe sono in un'altra pagina) e gli algoritmi presenti nel C++. Questa libreria fa ampio uso dei templete, che è un concetto abbastanza avanzato del C++, ed è infatti chiamata STL (Standard Template Library). Un'altro concetto importante per capirli è il concetto di iteratore, ma sono concetti che vedrai più avanti.
Per farti un esempio, con l'uso delle STL, il tuo codice può essere riscritto come:
Per farti un esempio, con l'uso delle STL, il tuo codice può essere riscritto come:
#include <algorithm> // max_element #include <iostream> // cout, cin, endl #include <vector> // vector definitione e funzioni membro static inline size_t get_size( ) { int k; std::cout << "Inserisci il numero di valori di cui si vuole il massimo" << std::endl; std::cin >> k; if (k > 0) { return static_cast<size_t>(k); } std::cout << "L'elemento inserito non è valido" << std::endl; return get_size( ); } int main( ) { const size_t dim = get_size( ); std::vector<float> vec; vec.reserve(dim); for (size_t i = 0; i < dim; i++) { float t; std::cout << "Inserisci il valore dell'elemento " << i << std::endl; std::cin >> t; vec.push_back(t); } std::vector::const_iterator result = std::max_element(vec.begin( ), vec.end( )); std::cout << "Il valore massimo:" << *result << std::endl; }ovviamente scrivere un codice di questo tipo ti potrebbe insegnare la sintassi del C++ ma non ti aiuta minimamente ad imparare a ragionare sui problemi. D'altra parte, la presenza di queste funzioni è molto utile al programmatore esperto perché gli fa risparmiare tempo e riduce il rischio di errori di distrazione.
@vict85:grazie anche te per la risposta.