Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1

    [C] Calcolatrice polacca da riga di comando

    Un saluto a tutti i programmatori (o agli aspiranti tali )
    Sto provando ad orientarmi tra i complicati meandri dell'uso di puntatori. In questo momento sto provando a realizzare una calcolatrice da riga di comando in notazione polacca.

    Facendo delle prove generiche per provare il codice volta per volta, ottengo un errore di segmentation fault se provo ad eseguire questo codice

    codice:
    int main(int argc, char *argv[])
    {
    	while (--argc > 0)
    	{
    		if ( isdigit(*++argv))
    			printf("numero %f\n", (double) *argv);
    	}
    }
    Inoltre, poichè la calcolatrice polacca dovrebbe essere gestita come una pila, ho provato a scrivere queste due funzioni push e pop in questo modo.
    codice:
    #define MAX_OP 100
    double stack[MAX_OP];
    double *p = stack;
    
    void push(double n)
    {
    	*p++ = n;
    }
    
    double pop(void)
    {
    	return *--p;
    }
    Sembra funzionare bene dopo svariate prove, ma volevo capire se è possibile migliorarlo in qualche modo.

    Grazie mille a tutti per l'attenzione

  2. #2
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219

    Re: [C] Calcolatrice polacca da riga di comando

    Prima cosa: non ti consiglio di cambiare argc perchè poi perdi traccia del numero di elementi.Nel tuo caso va bene, ma se poi la calcolatrice la vuoi estendere per fargli fare cose più complesse, perdi traccia di argc (usa una variabile di appoggio).
    Poi (double)*argv ha come effetto quello di convertire il valore ascii del primo carattere della stringa.
    Usa la atof al posto del cast esplicito (la trovi sempre su c++ reference).
    Ma il perchè del segmentation fault mi sfugge, forse faresti meglio a gestire il tutto con un for:
    codice:
    for(int i=0;i<argc;i++)
        // gestisci argv[i]

  3. #3

    Re: Re: [C] Calcolatrice polacca da riga di comando

    Originariamente inviato da ramy89
    ....
    Prima di tutto grazie per i consigli, sempre ottimi spunti
    Per quanto riguarda il double, in effetti mi ero accorto che avevo scritto qualcosa che non era proprio ben chiaro. Il problema è che anche provando a dare qualcosa come
    codice:
    int main(int argc, char *argv[])
    {
            n = argc;
    	while (--n > 0)
    	{
    		if ( isdigit(*++argv))
    			printf("E' un numero\n");
    	}
    }
    Mentre in fase di compilazione non ho errori, appena eseguo il programma mi esce un errore di segmentazione :S

    Originariamente inviato da ramy89
    forse faresti meglio a gestire il tutto con un for:
    codice:
    for(int i=0;i<argc;i++)
        // gestisci argv[i]
    Il fatto è che volevo sbattere la testa il più possibile sui puntatori per capirli per bene, non mi piace conoscere le cose solo per sommi capi.

    PS: dici che si può postare il codice intero della calcolatrice? Non è molto lungo e forse potrei cavarne buoni consigli.

  4. #4
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219

    Re: Re: Re: [C] Calcolatrice polacca da riga di comando

    Originariamente inviato da tigerjack89

    PS: dici che si può postare il codice intero della calcolatrice? Non è molto lungo e forse potrei cavarne buoni consigli.
    Certo, anzi meglio se posti sempre il codice intero così si capisce meglio.

  5. #5
    Ci sto ancora lavorando, quindi potrebbero esserci degli errori grossolani, a parte ovviamente il segmentation fault del main a cui ora provo a porre rimedio.
    Grazie mille per l'aiuto
    codice:
    #include <stdio.h>
    
    void push(double);
    double pop(void);
    int isoperator(char *);
    void operation(void);
    
    int main(int argc, char *argv[])
    {
    	double value;
    	int n = argc;
    	int i = 0;
    	double op2 = 0.0;
    	while (--n > 0)
    	{
    		if ( isdigit(*argv))
    			push(atof(*argv));
    		
    		else if( isoperator(*argv) )
    		{
    			switch ( (*argv)[0])
    			{
    				case '+':
    				push (pop() + pop() );
    				break;
    				
    				case '*':
    				push (pop() * pop() );
    				break;
    				
    				case '-':
    				op2 = pop();
    				push(pop() - op2);
    				break;
    				
    				case '/':
    				op2 = pop();
    				push(pop() - op2);
    				break;
    				
    				default:
    				printf("Undefined operations\n");
    				break;
    			};
    		}
    		else
    			printf("Stringa non valida\n");
    	}
    	argv++;
    }
    
    #define MAX_OP 100
    double stack[MAX_OP];
    double *p = stack;
    int stackp = 0;
    
    void push(double n)
    {
    	*p++ = n;
    }
    
    double pop(void)
    {
    	return *--p;
    }
    
    int isoperator(char *s)
    {
    	if (*s == '+' || *s == '-' || *s == '*' || *s == '/')
    		if (*++s == '\0')
    			return 1;
    	return 0;		
    }
    
    void operation(void)
    {
    	//Vorrei delegare a questa funzione la gestione delle operazioni, ma per il
    	//momento non so ancora come fare
    }

  6. #6
    Il problema principale è riuscire a gestire le stringhe di caratteri memorizzate in char *argv[].
    Infatti, usando *argv[], dovrebbe restituirmi la stringa, che poi posso usare o passare a una funzione, ma se mi da Errore di segmentazione non so in che altro modo passare direttamente la stringa puntata :S

  7. #7
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Nella pop:

    codice:
    double pop(void)
    {
    	return *--p;
    }
    Se p punta all' ultimo elemento inserito, con un pre-decremento restituisci il penultimo inserito, non l' ultimo.
    Meglio fare un post-decremento:
    codice:
    double pop(void)
    {
    	return *p--;
    }
    Sai la riga esatta dove avviene il segmentation fault?
    E altra cosa: gli argomenti possono anche essere tantissimi? Cioè si può digitare 2+4*6+7 ? Perchè in questo caso devi dare la precedenza agli operatori.

  8. #8
    Originariamente inviato da ramy89
    Nella pop:
    Se p punta all' ultimo elemento inserito, con un pre-decremento restituisci il penultimo inserito, non l' ultimo.
    Meglio fare un post-decremento:
    La pop, collaudata, dovrebbe essere giusta, in quanto dovrebbe essere chiamata solo in caso sia già stato invocato push(). Quando invochi push, prima copi il valore nella posizione corrente e poi incrementi la posizione; per questo la posizione dell'ultimo valore è quella precedente a quella puntata attualmente.
    Che poi ci dovrebbe essere qualcosa per controllare gli errori e le eccezioni, beh su quello hai ragione, ma ci lavorerò in seguito, appena mi riesce di finire il programma per sommi capi
    Sai la riga esatta dove avviene il segmentation fault?
    E altra cosa: gli argomenti possono anche essere tantissimi? Cioè si può digitare 2+4*6+7 ? Perchè in questo caso devi dare la precedenza agli operatori.
    Dovrebbe essere in questa parte di codice
    codice:
    		if ( isdigit(*argv))
    			push(atof(*argv));
    Riguardando meglio, penso che la funzione isdigit si aspetta un carattere e non una stringa.

    Per quanto riguarda gli argomenti, si, possono essere massimo 100, come nella definizione di MAX_OP; non so come gestire argomenti infiniti poi per usarli nelle funzioni push e pop.
    Ad ogni modo, la calcolatrice polacca è leggermente diversa da quella tradizionale.
    Se scrivi qualcosa del tipo 2 3 4 + * dovrebbe darti (4 + 3) * 2.
    In pratica mette i valori in un pila e li estrai in ordine inverso; estrae il primo, prende l'operatore e fa (primo estratto (operatore) 2)) e lo memorizza di nuovo nella pila, per poi continuare. Un po' grossolana come spiegazione, ma spero si capisca

  9. #9
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Prova a cambiare l' argomento della isdigit con *argv[0] , però tieni presente che così stai controllando un solo carattere: il primo.
    Faresti meglio a usare la atoi.

  10. #10
    Allora, ho modificato dopo vari sbattimenti il main in questo modo

    EDIT: FUNZIONA !!
    codice:
    int main(int argc, char *argv[])
    {
    	int value;
    	int n = argc;
    	int i;	
    	int op2 = 0;
    	
    	while (--n > 0)
    	{
    		argv++;
    		i = 0;
    		while ( isdigit( (*argv)[i++]))
    			;
    /*			
    		for (i = 0; (*argv)[i]; i++)
    			printf("i = %d \tc=%c\n", i, (*argv)[i]);
    		printf ("i = %d e argv[i] = %d\n", i, (*argv)[i]);	
    */			
    		if (i > 1 && (*argv)[i-1] == '\0')
    		{
    			value = atoi(*argv);
    			push(value);
    			printf("value is %d\n", value);
    		}	
    		else if( isoperator(*argv) )
    		{
    			switch ( (*argv)[0])
    			{
    				case '+':
    				push (pop() + pop() );
    				break;
    				
    				case '*':
    				push (pop() * pop() );
    				break;
    				
    				case '-':
    				op2 = pop();
    				push(pop() - op2);
    				break;
    				
    				case '/':
    				op2 = pop();
    				push(pop() - op2);
    				break;
    				
    				default:
    				printf("Undefined operations\n");
    				break;
    			};
    		}
    		else
    			printf("Stringa non valida\n");
    //
    
    //
    	}
    	
    	printf("%d\n", pop());
    }

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.