Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Ricerca personalizzata

C: Come gestire una funzione che restituisce due valori?

Linguaggi e sistemi

Moderatori: Foto UtentePaolino, Foto UtenteMassimoB

0
voti

[11] Re: C: Come gestire una funznione che restituisce due valori

Messaggioda Foto UtenteMax2433BO » 29 apr 2017, 10:21

Ti ringrazio Foto UtenteDirtyDeeds,

ma il mio scopo era capire come ritornare due valori da una funzione al main senza variabili globali e/o puntatori, la divisione tra interi era solo un pretesto, appunto, per ritornare due valori...

... torno a studiare le strutture.

O_/ Max
Disapprovo quello che dite, ma difenderò fino alla morte il vostro diritto di dirlo [attribuita a Voltaire]

Sapere sia di sapere una cosa, sia di non saperla: questa è conoscenza. [Confucio, "I colloqui"]
Avatar utente
Foto UtenteMax2433BO
4.813 2 5 9
Master
Master
 
Messaggi: 1412
Iscritto il: 25 set 2013, 15:29
Località: Un puntino insignificante nell'universo!!

1
voti

[12] Re: C: Come gestire una funznione che restituisce due valori

Messaggioda Foto UtenteTardoFreak » 29 apr 2017, 10:36

Le strutture sono molto importanti e, almeno nei microcontrollori, vengono utilizzate per passare molti parametri e contenere eventuali valori di ritorno perché è sufficiente passare un puntatore ad una struct e la funzione, in pratica, lavora sui dati originali.
Va da se che passare un puntatore è un'operazione velocissima e la struttura può essere di dimensioni enormi. Può ad esempio contenere array, stringhe, dati numerici tutti insieme ...
Ah, dimenticavo: negli argomenti stringhe ed array viene passato il puntatore.
Nel data sheet si trova tutto. Anche gli errori.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
PIERIN-PIC18
Avatar utente
Foto UtenteTardoFreak
71,4k 8 12 13
G.Master EY
G.Master EY
 
Messaggi: 15623
Iscritto il: 16 dic 2009, 10:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[13] Re: C: Come gestire una funznione che restituisce due valori

Messaggioda Foto UtenteMax2433BO » 29 apr 2017, 10:45

:ok:

So che devo ancora studiare parecchio ma approfitterei per farti un paio di domande per vedere se, almeno, ho capito il concetto:

1) In pratica le strutture potrei paragonarle ad un array che può contenere qualsiasi tipologia di variabile (a differenza dell'array standard che contiene variabili di un unico tipo, es. int, char, ...) e l'utilizzo della struttura avviene tramite un puntatore alla struttura e tramite il nome della variabile contenuta nella struttura stessa.

2) Se la funzione può andare a modificare direttamente i dati all'interno di una variabile contenuta nella struttura, qual è il vantaggio rispetto ad avere variabili globali?

O_/ Max
Disapprovo quello che dite, ma difenderò fino alla morte il vostro diritto di dirlo [attribuita a Voltaire]

Sapere sia di sapere una cosa, sia di non saperla: questa è conoscenza. [Confucio, "I colloqui"]
Avatar utente
Foto UtenteMax2433BO
4.813 2 5 9
Master
Master
 
Messaggi: 1412
Iscritto il: 25 set 2013, 15:29
Località: Un puntino insignificante nell'universo!!

1
voti

[14] Re: C: Come gestire una funznione che restituisce due valori

Messaggioda Foto UtenteTardoFreak » 29 apr 2017, 11:06

