[C] Esercizio notazione polacca inversa

Gead1

Nuovo Utente
2
0
@Gead1 (great nickname BTW)
Ieri ho avuto tempo di provare il tuo programma, che funziona bene anche a me. Sei sicuro che lo hai trasferito correttamente nel computer scolastico? Sei sicuro di avere immesso i dati correttamente? Quando ti dà errore, al primo passo, in alcuni o in tutti?

Il tuo codice mi pare ben strutturato, se posso dare un consiglio è di implementare la lista di tipo LIFO in quanto è proprio quella che si usa per la notazione polacca inversa (dove il primo operando che si usa è l’ultimo a essere immesso), ti semplifica il codice non poco.
I dati sono stati passati correttamente anche perchè ho fatto un semplice ctrl+c e ctrl+v, il problema del compilatore scolastico è che non mi fa vedere l'output che esce a lui e mi riporta solamente l'errore che avevo scritto, l'unico caso in cui posso avere l'errore è nel caso in cui inserisco il valore "2147483648" direttamente(Quindi dovrebbe riportarmi l'overflow dopo il tentativo di concatenamento) perchè non è presente negli altri testcase. Comunque ho provato a rimuovere le 2 variabili globali e mi da lo stesso errore. Grazie per il consiglio sulla lista. Questo è il codice che ho riscritto:
C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define LENGHT 35

//Struttura che conterrà i valori delle espressioni
typedef struct n{
    int numero;
    struct n *nextPtr;
}Numeri;
typedef Numeri *numPtr;

//Dichiarazione funzioni
int acquisisci(char *stringa);
void azzera(numPtr *nPtr);
unsigned short int concatena(numPtr *nPtr, short int val);
void newNum(numPtr *nPtr, short int val);
unsigned short int calcolo(numPtr *nPtr, short int temp);
void stampa(numPtr *nPtr, unsigned short int ov);
void complemento2(int num);


//Inizio main
int main()
{
    short int temp = 0;
    unsigned short int ov;
    unsigned short int conc;
    unsigned short int negativo = 0;
    char espressione[LENGHT]; //Variabile che conterrà l'espressione
    Numeri *nPtr = NULL; //Dichiarazione e inizializzazione puntatore

    while(acquisisci(espressione)){//Ripeto fin quando non trovo il valore "fine"
        //Azzero la lista ad ogni reiterazione del ciclo while

        azzera(&nPtr);
        conc = 0;
        ov = 0;
        //Analizzo ogni elemento dell'espressione
        for(size_t i = 0; i<strlen(espressione); i++){
            //Trasformo in int l'iesimo elemento dell'espressione
            temp = (int)espressione[i];

            //Se abbiamo un "-" seguito da un valore allora abbiamo un numero negativo
            if(temp == 45 && isdigit(espressione[i+1])){
                negativo = 1;
            }
            //Se abbiamo un valore intero
            else if(temp < 58 && temp > 47){
                temp = temp - '0'; //Convertiamo il valore dal suo codice ascii al suo reale valore
                if(conc == 1){//Concateniamo al numero letto in precedenza
                    ov = concatena(&nPtr, temp);
                    if(ov == 1){
                        break;
                    }
                }else{ //Oppure creiamo un nuovo elemento in lista
                    if(negativo == 1){
                        temp *= -1;
                        negativo = 0;
                    }
                    newNum(&nPtr, temp);
                    conc = 1;
                }
            }
            //Se il valore è un'operazione (+, - o *) chiamiamo la funzione calcolo
            else if(temp == 45 || temp == 43 || temp == 42){
                ov = calcolo(&nPtr, temp);
                if(ov == 1){
                    break;
                }
            }else{//Altrimenti sarà uno spazio e quindi azzariamo conc
                conc = 0;
            }
        }
        //Stampiamo il risultato dopo aver analizzato l'espressione
        stampa(&nPtr, ov);
    }
    //Azzeriamo definitivamente la lista
    azzera(&nPtr);

}
//Funzione per l'acquisizione della stringa da stdin
int acquisisci(char *stringa){
    fgets(stringa, LENGHT, stdin);
    stringa[strlen(stringa) - 1] = 0;
    if(strcmp(stringa, "fine")){//Se la stringa è "fine" allora restituiamo 1 per interrompere l'esecuzione
        return 1;
    }else{
        return 0;
    }
    while(getchar() != '\n');
}

//Funzione per azzerare la lista prima di una nuova conversione o alla fine del programma
void azzera(numPtr *nPtr){
    //Inizializziamo i puntatori necessari
    numPtr corrPtr = *nPtr;
    numPtr tempPtr = NULL;
    //Libero la memoria allocata per ogni puntatore fino all'ultimo
    while(corrPtr != NULL){
        tempPtr = corrPtr;
        corrPtr = corrPtr->nextPtr;
        free(tempPtr);
    }
    *nPtr = NULL;
}

//Funzione per inzializzare e inserire un nuovo elemento in lista
void newNum(numPtr *nPtr, short int val){
    //Inizializziamo i puntatori necessari
    numPtr corrPtr = *nPtr;
    numPtr precPtr = NULL;

    //Allochianmo la memoria per il nuovo nodo e il nuovo nodo
    numPtr nuovoPtr = malloc(sizeof(Numeri));
    if(nuovoPtr == NULL){
        puts("Memoria insufficiente!");
        exit(0);
    }
    nuovoPtr->numero = val;
    nuovoPtr->nextPtr = NULL;

    //Portiamoci all'ultimo elemento della lista
    while(corrPtr != NULL){
        precPtr = corrPtr;
        corrPtr = corrPtr->nextPtr;
    }
    //Se la lista è vuota la inizializziamo
    if(precPtr == NULL){
        nuovoPtr->nextPtr = *nPtr;
        *nPtr = nuovoPtr;
    }else{ //Altrimenti lo aggiungiamo in
        precPtr->nextPtr = nuovoPtr;
        nuovoPtr->nextPtr = corrPtr;
    }
    //Aggiunto un nuovo nodo, avvertiamo che i successivi valori saranno da concatenare
    return;
}
//Funzione per la concatenazione
unsigned short int concatena(numPtr *nPtr, short int val){
    //Inizializziamo i puntatori e le variabili necessarie
    numPtr corrPtr = *nPtr;
    numPtr precPtr = NULL;
    int temp = 0;
    unsigned short int ov = 0;
    //Arrivo all'ultimo elemento in lista
    while(corrPtr != NULL){
        precPtr = corrPtr;
        corrPtr = corrPtr->nextPtr;
    }
    //Concateno il numero e controllo se faccia overflow il concatenamento
    if(precPtr->numero<0){
        temp = precPtr->numero;
        if(temp == -214748364 && val == 9){
            ov = 1;
        }else{
            precPtr->numero = (precPtr->numero * 10) - val;
        }
        if(temp<precPtr->numero){
            ov = 1;
        }
    }else{
        temp = precPtr->numero;
        if(temp == 214748364 && val>7){
            ov = 1;
        }else{
            precPtr->numero = (precPtr->numero * 10) + val;
            if(temp>precPtr->numero){
                ov = 1;
            }
        }

    }
    return ov;
}

//Funzione per il calcolo che svolge l'operazione con gli ultimi 2 numeri in lista
unsigned short int calcolo(numPtr *nPtr, short int temp){
    numPtr corrPtr = *nPtr;
    numPtr precPtr = NULL;
    unsigned short int ov = 0;

    while(corrPtr->nextPtr != NULL){
        precPtr = corrPtr;
        corrPtr = corrPtr->nextPtr;
    }
    int primo = precPtr->numero;
    int secondo = corrPtr->numero;

    //Controllo overflow moltiplicazione
    if(temp == 42){
        if(primo == 0 || secondo == 0){//Se abbiamo uno "0" allora la moltiplicazione farà 0
            precPtr->numero = 0;
        }
        if(primo>0){
            if(secondo>0){
                if(primo > (precPtr->numero = primo*secondo) ){//Se i 2 numeri sono > 0 e temp < primo allora abbiamo overflow
                    ov = 1;
                }
            }else{//Primo > 0 e secondo < 0
                if(primo < (precPtr->numero = primo*secondo)){//Se primo è minore della molt. allora abbiamo overflow
                    ov = 1;
                }
            }
        }else{
            if(secondo > 0){ //Primo min 0 e sec magg 0
                if(primo < (precPtr->numero = primo*secondo)){//Se primo < operazione allora abbiamo overflow
                    ov = 1;
                }
            }else{//Anche secondo minore di 0
                if(primo > (precPtr->numero = primo*secondo) ){//Se primo > operazione allora overflow
                    ov = 1;
                }
            }
        }
    }
    //Controllo overflow somma
    else if(temp == 43){
        //Se l'operazione è una somma e uno dei due valori è 0 allora restituiamo l'altro valore
        if(primo == 0){
            precPtr->numero = secondo;
        }else if(secondo == 0){
            precPtr->numero = primo;
        }
        if(primo>0){
            if(secondo>0){//Primo e secondo > 0
                if(primo > (precPtr->numero = primo + secondo)){//Se primo > somma allora overflow
                    ov = 1;
                }
            }
        }else{
            if(secondo > 0){//Eseguiamo l'operazione perchè non può esserci overflow
                precPtr->numero = primo + secondo;
            }else{
                if(primo < (precPtr->numero = primo + secondo)){//Se sec < 0 e primo < somma allora overflow
                    ov = 1;
                }
            }
        }
    }
    //Controllo overflow sottrazione
    else if(temp == 45){
        //Nella sottrazione, se il secondo valore è 0 possiamo ritornare direttamente il primo
        if(secondo == 0){
            precPtr->numero = primo;
        }
        if(primo >= 0){
            if(secondo>0){//Primo e secondo > 0 eseguiamo sottrazione
                precPtr->numero = primo - secondo;
            }else{//Secondo minore 0 controlliamo overflow
                if(primo >= (precPtr->numero = primo - secondo)){
                    ov = 1;
                }
            }
        }else{
            if(secondo >= 0){//Primo >= 0, secondo < 0 controlliamo overflow
                if(primo < (precPtr->numero = primo - secondo)){
                    ov = 1;
                }
            }else{//Secondo < 0 eseguiamo sottrazione perchè non può essere overflow
                precPtr->numero = primo - secondo;
            }
        }
    }
    free(corrPtr);//Liberiamo in nodo che non ci serve più
    precPtr->nextPtr = NULL;
    return ov;
}

//Funzione per la stampa del valore finale e conversione in c2
void stampa(numPtr *nPtr, unsigned short int ov){
    //Se abbiamo un overflow stampiamo l'errore
    if(ov == 1){
        puts("Overflow!");
        ov = 0;
        return;
    }
    numPtr corrPtr = *nPtr;
    //Stampiamo il valore e chiamiamo la funzione per il complemento a 2
    printf("%d in C2:  ", corrPtr->numero);
    complemento2(corrPtr->numero);
}

//Funzione per effettuare il complemento a 2
void complemento2(int num){

    unsigned short int numconv[32];
    unsigned short int cont=31;
    unsigned short int spazi=0;
    size_t neg=0;
    size_t riporto=0;

    if(num==1){
        printf("0000 0000 0000 0000 0000 0000 0000 0001");
        return;
    }
    if(num==0){
        printf("0000 0000 0000 0000 0000 0000 0000 0000");
        return;
    }
    if(num<0){
        neg=1;
        num *= -1;
    }
    for(int i=0; i<=cont; i++){
            numconv[i]=0;
    }
    while(num>0){
        numconv[cont]=num%2;
        cont--;
        num=num/2;
    }
    if(neg==1){
        for(int i=0; i<32; i++){
            if(numconv[i]==0){
                numconv[i]=1;
            }
            else if(numconv[i]==1){
                numconv[i]=0;
            }
        }
        for(int k=31; k>=0; k--){
            if(k==31){
                numconv[k] += 1;
                if(numconv[k]==2){
                    riporto=1;
                    numconv[k]=0;
                }
            }else{
                if(riporto==1 && numconv[k]==0){
                    numconv[k]=1;
                    riporto=0;
                }else if(riporto==1 && numconv[k]==1){
                    numconv[k]=0;
                    riporto=1;
                }
            }
        }
        numconv[0]=1;
    }
    for(size_t i=0; i<32; i++){
        printf("%d", numconv[i]);
        spazi++;
        if(spazi==4){
            printf(" ");
            spazi=0;
        }

    }
    printf("\n");
}

Post unito automaticamente:

Non ho il tempo di trovare il problema preciso, compilato stesso test case qui
non da problemi. Per trovare il problema facilmente sulla macchina dove lo da,

Codice:
gcc -ggdb -o binario main.c

gdb ./binario
run
Purtroppo non ho la possibilità di operare sulla macchina dove da l'errore perchè è una sorta di compilatore online fornito dall'università e restituisce solo la correttezza dell'output o l'errore come nel mio caso.
 

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili