All pastes #877825 Raw Edit

Anonymous

public text v1 · immutable
#877825 ·published 2008-01-29 11:48 UTC
rendered paste body
                                                                  
                                                                     
                                                                     
                                             
/* 
program kalkulacka - pocitanie v reverznej polskej notacii s neobmedzene velkymi cislami
prikazy: + - * / ^(=mocnina) p (=vypis vysledku)
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Cislo{
	size_t dlzka;
	char znam;//znamienko
	int* num;
	struct Cislo* next;
};

//deklaracie dolezitych funkcii
void scitaj(struct Cislo** zasobnik);
void odcitaj(struct Cislo** zasobnik,int nemaz);
void nasob(struct Cislo** zasobnik);
void del(struct Cislo** zasobnik);
void mocnina(struct Cislo** zasobnik);

void dosla_pamat(void)
{
	fprintf(stderr,"nedostatok pamate!");
	abort();
}

int char2int(int znak)
{
	/*pride mi pomerne zbytocne pouzivat atoi s jej obmedzeniami ako nutnost zistovat ci cislo nebolo 0
	a prerabanim char-u na string
	*/
	switch (znak)
	{
	
	case '0':
		return 0;
		break;
	case '1':
		return 1;
		break;
	case '2':
		return 2;
	case '3':
		return 3;
		break;
	case '4':
		return 4;
		break;
	case '5':
		return 5;
		break;
	case '6':
		return 6;
		break;
	case '7':
		return 7;
		break;
	case '8':
		return 8;
	case '9':
		return 9;
		break;
	default:
		return -1;
	}
}

int zisti_vacsie(const struct Cislo *c1,const struct Cislo* c2)
/*pracuje s absolutnymi hodnotami cisel.
vracia 1 ak je 1.cislo vacsie v abs.hodnote alebo 2.ak je vacsie 2.cislo, 0 ak su zhodne*/
/*predpoklada sa ze obe cisla su kladne*/
{
	size_t dlzka1,dlzka2;
	size_t i1=0,i2=0;
	dlzka1=c1->dlzka;
	dlzka2=c2->dlzka;
	while (c1->num[i1]==0) i1++;
	while (c2->num[i2]==0) i2++;
	if (dlzka1-i1>dlzka2-i2) return 1;
	else if (dlzka1-i1<dlzka2-i2) return 2;
	else
	{
		while((dlzka1-i1)>0)
		{
			if (c1->num[i1]>c2->num[i2]) return 1;
			else if (c1->num[i1]<c2->num[i2]) return 2;
			else
			{
				i1++;
				i2++;
			}
		}
		return 0;//ak dojde f-cia az sem tak su obe cisla rovnake
	}
}