Le variabili globali sono visibili ovunque, la struttura, essendo una variabile, può avere la visibilità che decidi tu.
Puoi anche passarla come copia (senza puntatore) o riceverla come variabile (come negli esempi precedenti).
Le variabili globali dovrebbero essere evitate, soprattutto quando i programmi diventano grandi.
Vedi, quando si scrivono programmi si è soliti suddividerli in moduli (che sono dei files) che fanno un qualcosa di specifico.
Ad esempio nei micro c'è quasi sempre un modulo che si chiama HAL.c (Hardware Astractin Layer) che contiene tutte le funzioni relative all'hardware del sistema. Quindi se voglio attivare un relè il modulo implementerà la funzione rele_on() e rele_off(). Quello che queste due funzioni fanno per attivare il relè non si deve sapere, deve rimanere incapsulato nel modulo. Il lavoro dietro alle quinte interessa solo al modulo, renderlo visibile creerebbe solo casino e non servirebbe a niente. Poi, all'interno del modulo ci sarà di tutto e di più ma verrà reso visibile solo quello che serve. Questa tecnica, che è un requisito vero e proprio per un programma ben scritto, si chiama incapsulamento.
Tutto quello che non è strettamente utile non deve essere visibile al popolo. :mrgreen:
Il main, come altri moduli che devono agire sull'hardware, vedranno solo queste due funzioni e vivranno felici.

Edit: ad esempio in questo momento sto implementando un interprete per messaggi di sistema che risiende in un modulo. In pratica riceve un comando, fa un qualcosa e restituisce eventualmente una risposta. L'unica cosa che è visibile è la funzione
Codice: Seleziona tutto
uint8_t masgServer(char* command, char* output)

E ne fa di cotte e di crude, ma lo sa solo lui (ed io che lo scrivendo eh eh eh) :mrgreen:
Nel data sheet si trova tutto. Anche gli errori.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
PIERIN-PIC18
Avatar utente
Foto UtenteTardoFreak
71,4k 8 12 13
G.Master EY
G.Master EY
 
Messaggi: 15623
Iscritto il: 16 dic 2009, 10:10
Località: Torino - 3° pianeta del Sistema Solare

1
voti

[15] Re: C: Come gestire una funznione che restituisce due valori

Messaggioda Foto UtenteMax2433BO » 29 apr 2017, 11:13

:ok: ... grazie mille per la spiegazione!!

TardoFreak ha scritto:Tutto quello che non è strettamente utile non deve essere visibile al popolo. :mrgreen:


... come si dice in questi casi: E' cosa buona et giusta!!

O_/ Max
Disapprovo quello che dite, ma difenderò fino alla morte il vostro diritto di dirlo [attribuita a Voltaire]

Sapere sia di sapere una cosa, sia di non saperla: questa è conoscenza. [Confucio, "I colloqui"]
Avatar utente
Foto UtenteMax2433BO
4.813 2 5 9
Master
Master
 
Messaggi: 1412
Iscritto il: 25 set 2013, 15:29
Località: Un puntino insignificante nell'universo!!

0
voti

[16] Re: C: Come gestire una funzione che restituisce due valori?

Messaggioda Foto UtenteMax2433BO » 30 apr 2017, 9:47

