Задача (придумал сам): реализовать слегка навороченный стэк и стандартные арифметические операции (+ / * -) Так как писал исключительно для себя, не стал делать файл .h и документацию. На, если надо, могу расписать, что к чему.
Знающих людей прошу посмотреть приложенный исходник и высказать конструктивную критику, так как сам я не программист, не учусь на программиста и не работаю в этой сфере, по-этому спросить по существу некого.
P.S. компилируется : gcc -Wall -g stack.c -lm
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <float.h>
#include <math.h>
#include <ctype.h>
#define STACK_INIT 1024
#define STACK_ADD 1024
#define BUFFER_INIT 4096
#define BUFFER_ADD 4096
enum type_expression {type_char, type_string, type_double};
struct stack_atom
{
int type_data;
int buffer_offset;
};
typedef struct stack_atom s_atom;
s_atom *stack;
char *data_buffer;
ptrdiff_t stack_size, top_element, buffer_size, buffer_top;
void stack_init(void)
{
stack_size = STACK_INIT;
buffer_size = BUFFER_INIT;
if(!(stack = (s_atom*)malloc(stack_size * sizeof(s_atom))))
{
fputs("ERR : Cannot initialize stack\n", stdout);
exit(1);
}
if(!(data_buffer = (char*)malloc(buffer_size * sizeof(char))))
{
fputs("ERR : Cannot initialize buffer\n", stdout);
exit(2);
}
top_element = 0;
buffer_top = 0;
}
void check_push(int add)
{
if(top_element == stack_size)
{
stack_size += STACK_ADD;
if(!(stack = (s_atom*)realloc(stack, sizeof(s_atom) * stack_size)))
{
fputs("ERR : Cannot reallocate stack\n", stdout);
exit (3);
}
}
if(buffer_top + add >= buffer_size)
{
buffer_size += BUFFER_ADD + add;
if(!(data_buffer = (char*)realloc(data_buffer, sizeof(char) * buffer_size)))
{
fputs("ERR : Cannot reallocate data buffer\n", stdout);
exit(4);
}
}
}
void push_char(char c)
{
check_push(sizeof(char));
stack[top_element].type_data = type_char;
stack[top_element].buffer_offset = buffer_top;
*(data_buffer + buffer_top) = c;
++buffer_top;
++top_element;
}
void push_double(double n)
{
check_push(sizeof(double));
stack[top_element].type_data = type_double;
stack[top_element].buffer_offset = buffer_top;
*((double *)(data_buffer + buffer_top)) = n;
buffer_top += sizeof(double);
++top_element;
}
void push_string(char* str)
{
int length = strlen(str);
check_push(length + 1);
stack[top_element].type_data = type_string;
stack[top_element].buffer_offset = buffer_top;
strncpy ((data_buffer + buffer_top), str, length);
data_buffer[buffer_top + length + 1] = 0;
buffer_top += length + 1;
++top_element;
}
void push(char *data)
{
double dbl;
if(data[1] == '\0') //special case;
{
if(isdigit(data[0]))
{
push_double((double)(data[0] - '0'));
return;
}
push_char(data[0]);
return;
}
else if((dbl = atof(data)) != 0.0)
{
push_double(dbl);
return;
}
else
push_string(data);
}
void print_object(int element)
{
switch(stack[element].type_data)
{
case type_char:
printf("%c ", (char)(*(data_buffer + stack[element].buffer_offset)));
break;
case type_double:
printf("%e ", *((double *)(data_buffer + stack[element].buffer_offset)));
break;
case type_string:
printf("%s ", (data_buffer + stack[element].buffer_offset));
}
}
void binary_operation(char operation)
{
double op1, op2;
if((stack[top_element - 1].type_data == type_string) ||
(stack[top_element - 2].type_data == type_string))
{
puts("WARN: Operations + - * / not work with strings");
return;
}
if(stack[top_element - 1].type_data == type_char)
op1 = (double)((char)(*(data_buffer + stack[top_element - 1].buffer_offset)));
else
op1 = (double)(*((double *)(data_buffer + stack[top_element - 1].buffer_offset)));
if(stack[top_element - 2].type_data == type_char)
op2 = (double)((char)(*(data_buffer + stack[top_element - 2].buffer_offset)));
else
op2 = (double)(*((double *)(data_buffer + stack[top_element - 2].buffer_offset)));
switch(operation)
{
case '+':
op1 += op2;
break;
case '-':
op1 -= op2;
break;
case '*':
op1 *= op2;
break;
case '/':
if(fabs(op2) <= DBL_EPSILON*fmax(fabs(op2), 0))
{
puts("WARN: Division by zero");
return;
}
op1 /= op2;
}
top_element -= 2;
buffer_top = stack[top_element].buffer_offset;
push_double(op1);
}
void main_loop(void)
{
char command[256];
size_t temp;
while(1)
{
scanf("%255s", command);
if(!command[1])
{
switch(command[0])
{
case '+':
case '-':
case '*':
case '/':
if(top_element < 2)
{
puts("WARN: Not enough elements");
continue;
}
binary_operation(command[0]);
continue;
case '.':
if(!top_element)
{
puts("WARN: Stack empty");
continue;
}
--top_element;
buffer_top = stack[top_element].buffer_offset;
print_object(top_element);
continue;
case '^':
temp = top_element;
while(temp)
print_object(--temp);
continue;
case '$':
temp = 0;
while(temp < top_element)
print_object(temp++);
continue;
default:
push(command);
continue;
}
}
else if(!strncmp(command, "exit", 255))
exit(0);
else if(!strncmp(command, "obj", 255))
{
printf("%td ", top_element);
continue;
}
else if(!strncmp(command, "max_obj", 255))
{
printf("%td ", stack_size);
continue;
}
else if(!strncmp(command, "data", 255))
{
printf("%td ", buffer_top);
continue;
}
else if(!strncmp(command, "max_data", 255))
{
printf("%td ", buffer_size);
continue;
}
else
push(command);
}
}
int main(int argc, char *argv[])
{
stack_init();
main_loop();
return 0;
}