void odcitaj(struct Cislo** zasobnik,int nemaz)
//parameter nemaz je skoro vzdy 0.ak nie je,to sa vyuzije pri deleni,
//vtedy sa vysledok vlozi do zasobnika namiesto cis1 a cis2 ostane na svojom mieste kvoli usetreniu pamate
{
	struct Cislo *cis1,*cis2,*vysledok;
	if (!(*zasobnik)) printf("prazdny zasobnik!");
	else if (!(*zasobnik)->next) printf("iba jedno cislo na zasobniku!");
	else
	{
		cis2=(*zasobnik);
		cis1=(*zasobnik)->next;
		if (cis2->znam=='+' && cis1->znam=='-')
		{
			cis2->znam='+';
			scitaj(zasobnik);//scita a nastavi znamienko -
		}
		else if(cis2->znam=='-'&&cis1->znam=='+')
		{
			cis2->znam='+';
			scitaj(zasobnik);
		}
		else if(cis1->znam=='-'&&cis2->znam=='-')//prehodit a odcitat
		{
			cis1->znam='+';
			cis2->znam='+';
			cis2->next=cis1->next;
			cis1->next=cis2;
			(*zasobnik)=cis1;
			odcitaj(zasobnik,0);
		}
		else
		{
			int vacsie=zisti_vacsie(cis1,cis2);
			if (!vacsie)
			{
				free(cis2->num);
				free(cis2);
				cis1->dlzka=1;
				free(cis1->num);
				cis1->num=malloc(sizeof(int));
				if (!cis1->num) dosla_pamat();
				cis1->num[0]=0;
				(*zasobnik)=cis1;
				
			}
			else if (vacsie==2)//ak je druhe cislo vacsie,odcita sa 1. od 2. a znam je - 
			{
				cis2->next=cis1->next;
				cis1->next=cis2;
				(*zasobnik)=cis1;
				cis2->znam='+';
				odcitaj(zasobnik,0);
				(*zasobnik)->znam='-';
			}
			else
			{
				size_t dlzka_vysl;
				size_t dlzka1=cis1->dlzka;
				size_t dlzka2=cis2->dlzka;
				int prenos=0;

				vysledok=malloc(sizeof(struct Cislo));
				if (!vysledok) dosla_pamat();
				vysledok->next=(*zasobnik)->next->next;
				vysledok->znam='+';
				if (dlzka1>dlzka2) dlzka_vysl=dlzka1;
				else dlzka_vysl=dlzka2;
				vysledok->num=malloc(sizeof(int)*dlzka_vysl);
				if (!vysledok) dosla_pamat();
				vysledok->dlzka=dlzka_vysl;
				while(dlzka_vysl>0)
				{
					if (dlzka1>0 &&dlzka2>0)
					{
						if ((cis1->num[dlzka1-1]-(cis2->num[dlzka2-1]+prenos))>-1)
						{
							vysledok->num[dlzka_vysl-1]=(cis1->num[dlzka1-1]-(cis2->num[dlzka2-1]+prenos));
							prenos=0;
						}
						else
						{
							vysledok->num[dlzka_vysl-1]=(10+cis1->num[dlzka1-1]-(cis2->num[dlzka2-1]+prenos));
							prenos=1;
						}

						dlzka_vysl--;
						dlzka1--;
						dlzka2--;
					}
					else if (dlzka1>0 &&dlzka2==0)
					{
						if ((cis1->num[dlzka1-1]-prenos)>-1)
						{
							vysledok->num[dlzka_vysl-1]=(cis1->num[dlzka1-1]-prenos);
							prenos=0;
						}
						else
						{
							vysledok->num[dlzka_vysl-1]=(10+cis1->num[dlzka1-1]-prenos);
							prenos=1;
						}
						dlzka_vysl--;
						dlzka1--;
					}
					else if (dlzka1==0 &&dlzka2>0)
					{
						if ((cis2->num[dlzka2-1]-prenos)>-1)
						{
							vysledok->num[dlzka_vysl-1]=(cis2->num[dlzka2-1]-prenos);
							prenos=0;
						}
						else
						{
							vysledok->num[dlzka_vysl-1]=(10+cis2->num[dlzka2-1]-prenos);
							prenos=1;
						}
						dlzka_vysl--;
						dlzka2--;
					}
					
				}
				free(cis1->num);
				free(cis1);
				if (nemaz)
				{
					cis2->next=vysledok;
					(*zasobnik)=cis2;
				}
				else
				{
					(*zasobnik)=vysledok;
					free(cis2->num);
					free(cis2);
					
				}

			}
		}
		
	}
}

