[C] Domanda su funzioni

bad.alex
Ragazzi, altro esercizio, altre ( o stesse?) difficoltà.

Il testo è il seguente:
Si considerino tre vettori di reali (float), il cui numero di dati significativi “n” è fornito da tastiera,
contenenti elementi generati nel seguente modo:
• vettore temperatura valori casuali → nell'intervallo [17, 40]
• vettore pressione → valori casuali nell'intervallo [950, 1150]
• vettore umidita → valori casuali nell'intervallo [0, 100]
1. Scrivere una funzione che riceve i tre vettori e restituisce altri 3 vettori t2, p2 e u2 contenenti i
valori di temperatura, pressione, umidita che soddisfano TUTTE E TRE le seguenti relazioni:
▪ (temperatura – temperatura[i-1])< 3
▪ (pressione – pressione[i-1])< 50
▪ (umidita – umidita[i-1])> 5
2. Scrivere una funzione che, ricevuto in ingresso un intervallo di temperatura Tmin, Tmax,
inserito da tastiera, stampa i valori dei tre vettori t2, p2 e u2 per ogni indice i tale che t2 e'
compreso tra Tmin e Tmax.
3. Calcolare e stampare i valori massimi e minimi di p2 e u2.

Il mio svolgimento è:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>

void riempi_vettore ( float *v, int size , int a , int b);
void ricevi_vettore ( float * v1, float *v2, float *v3, int size, float *t2, float *p2, float *u2);
void funzione_temp ( float *v1, float *v2, float *v3, float *t2, float *p2, float *u2, int size, float Tmin, float Tmax);
int main (void) {
    int n, i, j, k, Max_p, Min_p, Max_u, Min_u;
    float * temperatura, *pressione, * umidita, *temperatura2, *pressione2, *umidita2;
    float T_max, T_min;
    
    
    printf ("Inserisci da tastiera il valore n \n");
    scanf ("%d", &n);
    
    /* Alloco dinamicamente i tre vettori */
    
    temperatura = (float*)malloc(n*sizeof(float));
    pressione = (float *)malloc (n*sizeof(float));
    umidita = (float*)malloc(n*sizeof(float));
    
    /* Riempio i vettori */
    
    riempi_vettore ( temperatura, n, 17, 40);
    
    /* stampo vettore */
    for (i = 0; i < n;i++)
        printf ("temperatura[%d] = %f\n", i, temperatura[i]);
    
    riempi_vettore (pressione, n, 950, 1150);
    
    /* stampo vettore */
    for (j = 0; j < n;j++)
        printf ("pressione[%d] = %f\n", j, pressione[j]);
        
    riempi_vettore ( umidita, n, 0, 100);
    /* stampo vettore */
    
    for (k = 0; k < n;k++)
        printf ("umidita[%d] = %f\n", k, umidita[k]);
    
    
    ricevi_vettore ( temperatura, pressione, umidita, n, temperatura2, pressione2, umidita2);
    
    printf (" Inserisci da tastiera il valore della temperatura minima \n");
    scanf ("%f", &T_min);
    
    printf (" Inserisci da tastiera il valore della temperatura massima \n");
    scanf ("%f", &T_max);
    
    funzione_temp (temperatura, pressione, umidita, temperatura2, pressione2, umidita2, n, T_min, T_max);
    
    /* Calcolo e stampo il valore massimo e minimo di pressione2 */
  Max_p = pressione2[0];
  Min_p = pressione2[0];
  i = 1;
  while (i < n) {
    if (pressione2[i] > Max_p) Max_p = pressione2[i];
    if (pressione2[i] < Min_p) Min_p = pressione2[i];
    i++;
  }
  printf("Il massimo e' = %d\n", Max_p);
  printf("Il minimo e' = %d\n", Min_p);
  
  /* Calcolo e stampo il valore massimo e minimo di umidita2 */
  Max_u = umidita2[0];
  Min_u = umidita2[0];
  i = 1;
  while (i < n) {
    if (umidita2[i] > Max_u) Max_u = umidita2[i];
    if (umidita2[i] < Min_u) Min_u = umidita2[i];
    i++;
  }
  printf("Il massimo e' = %d\n", Max_u);
  printf("Il minimo e' = %d\n", Min_u);
   
   
    system("pause");
}

void riempi_vettore ( float *v, int size, int a, int b) {
     int i;
     
     srand((unsigned)time(NULL));

     for (i=0; i<size; i++) {
         v[i]= rand()%(b-a+1) + a;
                     }
         }
void ricevi_vettore ( float * v1, float *v2, float *v3, int size, float *t2, float *p2, float *u2) {
     int i, j;
     
     for (i=0, j=0; i<size; i++) {
         
         if (((v1[i]- v1[i-1])<3) && ((v2[i]-v2[i-1])<50) && ((v3[i]-v3[i-1])>5)) {
                 t2[j]=v1[i];
                 p2[j]=v2[i];
                 u2[j]=v3[i];
                 }
                 j++;
               }   
     }
     
     /* per la chiamata a funzione....non so quali parametri inserire all'interno della funzione...*/

