[C] funzione che ritorna due valori
Ciao. Dopo aver provato mille modi, ho bisogno di una mano per capire come stampare entrambi i valori che ottengo da una funzione. Questa prende in ingresso due matrici e la loro dimensione che è uguale. Non importa che vi dica cosa fa perché la funzione inserire dovrebbe essere giusta, però non capisco come poter mettere in un printf nel main entrambi i valori di risposta che sono un arrai D e una matrice C[i*N+j].
oppure questo nel main, e vari altri tentativi, ma nulla, ottengo numeri stranissimi
grazie
printf("somma %d, diagonale %d", C[i*N+j], D[s]); //ho provato a scrivere questo nella funzione return C, D;
oppure questo nel main, e vari altri tentativi, ma nulla, ottengo numeri stranissimi
*C, *D=funzione(A,B,size); printf("ris1:%d \n",*C); printf("ris2 %d",*D);
grazie
Risposte
In C una funzione può ritornare un solo valore. Ci sono comunque due modi per aggirare questa "restrizione":
- inserire tutti i dati di interesse in una struct e impostare tale struct come valore di ritorno della funzione;
- passare per indirizzo tutti i dati di interesse a una funzione di tipo void in modo che le modifiche apportate all'interno della funzione restino anche nel main.
Ipotizziamo di utilizzare la seconda soluzione, la funzione assumerà una forma del tipo:
void funzione(int **A , int **B, int dim, int **C, int *D) //C e D saranno già stati dichiarati nel main
{
...
}
Ritornando al main le modifiche apportate a C e D saranno conservate, ma nulla sappiamo circa le loro dimensioni (che ipotizzo variano al variare dei valori contenuti in A e B) che sono indispensabili per impostare i cicli for per visualizzarli a schermo. Quindi anche le dimensioni di C e D andranno passate per indirizzo alla funzione in cui verranno modificate opportunamente.
- inserire tutti i dati di interesse in una struct e impostare tale struct come valore di ritorno della funzione;
- passare per indirizzo tutti i dati di interesse a una funzione di tipo void in modo che le modifiche apportate all'interno della funzione restino anche nel main.
Ipotizziamo di utilizzare la seconda soluzione, la funzione assumerà una forma del tipo:
void funzione(int **A , int **B, int dim, int **C, int *D) //C e D saranno già stati dichiarati nel main
{
...
}
Ritornando al main le modifiche apportate a C e D saranno conservate, ma nulla sappiamo circa le loro dimensioni (che ipotizzo variano al variare dei valori contenuti in A e B) che sono indispensabili per impostare i cicli for per visualizzarli a schermo. Quindi anche le dimensioni di C e D andranno passate per indirizzo alla funzione in cui verranno modificate opportunamente.
"Super Squirrel":
In C una funzione può ritornare un solo valore. Ci sono comunque due modi per aggirare questa "restrizione":
- inserire tutti i dati di interesse in una struct e impostare tale struct come valore di ritorno della funzione;
- passare per indirizzo tutti i dati di interesse a una funzione di tipo void in modo che le modifiche apportate all'interno della funzione restino anche nel main.
Ipotizziamo di utilizzare la seconda soluzione, la funzione assumerà una forma del tipo:
void funzione(int **A , int **B, int dim, int **C, int *D) //C e D saranno già stati dichiarati nel main
{
...
}
Ritornando al main le modifiche apportate a C e D saranno conservate, ma nulla sappiamo circa le loro dimensioni (che ipotizzo variano al variare dei valori contenuti in A e B) che sono indispensabili per impostare i cicli for per visualizzarli a schermo. Quindi anche le dimensioni di C e D andranno passate per indirizzo alla funzione in cui verranno modificate opportunamente.
Ma la funzione in void è un'altra funzione da mettere dopo la mia di operazione o dici che la funzione che faccio è necessario sia in void? Una domanda, perché il doppio puntatore alle matrici?
Come già correttamente osservato da Super Squirrel non è possibile restituire due valori da una funzione C come sembra tu stia cercando di fare in quel pezzo di codice. La virgola è in effetti un operatore in C che dice di valutare la prima espressione, ignorarne il valore e quindi usare la seconda espressione come valore finale. In altri termini, il tuo codice è del tutto equivalente al seguente:
Ci sono poi altri aspetti del tuo codice che mi fanno pensare che sia tutto molto sbagliato. *C e *D non rappresentano l'intero array, ma solo il loro primo elemento. Mi sembra quinid che in realtà la tua funzione stia semplicemente restituendo un singolo intero (che è ovviamente molto diverso da voler restituire due array/matrici). Mostra insomma tutto il codice che hai provato a scrivere perché penso che ci sia ben poco di corretto. Non sembra tu abbia infatti capito veramente come si lavora con array e puntatori in C.
*D = funzione(A, B, size); printf("ris1:%d \n",*C); printf("ris2 %d",*D);
Ci sono poi altri aspetti del tuo codice che mi fanno pensare che sia tutto molto sbagliato. *C e *D non rappresentano l'intero array, ma solo il loro primo elemento. Mi sembra quinid che in realtà la tua funzione stia semplicemente restituendo un singolo intero (che è ovviamente molto diverso da voler restituire due array/matrici). Mostra insomma tutto il codice che hai provato a scrivere perché penso che ci sia ben poco di corretto. Non sembra tu abbia infatti capito veramente come si lavora con array e puntatori in C.
grazie ma ho risolto, ho fatto un printf all'interno della funzione per uno dei risultati mentre l'altro nel main. Grazie

