KR esercizio 5.10 e domanda sui puntatori

di il
8 risposte

KR esercizio 5.10 e domanda sui puntatori

Ciao a tutti. Prima di parlare dell'esercizio vorrei fare una domanda sui puntatori.

Nei programmi che prevedono l'esecuzione da riga di comando, per considerare la stringa corrispondente all'argomento 0, ad esempio nel caso in cui volessi passare la stringa come argomento in una funzione, dovrei scrivere *argv[0], questa scrittura è equivalente ad *argv e fin qui ci sono.
Visto però che l'oggetto in questione è una stringa, esso corrisponde all'indirizzo del primo carattere, allora scrivere argv[0] senza asterisco, che sarebbe l'indirizzo dell'argomento zero, in questo caso equivale alle altre due scritture, visto l'argomento zero è un vettore e il suo valore equivale all'indirizzo del primo carattere della stringa?

Passando all'esercizio. Chiede di scrivere un programma eseguibile da linea di comando, che valuta espressioni in notazione Polacca inversa. Siccome al capitolo 4 paragrafo 3 c'è un esempio di programma che valuta queste espressioni, non ho dovuto scrivere l'intero programma, ma solo modificare questo.

La modifica più consistente è sulla funzione getop, che prende come argomento un carattere anzichè una stringa:
#include <ctype.h>

int getop(char c)
{
    if (isdigit(c) && c!= '.')
        return c;
    else
        return NUMBER
}
Le altre modifiche appartengono al main: il ciclo while, la cui durata sarà uguale a quella di argc-1 (visto che il primo argomento è il nome del programma) e l'assegnamento a type che viene spostato all'interno del ciclo (l'argomento passato a getop sarà il primo carattere della stringa dell'argomento prossimo (*++argv)[0]), infine negli altri posti in cui si usava la stringa s, viene passata invece la stringa dell'argomento corrente *argv. (il vettore s non serve più in quanto gli operandi e gli operatori sono già salvati in argv.)
Le funzioni push e pop rimangono invariate.

#include <stdio.h>
#include <math.h> 
#define MAXOP 100 
#define NUMBER ’0’ 

int getop(char s[]);
void push(double);
double pop(void);

main()
{
    int type;
    double op2;

    while (--argc > 0)
    {
        type = getop( (*++argv)[0] );
        switch (type) {
            case NUMBER:
                push(atof(*argv));
                break;
            case ’+’:
                push(pop()+pop());
                break;
            case ’*’:
                push(pop()*pop());
                break;
            case ’-’:
                op2=pop();
                push(pop()-op2);
                break;
            case ’/’:
                op2=pop();
                if (op2!=0.0)
                    push(pop()/op2);
                else
                    printf(“Errore: divisione per zero\n”);
                break;
            case ’\n’:
                printf(“\t%.8g\n”, pop());
                break;
            default:
                printf(“Errore: comando %s sconosciuto\n”, *argv);
                break;
        }
    }
    return 0;
}

/* Funzioni push e pop */
#define MAXVAL 100 
int sp = 0; 
double val[MAXVAL]; 

void push(double f)
{
    if (sp<MAXVAL)
        val[sp++]=f;
    else
        printf(“Errore: stack pieno; %g non inseribile\n”, f);
}

double pop(void)
{
    if (sp>0)
        return val[sp—];
    else {
        printf(“Errore: lo stack è vuoto\n”);
        return 0.0;
    }
}