Scusate se approfitto ancora della vostra pazienza :mrgreen: ma non mi è chiaro che differenza ci sia (se c'è) tra l'utilizzare una struttura (nel mio caso in maniera molto banale... forse troppo) e utilizzare delle variabili globali: in fin dei conti la modifica delle variabili interne alla struttura si ripercuote, comunque al di fuori del modulo che ha effettuato la modifica, proprio come accade con le variabili globali.

Esempio banale di struttura

Codice: Seleziona tutto
#include <stdio.h>
#include <stdlib.h>

struct numeri {
   
    int a;
    int b;
   
};

struct numeri Numeri = {0, 0};

void modifica_Numeri ();

/*
*
*/
int main(int argc, char** argv) {

    Numeri.a = 12;
    Numeri.b = 20;
   
    printf ("%d, %d \n", Numeri.a, Numeri.b);
   
    modifica_Numeri ();
   
    printf ("%d, %d \n", Numeri.a, Numeri.b);
   
    return (EXIT_SUCCESS);
}

void modifica_Numeri () {
   
    printf ("%d, %d \n", Numeri.a, Numeri.b);
   
    Numeri.a = 3;
    Numeri.b = 5;
   
    printf ("%d, %d \n", Numeri.a, Numeri.b);
   
    return;
}


risultato

Codice: Seleziona tutto
12, 20
12, 20
3, 5
3, 5

RUN FINISHED; exit value 0,; real time: 0ms; user: 0ms; system: 0ms


O_/ Max
Disapprovo quello che dite, ma difenderò fino alla morte il vostro diritto di dirlo [attribuita a Voltaire]

Sapere sia di sapere una cosa, sia di non saperla: questa è conoscenza. [Confucio, "I colloqui"]
Avatar utente
Foto UtenteMax2433BO
4.813 2 5 9
Master
Master
 
Messaggi: 1412
Iscritto il: 25 set 2013, 15:29
Località: Un puntino insignificante nell'universo!!

2
voti

[17] Re: C: Come gestire una funzione che restituisce due valori?

Messaggioda Foto UtenteTardoFreak » 30 apr 2017, 10:20

Andiamo un po' fuori tema ma riprendo il discorso visibilità.
Nel programma che hai scritto puoi notare alcune cose:
- Il tipo di variabile (struttura) è visibile in tutto il programma ed è utilizzabile da qualsiasi funzione contenuta nel programma (ovviamente dichiarata dopo la dichiarazione della struct, altrimenti non sa cos'è, succede anche con i tipi di base).
- La variabile Numeri l'hai dichiarata come globale e quindi è visibile da tutti.
- Se tu avessi dichiarato la variabile Numeri all'interno della frunzione main questa sarebbe stata visibile solo al suo interno ma da nessun'altra parte del programma.
Esistono diversi tipi di visibilità (chiamati scope)

Visibilità a livello di blocco e di funzione
Codice: Seleziona tutto
void main(void)
{
  int i;
  for(i=0; i<10; i++)
  {
    int b;
    // ...
  }
}

In questo caso la variabile i è visibile all'interno della funzione main mentre la variabile b esiste ed è visibile solo all'interno del blocco sotto il for.

Visibilità a livello di modulo
Se in un file a parte, chiamato modulo, dichiari una viariabile globale con l'attributo static questa sarà visibile solo all'interno di quel file. Supponiamo che tu abbia il programma principale in un file chiamato main.c e alcune funzioni e variabile in un altro file chiamato funzioni.c contenente:
Codice: Seleziona tutto
int var_a;
static int var_b;

void func_a(void)
{
  /...
}

static void func_b(void)
{
  /...
}

La variabile var_a non è visibile all'interno del file mani.c ma poi il linker se la va a cercare comunque, come pure la funzione func_a. La funzione func_b e la variabile var_b sono visibili solo all'interno del file funzioni.h e non c'è verso che altri file riescano a vederle. SOno incapsulate nel modulo funzioni.c
Nel data sheet si trova tutto. Anche gli errori.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
PIERIN-PIC18
Avatar utente
Foto UtenteTardoFreak
71,4k 8 12 13
G.Master EY
G.Master EY
 
Messaggi: 15623
Iscritto il: 16 dic 2009, 10:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[18] Re: C: Come gestire una funzione che restituisce due valori?

Messaggioda Foto UtenteMax2433BO » 30 apr 2017, 10:39

Perfetto, fino qui ci sono:

1) Se una variabile è esterna al main è visibile a chiunque
2) Se la variabile è interna al main, alla funzione, o a un modulo, è visibile, rispettivamente, solo al main, alla funznione o al modulo che la contiene
3) Se la variabile appartiene ad una funzione esterna al programma principale (richiamata con il comando #include... giusto?) ed è dichiarata static, allora è visibile solo dalla funzione stessa, altrimenti è visibile anche dal programma che l'ha richiamata.

Ma, a questo punto, l'unica soluzione per passare due (o più valori) come elaborati da una funzione ad un main rimane l'utilizzo delle sole variabili globali o delle variabili puntatore, giusto?

O_/ Max
Disapprovo quello che dite, ma difenderò fino alla morte il vostro diritto di dirlo [attribuita a Voltaire]

Sapere sia di sapere una cosa, sia di non saperla: questa è conoscenza. [Confucio, "I colloqui"]
Avatar utente
Foto UtenteMax2433BO
4.813 2 5 9
Master
Master
 
Messaggi: 1412
Iscritto il: 25 set 2013, 15:29
Località: Un puntino insignificante nell'universo!!

1
voti

[19] Re: C: Come gestire una funzione che restituisce due valori?

Messaggioda Foto UtenteTardoFreak » 30 apr 2017, 10:53

Direi di SI. Uno è il modo indicato da me e Foto Utentesimo85 ma c'è un altro modo. Considera questo programma
Codice: Seleziona tutto
typedef struct divisione_t
{
  int dividendo;
  int divisore;
  int risultato;
  int resto;
}

int divisione(divisione_t* s)
{
  if (s->divisore == 0) return 0;
  s->risultato = s->dividendo / s->divisore;
  s->resto = s->dividendo % s->divisore;
  return 1;
}

void main(void)
{
  int ok;
  divisione_t a;
  a.divindendo = 19;
  a.divisore = 4;
  ok = divisione(&a);
  if (ok == 1) printf("Risultato=%d Resto=%d\n", a.risultato, a.resto);
  else printf("Divisione per zero!\n");
}

Per la struttura c'è poco da dire, contiene le quattro variabili coinvolte nella divisione.
La funzione, ricevendo il puntato alla struttura, lavora su tutti i suoi campi modificandoli opportunamente. Se la divisione è andata a buon fine il valore di ritorno sarà 1, se si cerca di dividere un numero per 0 il valore di ritorno varrà 0.
All'interno della funzione main esistono le variabile ok e a che sono solo visibili al suo interno.
Con questa tecnica possiamo scrivere funzioni che lavorano direttamente sui dati e restituiscono non un valore ma un'informazione su come è andato il lavoro.

MI accorgo che sto divagando un po', se vado troppo fuori tema dimmelo.
Nel data sheet si trova tutto. Anche gli errori.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
PIERIN-PIC18
Avatar utente
Foto UtenteTardoFreak
71,4k 8 12 13
G.Master EY
G.Master EY
 
Messaggi: 15623
Iscritto il: 16 dic 2009, 10:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[20] Re: C: Come gestire una funzione che restituisce due valori?

Messaggioda Foto UtenteTardoFreak » 30 apr 2017, 11:05

Aggiungo ancora una piccola considerazione su come si trattano le variabili in modo sicuro e bene incapsulato
Supponiamo di avere una variabile ti tipo int che si chiama pippo e che risiede in un file chiamato lavori.c
Codice: Seleziona tutto
static int pippo;

int getPippo(void)
{
  return pippo;
}

void setPippo(int val)
{
  pippo = val;
}

int elaboraPippo(void)
{
  // fa l'elaborazione che deve fare
  // andato male
  return 0;
  // Andato bene
  return 1;
}

se nel programma principale vuoi leggere e/o scrivere nella variabile pippo, non fai riferimento direttamente alla variabile ma usi le cosiddette "funzioni setter e getter" tipiche del linguaggio Java ma che io uso anche in C.
Codice: Seleziona tutto
void main(void)
{
  setPippo(15);
  if (elaboraPippo() == 1) printf("Pippo vale ora %d\n", getPippo());
    else printf("Qualcosa è andato storto!\n");
}
Nel data sheet si trova tutto. Anche gli errori.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
PIERIN-PIC18
Avatar utente
Foto UtenteTardoFreak
71,4k 8 12 13
G.Master EY
G.Master EY
 
Messaggi: 15623
Iscritto il: 16 dic 2009, 10:10
Località: Torino - 3° pianeta del Sistema Solare

PrecedenteProssimo

Torna a PC e informatica

Chi c’è in linea

Visitano il forum: Nessuno e 7 ospiti