Credo sia comunque utile descrivere meglio in che modo avresti potuto restituire un array e una matrice dalla tua funzione in caso diventi necessario in altre occasioni. Non sempre è infatti sufficiente mostrare tali valori. Siccome l'unico problema reale con quella particolare forma che mi viene in mente è la ricerca di autovalori e autovettori generalizzati, che risolvono cioè il problema \( A\,v = \lambda\,B\,v, \) mi inventerò un problema fittizio molto più semplice. Suppongo per comodità quindi che il vettore \(D\) sia la diagonale del prodotto tra \(A\) e \(B\) e \(C\) sia la somma tra le due matrici. Esistono principalmente due strategie:
1. Usare una struttura come valore di ritorno.
2. Passare i valori di ritorno per riferimento.
Le due strategie sono mostrate nel seguente codice:
Una versione alloca la matrice e il vettore nella funzione e restituisce una struttura che le contiene entrambe. L'altra invece riceve in ingresso due ulteriori argomenti che verranno usati come output. E' ovviamente possibile mischiare le due strategie. Restituire quindi uno dei due input come valore di ritorno e ricevere l'altro come argomento.
1. Usare una struttura come valore di ritorno.
2. Passare i valori di ritorno per riferimento.
Le due strategie sono mostrate nel seguente codice:
#include <stdio.h> #include <stdlib.h> typedef struct FunResult { double *C; // Matrice double[size*size] double *D; // Vettore double[size] } FunResult; FunResult functionStruct(size_t N, double A[N*N], double B[N*N]) { double *C = calloc(N*N, sizeof(double)); double *D = calloc(N, sizeof(double)); for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { C[i*N + j] = A[i*N + j] + B[i*N + j]; D[i] += A[i*N + j] * B[j*N + i]; } } return (FunResult){ C, D }; } void functionArgs(size_t N, double A[N*N], double B[N*N], double C[N*N], double D[N]) { for (int i = 0; i < N; ++i) { D[i] = 0.0; for (int j = 0; j < N; ++j) { C[i*N + j] = A[i*N + j] + B[i*N + j]; D[i] += A[i*N + j] * B[j*N + i]; } } } int main(int argc, char const *argv[]) { double A[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}; double B[] = {2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 3.0, 1.0}; FunResult result = functionStruct(3, A, B); printf("Matrix C:\n"); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { printf("%lf ", result.C[i*3 + j]); } printf("\n"); } printf("Vector D:\n"); for (int i = 0; i < 3; ++i) { printf("%lf ", result.D[i]); } printf("\n"); free(result.C); free(result.D); double C[9] = { 0 }; double D[3] = { 0 }; functionArgs(3, A, B, C, D); printf("Matrix C:\n"); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { printf("%lf ", C[i*3 + j]); } printf("\n"); } printf("Vector D:\n"); for (int i = 0; i < 3; ++i) { printf("%lf ", D[i]); } printf("\n"); return 0; }
Una versione alloca la matrice e il vettore nella funzione e restituisce una struttura che le contiene entrambe. L'altra invece riceve in ingresso due ulteriori argomenti che verranno usati come output. E' ovviamente possibile mischiare le due strategie. Restituire quindi uno dei due input come valore di ritorno e ricevere l'altro come argomento.
Grazie mille. Sicuramente potrebbe essermi utile. Per fortuna ho trovato quell'alternativa che per il mio esercizio andava bene perché questo sembra un po' macchinoso.
Ti chiedo solo due cose:
la scrittura += cosa significa?
in: D += A[i*N + j] * B[j*N + i];
E la scrittura come result.C e result.D quando può essere usata? Intendo il punto. Quando si sta usando un passaggio per riferimento e quindi si sceglie di "passare il puntatore" (ipotesi mia)?
Ti chiedo solo due cose:
la scrittura += cosa significa?
in: D += A[i*N + j] * B[j*N + i];
E la scrittura come result.C e result.D quando può essere usata? Intendo il punto. Quando si sta usando un passaggio per riferimento e quindi si sceglie di "passare il puntatore" (ipotesi mia)?
a += b
coincide con
a = a + b.
. e -> servono ad accedere ai membri di una struct. In particolare si usa il punto quando abbiamo un oggetto e la freccia quando abbiamo un puntatore ad oggetto. Per esempio:
coincide con
a = a + b.
. e -> servono ad accedere ai membri di una struct. In particolare si usa il punto quando abbiamo un oggetto e la freccia quando abbiamo un puntatore ad oggetto. Per esempio:
#include <stdlib.h> struct esempio { int a; }; int main() { struct esempio oggetto; oggetto.a = 24; struct esempio *ptr = &oggetto; printf("%d", ptr->a); return 0; }