Ciao, mi servirebbe una mano con questo programma che sto scrivendo, effettua l'espressione data in input in forma di notazione polacca inversa e restituisce il calcolo in complemento a 2 binario. Siccome devo farlo verificare dal compilatore dell'università ho dei test case, a me escono tutti senza problemi, sul sito dell'uni invece mi da " Execution killed with signal 11 (could be triggered by violating memory limits) " su questo test case:
2147483648 -1 * (Risultato: Overflow!)
2147483648 -1 * 1 - (Risultato: Overflow!)
1024 1024 * 1024 * -2 * (Risultato: -2147483648 in C2: 1000 0000 0000 0000 0000 0000 0000 0000)
1024 1024 * 1024 * 2 * (Risultato: Overflow!)
2147483647 1 + (Risultato: Overflow!)
2147483647 1 - (Risultato: 2147483646 in C2: 0111 1111 1111 1111 1111 1111 1111 1110)
fine
Il codice che ho scritto è il seguente:
2147483648 -1 * (Risultato: Overflow!)
2147483648 -1 * 1 - (Risultato: Overflow!)
1024 1024 * 1024 * -2 * (Risultato: -2147483648 in C2: 1000 0000 0000 0000 0000 0000 0000 0000)
1024 1024 * 1024 * 2 * (Risultato: Overflow!)
2147483647 1 + (Risultato: Overflow!)
2147483647 1 - (Risultato: 2147483646 in C2: 0111 1111 1111 1111 1111 1111 1111 1110)
fine
Il codice che ho scritto è il seguente:
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);
void concatena(numPtr *nPtr, short int val);
void newNum(numPtr *nPtr, short int val);
void calcolo(numPtr *nPtr, unsigned short int temp);
void stampa(numPtr *nPtr);
int controlloOverflow (int primo, int secondo, unsigned short int operazione);
void complemento2(int num);
//Variabili globali per controllare concatenazione e overflow
unsigned short int conc = 0;
unsigned short int ov = 0;
//Inizio main
int main()
{
short int temp = 0;
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);
//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
concatena(&nPtr, temp);
}else{ //Oppure creiamo un nuovo elemento in lista
if(negativo == 1){
temp *= -1;
negativo = 0;
}
newNum(&nPtr, temp);
}
}
//Se il valore è un'operazione (+, - o *) chiamiamo la funzione calcolo
else if(temp == 45 || temp == 43 || temp == 42){
calcolo(&nPtr, temp);
}else{//Altrimenti sarà uno spazio e quindi azzariamo conc
conc = 0;
}
}
//Stampiamo il risultato dopo aver analizzato l'espressione
stampa(&nPtr);
}
//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
conc = 1;
return;
}
//Funzione per la concatenazione
void concatena(numPtr *nPtr, short int val){
//Inizializziamo i puntatori e le variabili necessarie
numPtr corrPtr = *nPtr;
numPtr precPtr = NULL;
int temp = 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;
}
//Funzione per il calcolo che svolge l'operazione con gli ultimi 2 numeri in lista
void calcolo(numPtr *nPtr, unsigned short int temp){
numPtr corrPtr = *nPtr;
numPtr precPtr = NULL;
while(corrPtr->nextPtr != NULL){
precPtr = corrPtr;
corrPtr = corrPtr->nextPtr;
}
//Chiamo la funzione che controlla l'overflow e effettua l'operazione
precPtr->numero = controlloOverflow(precPtr->numero, corrPtr->numero, temp);
precPtr->nextPtr = NULL;
free(corrPtr);//Liberiamo in nodo che non ci serve più
return;
}
//Funzione per la stampa del valore finale e conversione in c2
void stampa(numPtr *nPtr){
//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 il controllo dell'overflow
int controlloOverflow (int primo, int secondo, unsigned short int operazione){
int temp = 0;
//Controllo overflow moltiplicazione
if(operazione == 42){
if(primo == 0 || secondo == 0){//Se abbiamo uno "0" allora la moltiplicazione farà 0
return 0;
}
if(primo>0){
if(secondo>0){
if(primo > (temp = primo*secondo) ){//Se i 2 numeri sono > 0 e temp < primo allora abbiamo overflow
ov = 1;
}
}else{//Primo > 0 e secondo < 0
if(primo < (temp = 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 < (temp = primo*secondo)){//Se primo < operazione allora abbiamo overflow
ov = 1;
}
}else{//Anche secondo minore di 0
if(primo > (temp = primo*secondo) ){//Se primo > operazione allora overflow
ov = 1;
}
}
}
}
//Controllo overflow somma
else if(operazione == 43){
//Se l'operazione è una somma e uno dei due valori è 0 allora restituiamo l'altro valore
if(primo == 0){
return secondo;
}else if(secondo == 0){
return primo;
}
if(primo>0){
if(secondo>0){//Primo e secondo > 0
if(primo > (temp = primo + secondo)){//Se primo > somma allora overflow
ov = 1;
}
}
}else{
if(secondo > 0){//Eseguiamo l'operazione perchè non può esserci overflow
temp = primo + secondo;
}else{
if(primo < (temp = primo + secondo)){//Se sec < 0 e primo < somma allora overflow
ov = 1;
}
}
}
}
//Controllo overflow sottrazione
else if(operazione == 45){
//Nella sottrazione, se il secondo valore è 0 possiamo ritornare direttamente il primo
if(secondo == 0){
return primo;
}
if(primo >= 0){
if(secondo>0){//Primo e secondo > 0 eseguiamo sottrazione
temp = primo - secondo;
}else{//Secondo minore 0 controlliamo overflow
if(primo >= (temp = primo - secondo)){
ov = 1;
}
}
}else{
if(secondo >= 0){//Primo >= 0, secondo < 0 controlliamo overflow
if(primo < (temp = primo - secondo)){
ov = 1;
}
}else{//Secondo < 0 eseguiamo sottrazione perchè non può essere overflow
temp = primo - secondo;
}
}
}
return temp;
}
//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");
}