void scitaj(struct Cislo** zasobnik)
{
	struct Cislo* cis1,*cis2,*vysledok;
	if (!(*zasobnik)) printf("prazdny zasobnik!");
	else if (!(*zasobnik)->next) printf("iba jedno cislo na zasobniku!");
	else
	{
		cis1=(*zasobnik);
		cis2=(*zasobnik)->next;
		if (cis2->znam=='-' && cis1->znam=='+')//prehod cisla a odcitaj ich
		{
			cis2->znam='+';
			cis1->next=cis2->next;
			cis2->next=cis1;
			(*zasobnik)=cis2;
			odcitaj(zasobnik,0);
		}
		else if (cis1->znam=='-' &&cis2->znam=='+')
		{
			cis1->znam='-';
			odcitaj(zasobnik,0);
		}
		else
		{
			size_t dlzka_vysl;
			size_t dlzka1=cis1->dlzka;
			size_t dlzka2=cis2->dlzka;
			int prenos=0;

			vysledok=malloc(sizeof(struct Cislo));
			if (!vysledok) dosla_pamat();
			vysledok->next=(*zasobnik)->next->next;
			vysledok->znam='+';
			if (dlzka1>dlzka2) dlzka_vysl=dlzka1;
			else dlzka_vysl=dlzka2;
			if (cis1->num[0]!=0 && cis2->num[0]!=0) dlzka_vysl++; //aby bolo dost miesta na cislo o jednu
															 //cifru dlhsie
			vysledok->num=malloc(sizeof(int)*dlzka_vysl);
			if (!vysledok) dosla_pamat();
			vysledok->dlzka=dlzka_vysl;
			while(dlzka_vysl>0)
			{
				if (dlzka1>0 &&dlzka2>0)
				{
					vysledok->num[dlzka_vysl-1]=(cis1->num[dlzka1-1]+cis2->num[dlzka2-1]+prenos)%10;
					if ((cis1->num[dlzka1-1]+cis2->num[dlzka2-1]+prenos)>9) prenos=1;
					else prenos=0;
					dlzka_vysl--;
					dlzka1--;
					dlzka2--;
				}
				else if (dlzka1>0 &&dlzka2==0)
				{
					vysledok->num[dlzka_vysl-1]=(cis1->num[dlzka1-1]+prenos)%10;
					if ((cis1->num[dlzka1-1]+prenos)>9) prenos=1;
					else prenos=0;
					dlzka_vysl--;
					dlzka1--;
				}
				else if (dlzka1==0 &&dlzka2>0)
				{
					vysledok->num[dlzka_vysl-1]=(cis2->num[dlzka2-1]+prenos)%10;
					if ((cis2->num[dlzka2-1]+prenos)>9) prenos=1;
					else prenos=0;
					dlzka_vysl--;
					dlzka2--;
				}
				else if (dlzka1==0 &&dlzka2==0)
				{
					vysledok->num[dlzka_vysl-1]=prenos;
					dlzka_vysl--;
				}
					
			}
			if (cis1->znam=='-'&&cis2->znam=='-') vysledok->znam='-';
			(*zasobnik)=vysledok;
			free(cis1->num);
			free(cis1);
			free(cis2->num);
			free(cis2);
		}

	}


}

void nasob(struct Cislo** zasobnik)
{
	struct Cislo* cis1,*cis2,*vysledok;
	if (!(*zasobnik)) printf("prazdny zasobnik!");
	else if (!(*zasobnik)->next) printf("iba jedno cislo na zasobniku!");
	else
	{
		cis1=(*zasobnik)->next;
		cis2=(*zasobnik);

		vysledok=malloc(sizeof(struct Cislo));
		if (!vysledok) dosla_pamat();
		vysledok->next=(*zasobnik)->next->next;
		if (cis1->znam!=cis2->znam) vysledok->znam='-';
		else vysledok->znam='+';
		if ((cis1->dlzka==1&&cis1->num[0]==0)||(cis2->dlzka==1&&cis2->num[0]==0))
		{
			vysledok->dlzka=1;
			vysledok->num=malloc(sizeof(int));
			if (!vysledok->num) dosla_pamat();
			vysledok->num[0]=1;
			free(cis1->num);
			free(cis1);
			free(cis2->num);
			free(cis2);
			(*zasobnik)=vysledok;
		}
		if (cis1->dlzka==1&&cis1->num[0]==1)
		{
			free(vysledok->num);
			free(vysledok);
			vysledok=cis2;
			free(cis1->num);
			free(cis1);
			(*zasobnik)=vysledok;
			
		}
		if (cis2->dlzka==1&&cis2->num[0]==1)
		{
			free(vysledok->num);
			free(vysledok);
			vysledok=cis1;
			free(cis2->num);
			free(cis2);
			(*zasobnik)=vysledok;
			
		}
		else
		{
			size_t posun=0;
			char znam=vysledok->znam;
            struct Cislo* tmp;
			size_t i1,i2;
			int prenos=0;
			size_t dlzka=cis1->dlzka;
			dlzka=dlzka+cis2->dlzka-1;
			vysledok->znam='+';

			vysledok->num=malloc(sizeof(int)*dlzka);
			for (i1=0;i1<dlzka;i1++) vysledok->num[i1]=0;
			if (!vysledok->num) dosla_pamat();
			vysledok->dlzka=dlzka;
            for (i2=cis2->dlzka-1;i2+1>0;i2--)
			{
				size_t j;
				
				tmp=malloc(sizeof(struct Cislo));
				if (!tmp) dosla_pamat();
				tmp->next=vysledok;
                tmp->dlzka=cis1->dlzka+1+posun;
				tmp->znam='+';
			    tmp->num=malloc((tmp->dlzka) * sizeof(int));
				if (!tmp->num) dosla_pamat();
				for (j=0;j<tmp->dlzka;j++) tmp->num[j]=0;
				for (i1=cis1->dlzka-1;i1+1>0;i1--)
				{
					tmp->num[i1-posun]=(cis2->num[i2]*cis1->num[i1]+prenos)%10;
					prenos=(cis2->num[i2]*cis1->num[i1]+prenos)/10;
				}
				tmp->num[0]=prenos;
				prenos=0;
				scitaj(&tmp);
				vysledok=tmp;
			}
			vysledok->next=(*zasobnik)->next->next;
			(*zasobnik)=vysledok;
			vysledok->znam=znam;
			free(cis1->num);
			free(cis1);
			free(cis2->num);
			free(cis2);
		}
	}








}
void del(struct Cislo** zasobnik)
{
	struct Cislo* cis1,*cis2,*vysledok,*tmp;
	if (!(*zasobnik)) printf("prazdny zasobnik!");
	else if (!(*zasobnik)->next) printf("iba jedno cislo na zasobniku!");
	else
	{
		int vacsie;
		cis2=(*zasobnik);
		cis1=(*zasobnik)->next;
		//osetrit delenie 0
		if (cis2->dlzka==1 && cis2->num[0]==0)
		{
			fprintf(stderr,"delenie nulou!");
			abort();
		}
		vacsie=zisti_vacsie(cis1,cis2);
		vysledok=malloc(sizeof(struct Cislo));
		if (!vysledok) dosla_pamat();
		vysledok->next=(*zasobnik)->next->next;
		if (cis1->znam!=cis2->znam) vysledok->znam='-';
		else vysledok->znam='+';
		if (vacsie==0 || vacsie==2)
		{
			vysledok->dlzka=1;
			vysledok->num=malloc(sizeof(int));
			if (!vysledok->num) dosla_pamat();
			if (vacsie==0) vysledok->num[0]=1;
			else vysledok->num[0]=0;

			free(cis1->num);
			free(cis1);
			free(cis2->num);
			free(cis2);
			(*zasobnik)=vysledok;
		}
		else
		{//cis1 je vacsie v abs hodnote
			cis1->znam='+';
			cis2->znam='+';
			vysledok->num=malloc(sizeof(int));
			vysledok->dlzka=1;
			vysledok->num[0]=0;
			vysledok->next=0;
			while (zisti_vacsie(cis1,cis2)==1)
			{
				tmp=malloc(sizeof(struct Cislo));
				if (!tmp) dosla_pamat();
				tmp->num=malloc(sizeof(int));
				if(!tmp->num) dosla_pamat();
				tmp->dlzka=1;
				tmp->num[0]=1;
				tmp->next=vysledok;
				vysledok=tmp;
				scitaj(&vysledok);
				odcitaj(zasobnik,1);
				cis1=(*zasobnik)->next;
                
			}
			vysledok->next=(*zasobnik)->next->next;
			(*zasobnik)=vysledok;
			if (zisti_vacsie(cis1,cis2)==0)
			{
				tmp=malloc(sizeof(struct Cislo));
				if (!tmp) dosla_pamat();
				tmp->num=malloc(sizeof(int));
				if(!tmp->num) dosla_pamat();
				tmp->dlzka=1;
				tmp->num[0]=1;
				tmp->next=vysledok;
				(*zasobnik)=tmp;
				scitaj(zasobnik);
			}
			free(cis1->num);
			free(cis1);
			free(cis2->num);
			free(cis2);
			
			

		}
		
	}
}
void mocnina(struct Cislo** zasobnik)
{
}

