Re: [C] Dichiarazione funzione in ANSI C

Messaggioda Zyzzoy » 11/01/2019, 19:03

Codice:
double y = funzione( x, c, r0 );


è questo che mi mandava, io mettevo solo funzione (x); , dopo provo a ricalcolarlo. Quindi non si possono tirare in ballo gli indicatori i per svolgere il problema? Io:
-prima inizializzavo tutti i c[i]
-poi con un ciclo esterno e uno interno calcolavo le x e y mettendo nell espressione di y i c[i] (come ho fatto el messaggio prima).


Nel secondo ci capisco poco
Codice:
struct Retta {
    double m;
    double q;
};


Questa cosa non l'ho mai vista.

Nemmeno questa con le freccie
Codice:
{
    retta->m = c;
    retta->q = r * sin( c * c + 1 );
}


Provo a farlo come nel primo caso. Oggi ho dato l'esame, e cos ha messo il prof? Quest esercizio nella parte grafica dove già so fare poco o nulla, la funzione non l ho dichiarata e schiaffata direttamente nell int main (void) { , quindi probabilmente il calvario non sarà terminato nemmeno questa volta.


Beh in effetti mi diceva che nella funzione c erano troppi pochi argomenti, mea culpa
Zyzzoy
Junior Member
Junior Member
 
Messaggio: 12 di 324
Iscritto il: 06/01/2019, 17:36

Re: [C] Dichiarazione funzione in ANSI C

Messaggioda vict85 » 11/01/2019, 23:29

Non avevo inizializzato alcun array perché potevo generare i c e gli x durante il ciclo, ma è senz'altro possibile farlo. Per esempio:
Codice:
#include <math.h>
#include <stdio.h>

/**
 * Data la famiglia di rette
 *     \[\{ f_{c,\ r} = cx + r\sin(c^2 + 1) \colon c, r \in \mathbf{R} \},\]
 * questa funzione calcola il valore della funzione $f_{c,r}$ nel punto $x$.
 */
double funzione(double x, double c, double r);

int main(void)
{
#define NUM_RETTE (5)
    double c[NUM_RETTE];

#define NUM_SEGMENTI (10)
    double x[NUM_SEGMENTI];

    double y[NUM_RETTE][NUM_SEGMENTI];

    const double r0 = 2.0;

    /* inizializzazione c */
    c[0] = 0.1;
    {
        int i;
        for (i = 1; i < NUM_RETTE; ++i)
        {
            c[i] = c[i - 1] + 0.1;
        }
    }

    /* inizializzazione x */
    x[0] = 0.0;
    {
        int i;
        const double d = 1.0 / NUM_SEGMENTI;
        for (i = 1; i < NUM_SEGMENTI; ++i)
        {
            x[i] = x[i - 1] + d;
        }
    }

    { /* calcolo delle y */
        int i;
        for (i = 0; i < NUM_RETTE; ++i)
        {
            int j;
            for (j = 0; j < NUM_SEGMENTI; ++j)
            {
                y[i][j] = funzione(x[j], c[i], r0);
            }
        }
    }
    { /* stampare a video */
        int i;
        for (i = 0; i < NUM_RETTE; ++i)
        {
            int j;
            for (j = 0; j < NUM_SEGMENTI; ++j)
            {
                printf("c=%f, r=%f, x=%f, y=%f\n", c[i], r0, x[j], y[i][j]);
            }
        }
    }

#undef NUM_RETTE
#undef NUM_SEGMENTI
}

double funzione(double x, double c, double r)
{
    return x * c + r * sin(c * c + 1);
}


Tieni conto che ho scritto il codice in un modo un po' "antiquato", legato al fatto che tu continui ad evidenziare che usi l'ANSI C. Usando l'ultimo standard (che di fatto è anche lui ANSI/ISO1) lo avrei potuto scrivere così:
Codice:
#include <math.h>
#include <stdio.h>

/**
 * Data la famiglia di rette
 *     \[\{ f_{c,\ r} = cx + r\sin(c^2 + 1) \colon c, r \in \mathbf{R} \},\]
 * questa funzione calcola il valore della funzione $f_{c,r}$ nel punto $x$.
 */
