[C] funzione che ritorna due valori

Messaggioda Fenix797 » 25/02/2018, 11:22

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[s] e una matrice C[i*N+j].



Codice:
 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
Codice:
 *C, *D=funzione(A,B,size);
     
        printf("ris1:%d \n",*C);
    printf("ris2 %d",*D);



grazie
Fenix797
Junior Member
Junior Member
 
Messaggio: 45 di 138
Iscritto il: 01/02/2017, 10:42

Re: [C] funzione che ritorna due valori

Messaggioda Super Squirrel » 25/02/2018, 12:45

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.
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 165 di 1486
Iscritto il: 16/05/2013, 22:05

Re: [C] funzione che ritorna due valori

Messaggioda Fenix797 » 25/02/2018, 14:27

Super Squirrel ha scritto: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?
Fenix797
Junior Member
Junior Member
 
Messaggio: 46 di 138
Iscritto il: 01/02/2017, 10:42

Re: [C] funzione che ritorna due valori

Messaggioda apatriarca » 25/02/2018, 15:06

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:
Codice:
*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.
apatriarca
Moderatore
Moderatore
 
Messaggio: 4987 di 10435
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] funzione che ritorna due valori

Messaggioda Fenix797 » 25/02/2018, 15:20

grazie ma ho risolto, ho fatto un printf all'interno della funzione per uno dei risultati mentre l'altro nel main. Grazie :)
Fenix797
Junior Member
Junior Member
 
Messaggio: 47 di 138
Iscritto il: 01/02/2017, 10:42

Re: [C] funzione che ritorna due valori

Messaggioda apatriarca » 25/02/2018, 16:15

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:
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.
apatriarca
Moderatore
Moderatore
 
Messaggio: 4989 di 10435
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] funzione che ritorna due valori

Messaggioda Fenix797 » 25/02/2018, 19:22

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[i] += A[i*N + j] * B[j*N + i];

E la scrittura come result.C e result.D[i] 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)?
Fenix797
Junior Member
Junior Member
 
Messaggio: 49 di 138
Iscritto il: 01/02/2017, 10:42

Re: [C] funzione che ritorna due valori

Messaggioda Super Squirrel » 25/02/2018, 20:20

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:

Codice:
#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;
}
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 167 di 1486
Iscritto il: 16/05/2013, 22:05


Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite

cron