void vypis(struct Cislo** zasobnik)
{
	size_t i;
	struct Cislo* tmp;
	if (!*zasobnik) printf("prazdny zasobnik!");
	else
	{
		if ((*zasobnik)->znam=='-') printf("-");
		for (i=0;i<(*zasobnik)->dlzka;++i) printf("%i",(*zasobnik)->num[i]);
		tmp=*zasobnik;
		(*zasobnik)=(*zasobnik)->next;
		free(tmp->num);
		free(tmp);
	}
	printf("\n");
}

int main(void)
{
	int cislo;
	struct Cislo* aktualne=0;
	struct Cislo* zasobnik=0;
	int znak;
	char znamienko=0;

	printf("postfixova kalkulacka\n");
	printf("Zadaj vyraz: ");
	znak=getchar();

	
	while (znak!=EOF)
	{
		if (znak=='\n')
		{
			znak=getchar();
			continue;
		}
		switch (znak)
		{
		case '+':
			znamienko='+';
			break;
		case '-':
			znamienko='-';
			break;
		case 'p':
			vypis(&zasobnik);
			break;
		case '^':
			mocnina(&zasobnik);
			break;
		case '/':
			del(&zasobnik);
			break;
		case '*':
			nasob(&zasobnik);
			break;
		default:
			cislo=char2int(znak);
			if (cislo!=-1){
				aktualne=malloc(sizeof(struct Cislo));
				if (!aktualne) dosla_pamat();
				aktualne->dlzka=1;
				aktualne->znam='+';
				aktualne->num=malloc(sizeof(int)*aktualne->dlzka);
				if (!aktualne->num) dosla_pamat();
				aktualne->num[aktualne->dlzka-1]=cislo;

				aktualne->next=zasobnik;
				zasobnik=aktualne;
				znamienko=0;
			}
			else printf("chybne zadany vstup!\n");
		}
		znak=getchar();
		if (znak==EOF) break;
		if (znak=='\n')
		{
			if (!aktualne && znamienko=='+') scitaj(&zasobnik);
			else if (!aktualne && znamienko=='-') odcitaj(&zasobnik,0);
			znamienko=0;
			if (aktualne) aktualne=0;
		}
		else while (znak!=EOF && znak!='\n')
		{
			cislo=char2int(znak);
			if (cislo!=-1)
			{
				if (!aktualne)
				{
					aktualne=malloc(sizeof(struct Cislo));
					if (!aktualne) dosla_pamat();
					aktualne->dlzka=0;
					aktualne->znam=znamienko;
					aktualne->num=0;
					
					aktualne->next=zasobnik;
					zasobnik=aktualne;
					znamienko=0;
				}
				aktualne->dlzka++;
				aktualne->num=realloc(aktualne->num,(sizeof(int)*aktualne->dlzka));
				if (!aktualne->num) dosla_pamat();
				aktualne->num[aktualne->dlzka-1]=cislo;
			}

			else //cislo==-1 ->zly znak na vstupe
			{
				printf("chybne zadany vstup!");
				if (aktualne){
					zasobnik=aktualne->next;
					//zmazanie aktual.cisla zo zasobnika
					free(aktualne->num);
					free(aktualne);
					aktualne=0;
				}
			}
			
			znak=getchar();
		}
		znamienko=0;
		aktualne=0;
		znak=getchar();

	}


	return 0;
}