/* ** Konverzní funkce infix2postfix. ** Ète infixový výraz ze vstupního øetìzce infExpr a generuje ** odpovídající postfixový výraz do výstupního øetìzce (postup pøevodu ** hledejte v pøedná¹kách nebo ve studijní opoøe). Pamì» pro výstupní øetìzec ** (o velikosti MAX_LEN) je tøeba alokovat. Volající funkce, tedy ** pøíjemce konvertovaného øetìzce, zajistí korektní uvolnìní zde alokované ** pamìti. ** ** Tvar výrazu: ** 1. Výraz obsahuje operátory + - * / ve významu sèítání, odèítání, ** násobení a dìlení. Sèítání má stejnou prioritu jako odèítání, ** násobení má stejnou prioritu jako dìlení. Priorita násobení je ** vìt¹í ne¾ priorita sèítání. V¹echny operátory jsou binární ** (neuva¾ujte unární mínus). ** ** 2. Hodnoty ve výrazu jsou reprezentovány jednoznakovými identifikátory ** a èíslicemi - 0..9, a..z, A..Z (velikost písmen se rozli¹uje). ** ** 3. Ve výrazu mù¾e být pou¾it pøedem neurèený poèet dvojic kulatých ** závorek. Uva¾ujte, ¾e vstupní výraz je zapsán správnì (neo¹etøujte ** chybné zadání výrazu). ** ** 4. Ka¾dý korektnì zapsaný výraz (infixový i postfixový) musí být uzavøen ** ukonèovacím znakem '='. ** ** 5. Pøi stejné prioritì operátorù se výraz vyhodnocuje zleva doprava. ** ** Poznámky k implementaci ** ----------------------- ** Jako zásobník pou¾ijte zásobník znakù tStack implementovaný v pøíkladu c202. ** Pro práci se zásobníkem pak pou¾ívejte výhradnì operace z jeho rozhraní. ** ** Pøi implementaci vyu¾ijte pomocné funkce untilLeftPar a doOperation. ** ** Øetìzcem (infixového a postfixového výrazu) je zde my¹leno pole znakù typu ** char, jen¾ je korektnì ukonèeno nulovým znakem dle zvyklostí jazyka C. ** ** Na vstupu oèekávejte pouze korektnì zapsané a ukonèené výrazy. Jejich délka ** nepøesáhne MAX_LEN-1 (MAX_LEN i s nulovým znakem) a tedy i výsledný výraz ** by se mìl vejít do alokovaného pole. Po alokaci dynamické pamìti si v¾dycky ** ovìøte, ¾e se alokace skuteènì zdraøila. V pøípadì chyby alokace vra»te namísto ** øetìzce konstantu NULL. */ char* infix2postfix (const char* infExpr) { char *postExpr = malloc(MAX_LEN * sizeof(char)); unsigned postLen = 0; tStack stack; stackInit(&stack); char tmp; for(unsigned i = 0; (tmp = infExpr[i]) != '='; i++) { switch(tmp) { case '+': case '-': case '*': case '/': // Zpracuj operator doOperation(&stack, tmp, postExpr, &postLen); break; case '(': // Pridaj lavu zatvorku do zasobniku. stackPush(&stack, '('); break; case ')': // Zpracuj pravu zatvorku. untilLeftPar(&stack, postExpr, &postLen); break; default: // Zpracuj hodnotu. // isalnum() if((tmp >= '0' && tmp <='9') || (tmp >= 'a' && tmp <= 'z') || (tmp >= 'A' && tmp <= 'Z')) postExpr[postLen++] = tmp; break; } } while(!stackEmpty(&stack)) { stackTop(&stack, &tmp); postExpr[postLen++] = tmp; stackPop(&stack); } postExpr[postLen++] = '='; postExpr[postLen] = '\0'; return postExpr; }
/* ** Konverzní funkce infix2postfix. ** Ète infixový výraz ze vstupního øetìzce infExpr a generuje ** odpovídající postfixový výraz do výstupního øetìzce (postup pøevodu ** hledejte v pøedná¹kách nebo ve studijní opoøe). Pamì» pro výstupní øetìzec ** (o velikosti MAX_LEN) je tøeba alokovat. Volající funkce, tedy ** pøíjemce konvertovaného øetìzce, zajistí korektní uvolnìní zde alokované ** pamìti. ** ** Tvar výrazu: ** 1. Výraz obsahuje operátory + - * / ve významu sèítání, odèítání, ** násobení a dìlení. Sèítání má stejnou prioritu jako odèítání, ** násobení má stejnou prioritu jako dìlení. Priorita násobení je ** vìt¹í ne¾ priorita sèítání. V¹echny operátory jsou binární ** (neuva¾ujte unární mínus). ** ** 2. Hodnoty ve výrazu jsou reprezentovány jednoznakovými identifikátory ** a èíslicemi - 0..9, a..z, A..Z (velikost písmen se rozli¹uje). ** ** 3. Ve výrazu mù¾e být pou¾it pøedem neurèený poèet dvojic kulatých ** závorek. Uva¾ujte, ¾e vstupní výraz je zapsán správnì (neo¹etøujte ** chybné zadání výrazu). ** ** 4. Ka¾dý korektnì zapsaný výraz (infixový i postfixový) musí být uzavøen ** ukonèovacím znakem '='. ** ** 5. Pøi stejné prioritì operátorù se výraz vyhodnocuje zleva doprava. ** ** Poznámky k implementaci ** ----------------------- ** Jako zásobník pou¾ijte zásobník znakù tStack implementovaný v pøíkladu c202. ** Pro práci se zásobníkem pak pou¾ívejte výhradnì operace z jeho rozhraní. ** ** Pøi implementaci vyu¾ijte pomocné funkce untilLeftPar a doOperation. ** ** Øetìzcem (infixového a postfixového výrazu) je zde my¹leno pole znakù typu ** char, jen¾ je korektnì ukonèeno nulovým znakem dle zvyklostí jazyka C. ** ** Na vstupu oèekávejte pouze korektnì zapsané a ukonèené výrazy. Jejich délka ** nepøesáhne MAX_LEN-1 (MAX_LEN i s nulovým znakem) a tedy i výsledný výraz ** by se mìl vejít do alokovaného pole. Po alokaci dynamické pamìti si v¾dycky ** ovìøte, ¾e se alokace skuteènì zdraøila. V pøípadì chyby alokace vra»te namísto ** øetìzce konstantu NULL. */ char* infix2postfix (const char* infExpr) { char *postExpr; unsigned postLen = 0; int stringSize; tStack *s; // alokace vystupniho retezce if ((postExpr = (char *) malloc(MAX_LEN)) == NULL) { return NULL; } // alokace zasobniku if ((s = malloc(sizeof(char *) * STACK_SIZE)) == NULL) { free(postExpr); return NULL; } // inicializace zasobniku stackInit(s); // zjisteni delky retezce stringSize = snprintf(NULL, 0, "%s", infExpr); // zpracovani retezce for (unsigned i = 0; i <= stringSize; i++) { if ( (infExpr[i] >= '0' && infExpr[i] <= '9') || (infExpr[i] >= 'A' && infExpr[i] <= 'Z') || (infExpr[i] >= 'a' && infExpr[i] <= 'z') ) { // nacteni alfanumerickeho znaku do vystupniho retezce postExpr[postLen] = infExpr[i]; postLen++; } else if (infExpr[i] == '(') { // je-li zpracovana polozka leva zavorka, umistim na // vrchol zasobniku stackPush(s, infExpr[i]); } else if (infExpr[i] == ')') { // Je-li zpracovávanou polo¾kou pravá závorka, // odebíram z vrcholu zasobniku polo¾ky a dávam // na konec výstupního øetìzce a¾ narazim na levou // závorku. untilLeftPar(s, postExpr, &postLen); } else if (infExpr[i] == '=') { // Je-li zpracovávanou polo¾kou '=', pak postupnì // odstraòuju prvky z vrcholu zásobníku a pøidávam na // konec øetìzce, a¾ se zásobník zcela vyprázdní. // Na konec se pøidá rovnítko, jako omezovaè výrazu. while (!stackEmpty(s)) { stackTop(s, &postExpr[postLen]); postLen++; stackPop(s); } postExpr[postLen] = '='; postLen++; postExpr[postLen] = '\0'; } else { // zpracovani operatoru doOperation(s, infExpr[i], postExpr, &postLen); } } free(s); return postExpr; }