8 Risposte

  • Re: KR esercizio 5.10 e domanda sui puntatori

    E qual è il tuo dubbio?
  • Re: KR esercizio 5.10 e domanda sui puntatori

    XD volevo sapere se ho commesso errori tra l'altro non avendo mai usato linux non ho familiarità con l'esecuzione da linea di comando quindi non posso verificare. esiste un programma che simuli la linea di comando su windows?

    Per quanto riguarda la domanda sui puntatori che mi dici? Lo so che è contorta ma meglio di così non so come spiegarmi
  • Re: KR esercizio 5.10 e domanda sui puntatori

    La domanda non si capisce ...
  • Re: KR esercizio 5.10 e domanda sui puntatori

    In windows puoi utilizzare il prompt dei comandi cmd.exe .
    Per quanto riguarda gli argomenti della linea di comando non ho capito quali dubbi hai: argv[0] é il puntatore al nome del programma e da argv[1] ad argv[argc-1] hai i puntatori agli argomenti.
  • Re: KR esercizio 5.10 e domanda sui puntatori

    Grazie.
    Per la domanda provo a spiegarmi meglio.

    Diciamo che voglio usare la funzione atof che prende come argomento una stringa che rappresenta un numero e la converte in float.
    Voglio passare il primo argomento (per intenderci *argv[1]) come argomento di atof:

    - posso scrivere semplicemente atof(*argv[1])
    - oppure posso scrivere atof(*++argv)
    - ma posso scrivere anche atof(++argv) oppure atof(argv+1) (e di conseguenza anche atof(argv[1]))? Se la risposta è no, perchè?

    So a cosa serve l'operatore *, tuttavia mi sembra un caso particolare visto che in questo caso l'oggetto cui punta il puntatore è un indirizzo.
    Quando passo una stringa come argomento in una funzione quello che sto passando è l'indirizzo della stringa, precisamente l'indirizzo del primo carattere della stringa.
    argv è l'indirizzo della stringa 0, mentre argv+1 è l'indirizzo della stringa 1, quindi dovrei poter passare come argomento anche argv+1. Se non è così, dove sbaglio?

    Detto questo, dal modo in cui hai risposto mi hai fatto ricordare di un dubbio che ho avuto durante la lettura. argv è un puntatore che punta ad un vettore che contiene stringhe, oppure un vettore che contiene puntatori che puntano a stringhe? (e no... non l'ho rubata a Marzullo se ve lo state chiedendo )

    La prima definizione che ne da il libro è la prima che ho scritto (ossia un puntatore ad un vettore di stringhe), ma mi sembra che in seguito parli argv come di un vettore di puntatori (cosa che sottintendevi anche tu). All'atto pratico mi sembrano la stessa cosa visto che ogni elemento del vettore (in un caso e nell'altro) contiene un indirizzo, ma tecnicamente ci dovrebbe essere una sottile differenza. No?
  • Re: KR esercizio 5.10 e domanda sui puntatori

    - posso scrivere semplicemente atof(*argv[1])
    No, *argv[1] è un carattere
    - oppure posso scrivere atof(*++argv)
    Non va bene, modificheresti argv e dopo sono guai ...
    ma posso scrivere anche atof(++argv)
    Neanche questo, vedi sopra ...
    oppure atof(argv+1)
    No, forse intendi *(argv+1), è diverso ...
    anche atof(argv[1]))
    Sì, questo è giusto
    Quando passo una stringa come argomento in una funzione quello che sto passando è l'indirizzo della stringa, precisamente l'indirizzo del primo carattere della stringa.

    argv è l'indirizzo della stringa 0
    No. E' l'indirizzo del puntatore alla prima stringa
    mentre argv+1 è l'indirizzo della stringa 1
    No. E' *(argv+1) l'indirizzo del puntatore alla stringa 1.
    argv è un puntatore che punta ad un vettore che contiene stringhe, oppure un vettore che contiene puntatori che puntano a stringhe? (e no... non l'ho rubata a Marzullo se ve lo state chiedendo )
    E' un puntatore ad un vettore di puntatori che puntano alle varie stringhe ...
  • Re: KR esercizio 5.10 e domanda sui puntatori

    oregon ha scritto:


    - posso scrivere semplicemente atof(*argv[1])
    No, *argv[1] è un carattere
    Ecco, qui ho fatto confusione. E' il primo carattere del primo argomento? Il fatto è che mi vengono i dubbi e vorrei chiarirmi le idee. Se *argv corrisponde al puntatore che punta al nome del programma, *++argv corrisponde al puntatore che punta al primo argomento, anche argv[1] è il puntatore al primo argomento (che contiene l'indirizzo al primo carattere del primo argomento)? Quindi *argv[1] sarà il primo carattere del primo argomento, giusto?

    oregon ha scritto:


    - oppure posso scrivere atof(*++argv)
    Non va bene, modificheresti argv e dopo sono guai ...
    Al di là dei guai, questa scrittura è giusta? Essendo un puntatore, è come passare l'indirizzo del primo argomento?
    Sul libro la usa come esempio, ma immagino perchè il programma in questione accede una sola volta ad ogni argomento in maniera sequenziale. I guai cui ti riferisci immagino sorgano nel momento in cui qualche funzione vorrebbe far uso di argv dopo la modifica e in effetti pensavo potesse dare problemi in questi casi.

    oregon ha scritto:


    ma posso scrivere anche atof(++argv)
    Neanche questo, vedi sopra ...
    Ti riferisci ai guai? Per ora mi interessa capire la dinamica dei puntatori, fa niente se porta guai, mi serve per capire. se *++argv è il puntatore al primo argomento, ++argv è l'indirizzo di tale puntatore, quindi all'atto pratico atof(*++argv) ha lo stesso effetto di atof(++argv) ed sintatticamente corretto?

    oregon ha scritto:


    oppure atof(argv+1)
    No, forse intendi *(argv+1), è diverso ...
    Anche qui, *(argv+1) è il puntatore al primo argomento (quindi equivale a *++argv), questo vuol dire che (argv+1) è l'indirizzo di tale puntatore giusto? So che l'indirizzo del puntatore è diverso dal puntatore, ma come quello che vorrei capire è se possono essere passati entrambi come argomento indifferentemente.

    oregon ha scritto:


    anche atof(argv[1]))
    Sì, questo è giusto
    Ok. Quindi se ho capito bene argv[1] == *++argv == *(argv+1) e corrispondono al puntatore che punta al primo argomento.
    Mentre ++argv == (argv+1) == (a qualche altra cosa?) corrispondono all'indirizzo del puntatore di cui sopra.

    oregon ha scritto:


    argv è l'indirizzo della stringa 0
    No. E' l'indirizzo del puntatore alla prima stringa
    mentre argv+1 è l'indirizzo della stringa 1
    No. E' *(argv+1) l'indirizzo del puntatore alla stringa 1.
    argv è un puntatore che punta ad un vettore che contiene stringhe, oppure un vettore che contiene puntatori che puntano a stringhe? (e no... non l'ho rubata a Marzullo se ve lo state chiedendo )
    E' un puntatore ad un vettore di puntatori che puntano alle varie stringhe ...
    [/quote]

    Ok grazie. I dubbi in pratica derivavano da una definizione errata (avevo capito male cosa fosse argv). Spero di aver capito bene adesso.
  • Re: KR esercizio 5.10 e domanda sui puntatori

    ++argv modifica il valore di argv quindi si usa per puntare al prossimo puntatore, al secondo, al terzo, al quarto e così via.
Devi accedere o registrarti per scrivere nel forum
8 risposte