Skip to content

Instantly share code, notes, and snippets.

@yosida95
Created March 7, 2013 16:52
Show Gist options
  • Select an option

  • Save yosida95/5109599 to your computer and use it in GitHub Desktop.

Select an option

Save yosida95/5109599 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/Xlocale.h>
#define WINDOW_WIDTH 520
#define WINDOW_HEIGHT 520
#define PLOT_COUNT 511
struct Node{
char expression[255];
struct Node *left;
struct Node *right;
};
void remove_spaces(char *string){
char *source = string,
*result = string;
while(*source != '\0'){
if(*source == ' '){
source++;
}else{
*(result++) = *(source++);
}
}
*result = '\0';
}
int remove_bracket(char *string){
int length = strlen(string);
int indent = 0,
i;
if(string[0] == '(' && string[length - 1] == ')'){
for(i = 0; i < length - 2; ++i){
string[i] = string[i + 1];
}
string[length - 2] = '\0';
return 0;
}else{
for(i = 0; i < length; ++i){
switch(string[i]){
case '(':
indent++;
break;
case ')':
indent--;
break;
}
}
if(indent != 0){
printf("UNBALANCED BRUCKET\n");
return 1;
}
}
}
int get_lowest_operator(char *string){
int nest = 0,
lowest_position = 0,
priority = 0,
i;
int position = -1;
for(i = 0; i < strlen(string); ++i){
switch(string[i]){
case '+':
case '-':
priority = 3;
break;
case '*':
case '/':
priority = 2;
break;
case '^':
priority = 1;
break;
case '(':
nest++;
continue;
case ')':
nest--;
continue;
default:
continue;
}
if(nest == 0 && priority >= lowest_position){
position = i;
lowest_position = priority;
}
}
return position;
}
void strncpy_ext(char *target, char *source, int n){
int i,
got_null = 0;
for(i = 0; i < n; ++i){
if(got_null == 1){
target[i] = '\0';
}else{
if(source[i] == '\0'){
got_null = 1;
}
target[i] = source[i];
}
}
if(got_null == 0){
target[n] = '\0';
}
}
void free_node(struct Node *node){
if(node != NULL){
free_node(node->left);
free_node(node->right);
free(node);
}
}
struct Node *reserve_node(struct Node *node){
node = (struct Node *) malloc(sizeof(struct Node));
if(node == NULL){
printf("MALLOC ERROR\n");
exit(EXIT_FAILURE);
}
return node;
}
int parse(struct Node *root){
int position, length, i;
struct Node *left, *right;
remove_bracket(root->expression);
length = strlen(root->expression);
position = get_lowest_operator(root->expression);
if(position < 0){
root->left = NULL;
root->right = NULL;
return 0;
}
root->left = reserve_node(left);
strncpy_ext(root->left->expression, root->expression, position);
parse(root->left);
root->right = reserve_node(right);
strncpy_ext(root->right->expression, root->expression + position + 1,
length - position - 1);
parse(root->right);
root->expression[0] = root->expression[position];
root->expression[1] = '\0';
return 0;
}
float string_to_float(char *target){
int i,
length = strlen(target);
float result = 0.0;
for(i = 0; i < length; ++i){
if(target[i] >= 0x30 && target[i] <= 0x39){
result += ((float)(unsigned char)(target[i] - '0')) * (float)pow(10, length - i - 1);
}else{
printf("INVALID EXPRESSION\n");
exit(EXIT_FAILURE);
}
}
return result;
}
void _exec_calc(struct Node *node, float x_value,
float *result, int *stack_length){
if (node->left){
_exec_calc(node->left, x_value, result, stack_length);
}
if (node->right){
_exec_calc(node->right, x_value, result, stack_length);
}
switch(*node->expression){
case '+':
result[(*stack_length) - 2] = result[(*stack_length) - 2]
+ result[(*stack_length) - 1];
--(*stack_length);
break;
case '-':
result[(*stack_length) - 2] = result[(*stack_length) - 2]
- result[(*stack_length) - 1];
--(*stack_length);
break;
case '*':
result[(*stack_length) - 2] = result[(*stack_length) - 2]
* result[(*stack_length) - 1];
--(*stack_length);
break;
case '/':
result[(*stack_length) - 2] = result[(*stack_length) - 2]
/ result[(*stack_length) - 1];
--(*stack_length);
break;
case '^':
result[(*stack_length) - 2] = pow(
result[(*stack_length) - 2], result[(*stack_length) - 1]
);
--(*stack_length);
break;
case 'x':
result[(*stack_length)++] = x_value;
break;
default:
result[(*stack_length)++] = string_to_float(node->expression);
break;
}
}
float exec_calc(struct Node *node, float x_value){
float result[255];
int counter = 0;
_exec_calc(node, x_value, result, &counter);
return result[0];
}
void get_points(char *expression, XPoint *result){
struct Node *tree;
float i;
int j;
float center_x = (float) WINDOW_WIDTH / 2,
center_y = (float) WINDOW_HEIGHT / 2;
float max_x_value = ((float)(PLOT_COUNT / 2)) / 10.0;
float min_x_value = -1.0 * max_x_value;
tree = reserve_node(tree);
strcpy(tree->expression, expression);
if(parse(tree) < 0){
printf("INVALID EXPRESSION\n");
exit(EXIT_FAILURE);
}
for(i = min_x_value, j = 0; i <= max_x_value; i += 0.1, ++j){
result[j].x = (short) center_x + (i * 10.0);
// Y coordinate is reversed in XWindow
result[j].y = (short) center_y - (exec_calc(tree, i) * 10.0);
}
free_node(tree);
}
void get_expression(char *expression){
printf("\
GraphRenderer\n\
\n\
* Operator Guide *\n\
add - +\n\
sub - -\n\
mul - *\n\
div - /\n\
pow - ^\n\
\n\
* ATTENTION *\n\
YOU CAN USE ONLY A DECIMAL INTEGER. IF YOU WANT TO ENTER A DECIMAL FRACTION, YOU HAVE TO ENTER IT AS A FRACTIONAL EXPRESSION WITH BRACKETS.\n\
\n");
printf("y = ");
scanf("%[^\n]", expression);
remove_spaces(expression);
}
int main(){
Display *dpy;
XTextProperty win_name;
Window top, quit;
GC gc;
XEvent event;
char expression[255];
XPoint points[ PLOT_COUNT ];
get_expression(expression);
get_points(expression, points);
dpy = XOpenDisplay(NULL);
if(dpy == NULL){
printf("Couldn't connect to XServer\n");
return 1;
}
top = XCreateSimpleWindow(
dpy, RootWindow(dpy, 0), 0, 0,
WINDOW_WIDTH, WINDOW_HEIGHT, 1, BlackPixel(dpy, 0), WhitePixel(dpy, 0)
);
win_name.value = "GraphRenderer";
win_name.encoding = XA_STRING;
win_name.format = 8;
win_name.nitems = strlen(win_name.value);
XSetWMName(dpy, top, &win_name);
gc = XCreateGC(dpy, top, 0, 0);
quit = XCreateSimpleWindow(
dpy, top, WINDOW_WIDTH - 40 - 2 * 2 - 5, 5,
40, 20, 1, BlackPixel(dpy, 0), WhitePixel(dpy, 0)
);
XMapSubwindows(dpy, top);
XMapWindow(dpy, top);
XFlush(dpy);
XSelectInput(dpy, top, ExposureMask);
XSelectInput(
dpy, quit, ButtonPressMask | EnterWindowMask | LeaveWindowMask
);
while(1){
XNextEvent(dpy, &event);
switch(event.type){
case Expose:
if(event.xexpose.count == 0){
// x-axis
XDrawLine(dpy, top, gc, 0, WINDOW_HEIGHT / 2, WINDOW_WIDTH, WINDOW_HEIGHT / 2);
XDrawString(
dpy, top, gc,
WINDOW_WIDTH - 10, WINDOW_HEIGHT / 2 - 10, "x", 1
);
// y-axis
XDrawLine(dpy, top, gc, WINDOW_WIDTH / 2, 0, WINDOW_WIDTH / 2, WINDOW_HEIGHT);
XDrawString(
dpy, top, gc,
WINDOW_WIDTH / 2- 10, 10, "y", 1
);
// plots
XDrawPoints(dpy, top, gc, points, PLOT_COUNT, CoordModeOrigin);
// quit button
XDrawString(dpy, quit, gc, 8, 15, "Quit", 4);
XFlush(dpy);
}
break;
case ButtonPressMask:
// on quit button pressed
XFreeGC(dpy, gc);
XDestroyWindow(dpy, quit);
XDestroyWindow(dpy, top);
XCloseDisplay(dpy);
return 0;
case EnterNotify:
// quit button onmouse
XSetWindowBorderWidth(dpy, quit, 2);
XFlush(dpy);
break;
case LeaveNotify:
// quit button onunmouse
XSetWindowBorderWidth(dpy, quit, 1);
XFlush(dpy);
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment