Файл infix2postfix.H
#ifndef INFIX2POSTFIX_H
#define INFIX2POSTFIX_H
/* типы лексем: константы, операции, имена переменных */
typedef enum { tt_CONST, tt_OPER, tt_ID } TokenType;
/* виды операций: сложение, вычитание, умножение, деление,
* левая и правая скобки */
typedef enum {op_ADD='+', op_SUB='-', op_MUL='*', op_DIV='/', op_LBR='(', op_RBR=')'} OperType;
/* максимальная длина имени переменной */
#define MAX_ID_LEN 40
/* тип - лексема */
typedef struct {
TokenType ttype;
union Value {
/* с лексемой связано одно из следующих значений */
int inum;
OperType otype;
char id[MAX_ID_LEN + 1];
} tvalue;
int num;
} Token;
//It converts string (s) to array of tokens
//return 0 in case of success
// -1 in case of wrong format of any token
// -2 in case of it can not resize array
int tokenize(const char *s, Token **tokens, int *len);
//For converting from infix form to postfix
//return 0 in case of success
// -1 unknow type of operator
// -2 unknow type of token
// -3 stack is over full
// -4 memory error: cant resize array
int infix2postfix(const Token *infix, int in_len, Token **postfix, int *out_len);
#endif
Файл unit_tests.C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "infix2postfix.h"
#define IN_STR_SIZE 200
char strC[IN_STR_SIZE] = "";
void out_TokensArray(Token **t_array, int *len)
{
memset(strC,0,sizeof(strC)); //erase strC
char strT[IN_STR_SIZE] = "";
for(int i=0; i<(*len); i++)
switch((*t_array)[i].ttype)
{
case tt_CONST:
printf("%d ", (*t_array)[i].tvalue.inum);
sprintf(strT, "%d ", (*t_array)[i].tvalue.inum);
strcat(strC, strT);
break;
case tt_OPER:
printf("%c ", (*t_array)[i].tvalue.otype);
sprintf(strT, "%c ", (*t_array)[i].tvalue.otype);
strcat(strC, strT);
break;
case tt_ID:
printf("%s ", (*t_array)[i].tvalue.id);
sprintf(strT, "%s ", (*t_array)[i].tvalue.id);
strcat(strC, strT);
break;
}
printf("\n");
}
void covert_i2p(const char *s)
{
printf(" ORIGINAL INPUTED STRING: \"%s\"", s);
Token *infix;
int in_len = 0;
switch(tokenize(s, &infix, &in_len))
{
case 0:
printf("\n INFIX: ");
out_TokensArray(&infix, &in_len);
Token *postfix;
int out_len = 0;
switch(infix2postfix(infix, in_len, &postfix, &out_len))
{
case 0:
printf(" POSTFIX: ");
out_TokensArray(&postfix, &out_len);
break;
case -1:
printf("\nError: Unkown type of operator\n");
strcpy(strC, "Error");
break;
case -2:
printf("\nError: Unkown type of token\n");
strcpy(strC, "Error");
break;
case -3:
printf("\nError: Memory error: Stack is over full\n");
strcpy(strC, "Error");
break;
case -4:
printf("\nError: Memory error: Cant resize array\n");
strcpy(strC, "Error");
break;
default:
printf("\nError: Unknown error\n");
strcpy(strC, "Error");
break;
}
free(postfix);
break;
case -1:
printf("\nError: Format of token is incorrect\n");
strcpy(strC, "Error");
break;
case -2:
printf("\nError: Memory error: Cant resize array\n");
strcpy(strC, "Error");
break;
default:
printf("\nError: Unknown error\n");
strcpy(strC, "Error");
break;
}
free(infix);
}
void test(char *headline, char *in_str, char *expect_str)
{
printf("\n%s\n", headline);
covert_i2p(in_str);
printf(" EXPECTED: %s\n", expect_str);
if(strcmp(strC, expect_str) == 0)
printf(" PASSED");
else
printf(" DONT MATCH!!!");
printf("\nNext... press <Enter>\n");
getchar();
}
int main(int argc, char* argv[])
{
printf("\nUnit tests for infix2postfix.h is run\n");
printf(" Press <Enter> for the full test script...\n");
printf(" Input string and press <Enter> if you want to do test with this string...\n");
char s[IN_STR_SIZE];
gets(s);
if(strlen(s) == 0)
{
printf("Test script is running...\n");
//test("", "", " ");
test("Does it understand correct tokens?", "2 + 123 - ( abc * abc123 ) / a1b2c3", "2 123 + abc abc123 * a1b2c3 / - ");
test("Will it be worked correct with spaces/tabs at the begin/end?", " 2 + 7 ", "2 7 + ");
test("Can it work with one token?", "7", "7 ");
test("Will it return error in case of wrong format of token?", "a + 987bcd", "Error");
test("Will it return error in case of unknown operator?", "5 ^ 9", "Error");
test("Some random test 1", "3 + 4 * 2 / ( 1 - 5 )", "3 4 2 * 1 5 - / + ");
test("Some random test 2", "( 1 + 23 * 4 ) * ( 5 - 1 )", "1 23 4 * + 5 1 - * ");
test("Some random test 3", "7 + ( 5 - 2 ) * 4", "7 5 2 - 4 * + ");
test("Some random test 4", "8 / ( 2 + 2 )", "8 2 2 + / ");
test("Some random test 5", "( 8 / ( 2 + 2 ) )", "8 2 2 + / ");
printf("Test script is over\n");
}
else
covert_i2p(s);
printf("\nPress <Enter> for exit");
getchar();
return 0;
}