double funzione(double x, double c, double r);

int main(void)
{
    #define NUM_RETTE (5)
    double c[NUM_RETTE] = { [0] = 0.1 };
    for (int i = 1; i < NUM_RETTE; ++i)
    {
        c[i] = c[i - 1] + 0.1;
    }

    #define NUM_SEGMENTI (10)
    double x[NUM_SEGMENTI] = { [0] = 0.0 };
    {
        const double d = 1.0 / NUM_SEGMENTI;     
        for (int i = 1; i < NUM_SEGMENTI; ++i)
        {
            x[i] = x[i - 1] + d;
        }
    }

    double y[NUM_RETTE][NUM_SEGMENTI];
    const double r0 = 2.0f;
    // calcolo delle y
    for (int i = 0; i < NUM_RETTE; ++i)
    {
        for (int j = 0; j < NUM_SEGMENTI; ++j)
        {
            y[i][j] = funzione(x[j], c[i], r0);
        }
    }

    // stampare a video
    for (int i = 0; i < NUM_RETTE; ++i)
    {
        for (int j = 0; j < NUM_SEGMENTI; ++j)
        {
            printf("c=%f, r=%f, x=%f, y=%f\n", c[i], r0, x[j], y[i][j]);
        }
    }
#undef NUM_SEGMENTI
#undef NUM_RETTE
}

double funzione(double x, double c, double r)
{
    return x * c + r * sin(c * c + 1);
}


Nota che si potevano fare altre modifiche, per esempio si può spostare l'inizializzazione in una funzione esterna e fare
Codice:
#include <math.h>
#include <stdio.h>

/**
 * Data la famiglia di rette
 *     \[\{ f_{c,\ r} = cx + r\sin(c^2 + 1) \colon c, r \in \mathbf{R} \},\]
 * questa funzione calcola il valore della funzione $f_{c,r}$ nel punto $x$.
 */
double funzione(double x, double c, double r);

/**
 * Inizializza un array con una progressione aritmentica
 */
void inizializza(double a[], unsigned int size, double start, double step);

int main(void)
{
#define NUM_RETTE (5)
    double c[NUM_RETTE];
    inizializza(c, NUM_RETTE, 0.1, 0.1);

#define NUM_SEGMENTI (10)
    double x[NUM_SEGMENTI];
    inizializza(x, NUM_SEGMENTI, 0.0, (1.0 / NUM_SEGMENTI));

    double y[NUM_RETTE][NUM_SEGMENTI];
    const double r0 = 2.0;

    for (int i = 0; i < NUM_RETTE; ++i)
    {
        for (int j = 0; j < NUM_SEGMENTI; ++j)
        {
            y[i][j] = funzione(x[j], c[i], r0);
        }
    }

    for (int i = 0; i < NUM_RETTE; ++i)
    {
        for (int j = 0; j < NUM_SEGMENTI; ++j)
        {
            printf("c=%f, r=%f, x=%f, y=%f\n", c[i], r0, x[j], y[i][j]);
        }
    }

#undef NUM_RETTE
#undef NUM_SEGMENTI
}

double funzione(double x, double c, double r)
{
    return x * c + r * sin(c * c + 1);
}

void inizializza(double a[], unsigned int size, double start, double step)
{
    a[0] = start;
    for (unsigned int i = 1; i < size; ++i)
    {
        a[i] = a[i - 1] + step;
    }
}

Note

  1. Su gcc, il dialetto C di default è il gnu11 che è una versione modificata dell'ultimo standard.
vict85
Moderatore
Moderatore
 
Messaggio: 9456 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C] Dichiarazione funzione in ANSI C

Messaggioda Zyzzoy » 12/01/2019, 00:43

Codice:
/* inizializzazione x */
    x[0] = 0.0;
    {
        int i;
        const double d = 1.0 / NUM_SEGMENTI;
        for (i = 1; i < NUM_SEGMENTI; ++i)
        {
            x[i] = x[i - 1] + d;
        }
    }