void funzione_temp ( float *v1, float *v2, float *v3, float *t2, float *p2, float *u2, int size, float Tmin, float Tmax) {
     int i;
     
     for (i=0; i<size; i++) {
     if (( t2[i]>= Tmax) && (t2[i]<=Tmin)) {
           printf ( " t2[%d]=%f \n", i, t2[i]);
           printf ( " p2[%d]=%f \n", i, p2[i]);
           printf ( " u2[%d]=%f \n", i, u2[i]);
                             }
               }
     }


Il compilatore non mi segnala errori, ma arrivato all'inserimento da tastiera dei valori Tmin e Tmax il programma si chiude :(
Dove sbaglio?

Vi ringrazio per l'aiuto.

Risposte
vict85
Ma ti basta applicare ciò che ti abbiamo corretto negli scorsi problemi.

Il resto mi sembra relativamente ok, quello che devi però modificare è ricevi vettore che dovrebbe avere questa forma:
int ricevi_vettore( float * v1, float *v2, float *v3, int size, float **t2, float **p2, float **u2);
oppure anche
size_t ricevi_vettore( float const * const v1, float const * const v2, float const * const v3, size_t const size, float **t2, float **p2, float **u2);
se vuoi dire al compilatore tutte le cose per bene.

In ogni caso l'importante, cosa che non fai, è comunicare al main:
[list=1][*:38lqdsun] La dimensione degli array *t2, *p2 e *u2;[/*:m:38lqdsun]
[*:38lqdsun] Allocare la memoria di *t2, *p2 e *u2.[/*:m:38lqdsun][/list:o:38lqdsun]
Queste due cose non sono fatte dal tuo codice che usa memoria non allocata.

Le altre due funzioni mi sembrano corrette anche se funzione_temp la puoi scrivere come
void funzione_temp ( float *t2, float *p2, float *u2, int size, float Tmin, float Tmax)
perché non usi il primo vettore. Attenzione che in size non ci devi mettere n ma il valore di ritorno di una rinnovata ricevi_vettore.

P.S.: comunque con gli ultimi standard del C (o meglio in tutti quelli degli ultimi 10-15 anni) non è più necessario definire le variabili all'inizio del blocco ma le puoi definire ovunque nella funzione. È spesso utile farlo per rendere più leggibile il codice.

bad.alex
Grazie Vict. Si, effettivamente quando devo scrivere una funzione che riceve gli elementi di un vettore ho parecchi problemi!
l'utilizzo dei doppi puntatori, in genere ne facciamo uso quando si utilizzano matrici. Per questo mi è difficile pensare a questi nel caso di vettori da riempire con elementi presi da altri vettori. Proverò a riscrivere quanto suggerito.
Per la dimensione dei vettori t2, p2,u2, sapendo che è da definire in base alla condizione,come faccio?
Devo restituire un valore nel main da allocare?

vict85
"bad.alex":
l'utilizzo dei doppi puntatori, in genere ne facciamo uso quando si utilizzano matrici.


Ti suggerisco di farti passare questa abitudine il prima possibile. Il metodo più comune ed efficace per gestire le matrici è usando array (o puntatori) a 1 dimensione e gestendo personalmente la memoria :roll: . Usare un puntatore a puntatori non migliora le performance (generalmente le peggiora) né tanto meno semplifica il codice. Non a caso ogni libreria seria di algebra lineare utilizza, per le matrici dense, array di una dimensione oppure strutture dati più complesse (specialmente quando la matrice è molto grande). E ti assicura che la differenza in performance non è trascurabile se lavori con matrici di 1000x1000 elementi (che è ancora una matrice piccola per scopi scientifici).

Ti conviene abituarti a pensare che un puntatore ad un puntatore è una variabile che contiene l'indirizzo di un puntatore (che a sua volta è una variabile che contiene l'indirizzo di una qualche variabile).

Quello che il main deve avere dalla funzione ricevi_vettore è un tripletta di vettori allocati e riempiti (con gli elementi di altri 3). Quello che invia è una tripletta di puntatori e tre vettori riempiti. Inoltre, siccome il c non memorizza le dimensioni nel vettore (altri linguaggi lo fanno), devi inviare la dimensione dei vettori riempiti e ritornare la dimensione di quelli che ha riempito ricevi_vettore. Sostanzialmente quindi la faccio tornare usando il valore di ritorno del main. Volendo posso anche usare un puntatore ad int.

bad.alex
Chiarissimo! Proverò ad abituarmi anche se l'argomento più difficile ( o almeno uno tra i più difficili...) è quello sui puntatori!
Grazie mille!!

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.