[C] Funzione riceve array più corto
Ciao a tutti, mi servirebbe gentilmente una dritta riguardo a un semplice programmino di esercizio che ho trovato sul mio libro. Devo scrivere una funzione che calcoli il valore assunto da un polinomio di grado n per un determinato valore di x. I coefficienti del polinomio devono essere contenuti in un vettore, che viene passato alla funzione come argomento insieme a n e x. Coefficienti e x devono essere inseriti nel programma tramite linea di comando.
Per esempio, se io eseguo il mio programma (chiamato poly) in questo modo:
./poly 1 2 3 4
devo ottenere il valore di \(\displaystyle x^2 + 2x + 3 \), valutato per x=4.
DI seguito il codice.
Ho cercato di inserire brevi commenti per spiegare alcuni passaggi.
Il problema risiede nella chiamata alla funzione poly: non so per quale motivo, ma le viene passato sempre e solo un vettore di due elementi, anche se coeff[] ne contiene di più. Ho aggiunto due pezzetti di codice (che trovate commentati) che stampano il vettore coeff per come è inizializzato nel main e per come è ricevuto dalla funzione, per mostrare le differenze.
Di seguito tre esempi di esecuzione:
~/Documenti$ ./poly 1 2 3
1.00 ,2.00 ,
n=2
dim=2
1.00 ,2.00 ,
n=2
dim=2
il polinomio di grado 1 con i coefficienti inseriti vale 5.000.
______________________
~/Documenti$ ./poly 1 2 3 4
1.00 ,2.00 ,3.00 ,
n=3
dim=3
1.00 ,2.00 ,
n=3
dim=2
il polinomio di grado 2 con i coefficienti inseriti vale 10239811919020038.000.
_____________________________
~/Documenti$ ./poly 1 2 3 4 5
1.00 ,2.00 ,3.00 ,4.00 ,
n=4
dim=4
1.00 ,2.00 ,
n=4
dim=2
il polinomio di grado 3 con i coefficienti inseriti vale 7.061.
______________________________
Come vedete dai risultati restituiti dalla funzione, durante il calcolo accede senza dubbio a celle di memoria non previste, probabilmente perchè appunto il vettore su cui calcola il polinomio non è lungo quando dovrebbe.
Personalmente non so cosa pensare, che cosa sbaglio? è giusto il passaggio dei parametri alla funzione?
La cosa curiosa (per me) è che le due stampe vengono effettuate (dal main) appena prima di chiamare la funzione, e (dalla funzione) appena chiamata.. quindi l'array non viene modificato in nessun modo, il problema sta proprio nel passaggio alla funzione.
Per esempio, se io eseguo il mio programma (chiamato poly) in questo modo:
./poly 1 2 3 4
devo ottenere il valore di \(\displaystyle x^2 + 2x + 3 \), valutato per x=4.
DI seguito il codice.
#include <stdlib.h> #include <stdio.h> #include <math.h> double poly(const float *coeff, int n, double x) { int i; double sum=0; /* printf debug poly int dim = (sizeof(coeff))/(sizeof(*coeff)); for(i=0; i<dim; i++) printf("%.2f ,",coeff[i]); printf("\n n=%i\n dim=%i \n\n", n, dim); */ for (i=n; i>0; i--) sum = sum + (coeff[dim-i])*(pow(x,(i-1))); //sommo tutto tranne il termine noto sum = sum + (coeff[n+1]); //sommo il termine noto return sum; } int main(int argc, char *argv[]) { if (argc == 1) { printf("inserire almeno il coeff di grado 0!\n"); return 1; } if (argc == 2) //se riceve un solo parametro, lo considera termine noto (pol. di grado 0) { printf("il polinomio vale %.2f", atof(argv[1])); return 0; } int n = (argc-2); //n è il grado del polinomio +1. = argc -2 perchè tolgo argv[0] e la x (ultimo elemento di argv). float coeff[n]; //vettore dei coefficienti float x = atof(argv[n+1]); //valore per cui calcolare il polinomio int i; for (i=0; i<n; i++) // inizializzo il vettore con un ciclo for. A ogni ciclo setto un elemento coeff[i] = atof(argv[i+1]); /* printf debug main int dim = (sizeof(coeff))/(sizeof(*coeff)); for(i=0; i<dim; i++) printf("%.2f ,",coeff[i]); printf("\n n=%i \n dim=%i \n\n", n, dim); */ printf ("il polinomio di grado %i con i coefficienti inseriti vale %.3f.\n", (n-1), poly(coeff, n, x)); return 0; }
Ho cercato di inserire brevi commenti per spiegare alcuni passaggi.
Il problema risiede nella chiamata alla funzione poly: non so per quale motivo, ma le viene passato sempre e solo un vettore di due elementi, anche se coeff[] ne contiene di più. Ho aggiunto due pezzetti di codice (che trovate commentati) che stampano il vettore coeff per come è inizializzato nel main e per come è ricevuto dalla funzione, per mostrare le differenze.
Di seguito tre esempi di esecuzione:
~/Documenti$ ./poly 1 2 3
1.00 ,2.00 ,
n=2
dim=2
1.00 ,2.00 ,
n=2
dim=2
il polinomio di grado 1 con i coefficienti inseriti vale 5.000.
______________________
~/Documenti$ ./poly 1 2 3 4
1.00 ,2.00 ,3.00 ,
n=3
dim=3
1.00 ,2.00 ,
n=3
dim=2
il polinomio di grado 2 con i coefficienti inseriti vale 10239811919020038.000.
_____________________________
~/Documenti$ ./poly 1 2 3 4 5
1.00 ,2.00 ,3.00 ,4.00 ,
n=4
dim=4
1.00 ,2.00 ,
n=4
dim=2
il polinomio di grado 3 con i coefficienti inseriti vale 7.061.
______________________________
Come vedete dai risultati restituiti dalla funzione, durante il calcolo accede senza dubbio a celle di memoria non previste, probabilmente perchè appunto il vettore su cui calcola il polinomio non è lungo quando dovrebbe.
Personalmente non so cosa pensare, che cosa sbaglio? è giusto il passaggio dei parametri alla funzione?
La cosa curiosa (per me) è che le due stampe vengono effettuate (dal main) appena prima di chiamare la funzione, e (dalla funzione) appena chiamata.. quindi l'array non viene modificato in nessun modo, il problema sta proprio nel passaggio alla funzione.
Risposte
Sul mio computer il programma non compila nemmeno. Hai infatti dichiarato la variabile dim all'interno del commento.. Ma la variabile è comunque inizializzata in modo errato. Puoi usare sizeof solo con array dichiarati statici nel blocco in cui ti trovi (o uno più grande che lo contiene). Se passi un array come puntatore attraverso una funzione ogni informazione si perde. Nel tuo caso avrai probabilmente che sizeof(coeff) == sizeof(float*) == 8 e che sizeof(*coeff) == sizeof(float) == 4. Questa è la ragione per cui dim sarà sempre uguale a 2 nel tuo codice. La soluzione è quella di passare la dimensione dell'array come argomento. Ma lo stai già facendo.. Devi solo usare n nel codice al posto di dim.
Ciao, si hai ragione ho commentato i cicli di stampa per tenerli separati dal codice, direttamente qui sul forum, infatti dim non dovrebbe essere usato fuori.. comunque quei pezzi li ho aggiunti solo per rendermi conto di cosa stia accadendo (infatti si possono togliere).
Al di là di dim infatti, l'array passato alla funzione ha comunque due elementi, nonostante io gli dia n, inizializzata come argc-2..
Al di là di dim infatti, l'array passato alla funzione ha comunque due elementi, nonostante io gli dia n, inizializzata come argc-2..
La funzione dim è usata fuori dai commenti nella seguente riga:
Se usi n al posto di dim a me aveva funzionato quando l'ho testato prima.
sum = sum + (coeff[dim-i])*(pow(x,(i-1))); //sommo tutto tranne il termine noto
Se usi n al posto di dim a me aveva funzionato quando l'ho testato prima.
Effettivamente funziona se metto n (a patto di togliere l'istruzione che somma il termine noto, perchè n è il grado del polinomio +1). Strano pensavo di averci già provato.. grazie mille comunque, gentilissimo! ora è tutto chiaro