Nel primo esercizio quelle graffe senza ciclo servono a qualcosa o si possono omettere?

Codice:
y[i][j] = funzione(x[j], c[i], r0);


Questa è una matrice vero? Noi non le abbiamo fatte!

Codice:
}

#undef NUM_RETTE
#undef NUM_SEGMENTI
}


#undef cosa sarebbe?

Comunque ti ringrazio per la disponibilità, conosci un testo dove ci sono le basi del c di semplice interpretazione? Se cerco su internet una cosa (come per esempio quella di questa domanda) mi dà 100 versioni diverse e non saprei distinguere da un c++ a un c o gnu (non so cosa sia). Io penso che usiamo l'ANSI c, ma non so se sia una normativa o cosa, ne so come funziona. Nel nostro corso son state fatte solo esercitazioni senza teoria (e la poca teoria spiegata veramente male). Io so come svolgere a macchinetta pezzi degli esercizi che mi dà, ma se cambia qualcosa già non so dove mettere le mani, come in questo caso che penso sia una cosa banale questa.Quello che so lo so grazie ai tutorial di c di un ragazzo su youtube e esercizi ormai imparati a memoria a forza di farli.
Zyzzoy
Junior Member
Junior Member
 
Messaggio: 13 di 324
Iscritto il: 06/01/2019, 17:36

Re: [C] Dichiarazione funzione in ANSI C

Messaggioda vict85 » 12/01/2019, 17:12

Siccome conosco il C e il C++ da 17 anni, non saprei fornirti una buona guida. Io avevo studiato su un libro del C++ che ormai è datatissimo (il C++ è stato quasi completamente rivoluzionato nel 2011) e avevo pian piano scoperto le differenze con il C. Lo standard del 2011 del C, seppur sia stato meno rivoluzionario di quello del C++, è stato recepito in maniera positiva (al contrario di quello del 1999) quindi la maggior parte dei libri attuali lo useranno (o per lo meno non si preoccuperanno di un paio di limitazioni dell'ANSI C che venivano considerate antiquate già quando ho imparato il C io). Molti amanti del C considerano "The C Programming Language" (Second Edition) di Brian Kernighan e Dennis Ritchie come il libro su cui si dovrebbe studiare il C. Sinceramente io non l'ho usato e trovo il fatto che non sia stato aggiornato alle nuove versioni del linguaggio in grosso limite. Per esempio, il libro non terrà sicuramente conto del fatto che alcune funzioni di I/O sono attualmente deprecate, rimosse o comunque considerate poco sicure.

L'istruzione per il preprocessore #undef serve ad annullare un #define. La puoi ignorare.

Riguardo alla matrice/array multidimensionale, sì è una matrice/array multidimensionale. L'uso base lo puoi vedere lì. Di fatto non è altro che un array di array. Il mio comunque era solo un esempio, si può stampare direttamente il risultato a video invece di memorizzarlo oppure mettere due cicli non annidati all'interno del ciclo delle rette e memorizzare gli y per le varie rette in maniera indipendente.

Riguardo alle parentesi graffe, penso possa essere utile una spiegazione un po' più dettagliata. Una istruzione composta (spesso detta blocco di codice) consiste in una sequenza di definizioni e istruzioni racchiuse tra parentesi graffe. In generale, puoi mettere istruzioni composte ogni qual volta puoi usare istruzioni semplici (insomma una espressione seguita da ; ). Un esempio di questo "scambio" lo puoi vedere con if, for, switch, while e do.

Per capirci
Codice:
for( i = 0; i < 3; i++ )
printf( "1" );
printf( "2" );
stampa a video "1112" (non ho indentato i due printf per non creare confusione), mentre
Codice:
for( i = 0; i < 3; i++ )
{
    printf( "1" );
    printf( "2" ):
}
stampa "121212".

Una differenza tra C89 e gli standard successivi è che questi ultimi permettono di ordinare definizioni/dichiarazioni e istruzioni in qualsiasi ordine all'interno del blocco. Nel C89, le definizioni/dichiarazioni devono/dovevano precedere ogni istruzione.

Una cosa importante da sapere sulle istruzioni composte è che ogni variabile dichiarata in quell'istruzione è visibile SOLO all'interno del blocco stesso. In un certo senso puoi pensare che quella variabile viene creata nel momento in cui viene definita e poi distrutta alla fine del blocco. A livello professionale, definire le variabili solo quanto ti servono esplicitamente e restringere il loro "scope" il più possibile è considerata una buona prassi (da una parte aiuta il compilatore a capire quando non hai più bisogno di qualcosa e dall'altro evita alcuni errori che possono capitare quando recicli variabili). Nel mio esempio precedente, stavo evitando di riutilizzare gli indici dei cicli. Nota che con gli standard successivi al C89, è possibile definire variabili direttamente nella fare si inizializzazione del for.
vict85
Moderatore
Moderatore
 
Messaggio: 9457 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C] Dichiarazione funzione in ANSI C

Messaggioda Zyzzoy » 13/01/2019, 19:34

se voglio ottenere 1112 in output posso fare:

Codice:
for( i = 0; i < 3; i++ ){
printf( "1" ); }
printf( "2" );


per ottenere 121212

Codice:
for( i = 0; i < 3; i++ )
{
    printf( "1" );
    printf( "2" ):
}


Io intendevo ste graffe quà fuori che racchiudono le costanti e il ciclo for a cosa servono

Codice:
{
        int i;
        const double d = 1.0 / NUM_SEGMENTI;
        for (i = 1; i < NUM_SEGMENTI; ++i)
        {
            x[i] = x[i - 1] + d;
        }
   


Servono solo per dire che le verabili definite e la variabile inizializzata d e il contatore i valgono solo all'interno del ciclo e fuori non son nè definite nè inizializzate? Il prof a volte in alcuni esercizi faceva cicli for come questo:

Codice:
for( i = 0; i < 3; i++ )
printf( "1" );
printf( "2" );


Senza alcuna parentesi graffa, se le scordava o è un modo alternativo?
Zyzzoy
Junior Member
Junior Member
 
Messaggio: 15 di 324
Iscritto il: 06/01/2019, 17:36

Re: [C] Dichiarazione funzione in ANSI C

Messaggioda vict85 » 14/01/2019, 16:25

Le parentesi graffe formano quello che viene chiamato una istruzione composta o blocco. Ogni istruzione composta è vista come una unica istruzione e ogni variabile al suo interno è locale a quel blocco.

Per capirci,
Codice:
int main( void )
{
    { int i; }
    i = 2;
}

non compilerà. L'errore sarà che
Codice:
i
non è definita (perché è locale del blocco in cui è definita). Nel codice di qualche messaggio fa, ho messo quelle parentesi per restringere la variabile i al solo ciclo.

Il discorso relativo al for era solo per dire che il for faceva il ciclo sulla prima istruzione che lo seguiva, complessa o semplice che sia. Quindi se non metti le parentesi, ti esegue una sola espressione. Non avevo dimenticato alcune parentesi. Ma non metterle è spesso fonte di errore, quindi è utile sapere cose succede se non le metti, ma è sempre meglio metterle.
vict85
Moderatore
Moderatore
 
Messaggio: 9458 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C] Dichiarazione funzione in ANSI C

Messaggioda Zyzzoy » 14/01/2019, 20:45

Immagino che ti darà anche l errore che i non è usata. Non capisco che fastidio dia al programma se dichiari variabili senza poi usarle. Quindi l'assenza delle parentesi col ciclo for era voluta dal prof quando il for doveva eseguire una sola istruzione messa dopo il for stesso. Domani faccio un salto in biblioteca per vedere se c'è qualche buon libro e iniziare a studiare ,dopo il 5/30 preso all'esame. Meccanica razionale è una passeggiata in confronto a sta roba, possibile che debba perdere cosi tanto tempo con una materia che non centra nulla con il mio corso? Comunque ti ringrazio per l'aiuto che mi hai dato e sopratutto per la pazienza !
Zyzzoy
Junior Member
Junior Member
 
Messaggio: 21 di 324
Iscritto il: 06/01/2019, 17:36

Precedente

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite