더하기 빼기 곱하기 나누기 그리고 나머지 연산과 괄호 연산까지 가능한 버전임, 원래는 수식 연산기에 걸 맞도록 a-z 문자 연산과 log sprt 같은것도 지원하려고 했었지만 여러가지 이유로 못했음
이번에 추가된 메인 부분 ( 스파게티 코드 주의 )
주석처럼 이 함수를 보면 희망을 버리는게 맞음
// 이 함수를 보는자, 희망을 버려라!
char* sum(char* input) {
Array* array = NULL;
{
Node* node = NULL;
char* buf = str_cpy(input);
char swap_buffer = '\0';
char* buf_f = buf;
char* buf_p = buf;
while(*buf_p) {
switch( *buf_p ) {
case '+': case '-': case '*': case '/': case '%': case '(': case ')': SPS(buf_p, 1);
break;
case '\0':
continue;
break;
default:
if('0' <= *buf_p && *buf_p <= '9') while( *buf_p && ('0' <= *buf_p && *buf_p <= '9') ) { SPS(buf_p, 1); }
else {
SPS(buf_p, 1);
buf_f = buf_p;
continue;
}
break;
}
swap_buffer = *buf_p;
*buf_p = '\0';
char* str = str_cpy(buf_f);
*buf_p = swap_buffer;
{
Node* r = Node_push(node, str);
if(r == NULL) {
node = Node_free(node);
return NULL;
}
node = r;
}
buf_f = buf_p;
}
free(buf);
array = NodeToArray(node);
}
if(array == NULL) return NULL;
char* symarr[] = {
"*/%", "+-", ""
};
Node* bracket_node = NULL;
for(int point = 0; point <= array->c; SPP(point)){
int start = 0;
if(point == array->c) {
goto GOTO_FUNCTION;
} else switch(*(char*)array->d[point]) {
case '(':
{
int* d = malloc(sizeof(int));
if(!d) goto GOTO_ERROR;
*d = point;
Node* r = Node_push(bracket_node, d);
if(!r) {
free(d);
goto GOTO_ERROR;
}
bracket_node = r;
}
break;
case ')':
{
int d;
if(bracket_node) {
Node* n = bracket_node;
bracket_node = n->n;
d = *(int*)n->d;
free(n->d);
free(n);
} else {
bracket_node = Node_free(bracket_node);
goto GOTO_ERROR;
}
for(int j = d, h = PP(d); h < array->c; SPP(j), SPP(h)) {
array->d[j] = array->d[h];
}
SSS(array->c);
SSS(point);
start = d;
goto GOTO_FUNCTION;
GOTO_RETURN:
free(array->d[point]);
for(int i = point, j = PP(point); j < array->c; SPP(j), SPP(i)) {
array->d[i] = array->d[j];
}
SSS(array->c);
SSS(point);
continue;
}
break;
case '\0':
GOTO_FUNCTION:
{
//printf("%d pc: %d %d %d \n", __LINE__, start, point, array->c);
char** symarr_ptr = symarr;
while(**symarr_ptr) {
for(int i = start; i <= point && i < array->c; SPP(i)) {
char* sa_pp = *symarr_ptr;
while(*sa_pp) {
if( *(char*)(array->d[i]) == *sa_pp) break;
SPS(sa_pp, 1);
} if ( *sa_pp && 0 < i && PP(i) < array->c ) {
int flag = isNumber(array->d[SS(i)]) << 1 | isNumber(array->d[PP(i)]);
if(flag == 3) {
Num a, b, c; num_read(a, array->d[SS(i)]), num_read(b, array->d[PP(i)]);
switch (*sa_pp) {
case '+':
c_add(c, a, b);
break;
case '-':
c_sub(c, a, b);
break;
case '*':
c_mul(c, a, b);
break;
case '/':
c_div(c, a, b, nullnum);
break;
case '%':
c_div(nullnum, a, b, c);
break;
}
char* r = num_strdup(c);
if(!r) goto GOTO_ERROR;
free(array->d[SS(i)]), free(array->d[i]), free(array->d[PP(i)]);
array->d[SS(i)] = r;
for( int j = i, h = PP(PP(i)); h < array->c; SPP(j), SPP(h) ) {
array->d[j] = array->d[h];
}
array->c = SS(SS(array->c));
point = SS(SS(point));
SSS(i);
}
}
}
SPS(symarr_ptr, 1);
}
if(point < array->c) goto GOTO_RETURN;
break;
}
}
}
//for(int i = 0; i < array->c; SPP(i)) printf("%s ", array->d[i]);
if( '0' <= *(char*)array->d[0] && *(char*)array->d[0] <= '9' ); else goto GOTO_ERROR;
char* buf = str_cpy(array->d[0]);
array = Array_free(array);
return buf;
GOTO_ERROR:
array = Array_free(array);
return NULL;
}
goto 구문 사용은 물론 함수로 분리해야 하는 기능들까지 덕지덕지 안에서 구동해버리는 함수임, 만약에 후임이 이 함수를 받는다면 밤길 조심해야 할 정도
에딧도 이 함수를 보면 발작을 하는지, system_scanf만 만들어도 작동이 멈추더라, 원래도 무겁지만 그래도 잘 작동하는 것이... 최적화 이슈가...
원래는 이전글이랑 코드가 동일했었는데, 몇번 갈고 닦아서 다른 부분이 많아짐, 대표적으로 div가 있음
그리고 system_printf가 출력이라면 system_scanf은 입력임, 이번에 생긴 함수인데 잘 작동하는지는 모르겠다.
NS가 8이면 쾌적한데 32로 가면 연산 능력이 많이 딸림, 비효율적인 코드도 있겠지만 BCD가 왜 존재하는지 뼈저리게 깨닫게 해주더라
참고로 기본적으로는 음수 연산을 고려하지 않음
다른 부분이 많아졌으니 그냥 전문
#include <stdio.h>
#define NS 8
#define NUMITEM unsigned long long
typedef NUMITEM Num[NS];
static Num nullnum;
#define cfun(name) void c_##name (Num r, Num a, Num b)
cfun(add); cfun(sub); cfun(mul); void c_div(Num, Num, Num, Num);
int system_printf(char* format, ...);
int num_read(Num r, char* value);
unsigned long long PP(unsigned long long i) {
for(unsigned long long n = 1, w = ~0ULL; n; n <<= 1, w <<= 1) {
if(i & n); else {
i |= n;
i &= w;
return i;
}
}
return ~0;
}
unsigned long long SS(unsigned long long i) {
for(unsigned long long n = 1, w = ~0ULL; n; n <<= 1, w <<= 1) {
if(i & n) {
i |= ~w;
i &= ~n;
return i;
}
}
return ~0;
}
#define SPP(i) (i = PP(i))
#define SSS(i) (i = SS(i))
void c_cpy(Num b, Num n) {
for(int i = 0; i < NS; SPP(i)) {
b[i] = n[i];
}
}
void c_clear(Num n) {
Num b = {0};
c_cpy(n, b);
}
cfun(add) {
unsigned long long crad[3];
crad[2] = 0;
#define getIndexBit(n) (n[crad[1]] & crad[0])
#define R r[crad[1]]
#define C (crad[2])
for(crad[1] = 0; crad[1] < NS; SPP(crad[1])) for(crad[0] = 1; crad[0]; crad[0] = crad[0] << 1) {
unsigned long long A = !!getIndexBit(a);
unsigned long long B = !!getIndexBit(b);
R &= ~crad[0];
R |= (A^B^C ? crad[0] : 0);
C = A&B|B&C|C&A;
}
#undef C
#undef R
#undef getIndexBit
}
cfun(sub) {
unsigned long long crad[3];
crad[2] = 0;
#define getIndexBit(n) (n[crad[1]] & crad[0])
#define R r[crad[1]]
#define C (crad[2])
for(crad[1] = 0; crad[1] < NS; SPP(crad[1])) for(crad[0] = 1; crad[0]; crad[0] = crad[0] << 1) {
unsigned long long A = !!getIndexBit(a);
unsigned long long B = !!getIndexBit(b);
R &= ~crad[0];
R |= (A^B^C ? crad[0] : 0);
C = (!A)&B|B&C|C&(!A);
}
#undef C
#undef R
#undef getIndexBit
}
unsigned long long c_shift_left(Num n) {
unsigned long long c = 0, c_b = 0;
for(int i = 0; i < NS; SPP(i)) {
c_b = n[i] >> 63;
n[i] <<= 1;
n[i] |= c;
c = c_b;
}
return c;
}
unsigned long long c_shift_right(Num n) {
unsigned long long c = 0, c_b = 0;
for(int i = SS(NS); 0 <= i; SSS(i)) {
c_b = n[i] & 1;
n[i] >>= 1;
n[i] |= (c << 63);
c = c_b;
}
return c;
}
cfun(mul) {
Num buffer;
c_cpy(buffer, a);
c_clear(r);
for(int i = 0; i < NS; SPP(i)) for(unsigned long long s = 1; s; s <<= 1) {
if(b[i] & s) c_add(r, r, buffer);
c_shift_left(buffer);
}
}
int c_cmp(Num a, Num b) {
for(long long i = SS(NS); 0 <= i; i = SS(i)) {
if(a[i] == b[i]) continue;
if(a[i] > b[i]) return SS(0);
if(a[i] < b[i]) return 1;
}
return 0;
}
void c_div(Num r, Num a, Num b, Num m) {
int index = 0;
Num buffer, buf, point;
c_cpy(buf, a); c_cpy(buffer, b);
c_clear(r); c_clear(point); point[0] = 1;
while( !c_shift_left(buffer) ) c_shift_left(point);
c_shift_right(buffer);
buffer[~PP(~NS)] |= 1ULL << 63;
for(;;) {
int cmp = c_cmp(buffer, buf);
if(cmp == 1 || cmp == 0) c_sub(buf, buf, buffer), c_add(r, r, point);
c_shift_right(buffer); if( c_shift_right(point) ) break;
}
c_cpy(m, buf);
}
int num_len(Num n) {
for(int i = SS(NS); 0 <= i; SSS(i)) if(n[i]) for(int j = SS(16); 0 <= j; SSS(j) ) if((n[i] >> (j<<2)) & 15) for(int h = 3; 0 <= h; SSS(h)) {
if((n[i]>>(j<<2)>>h)&1) return (i<<6) | (j<<2) | h;
}
return SS(0);
}
static int c_dcode_fun(Num r, Num n, int flag) {
Num dcm = {10};
Num rmd;
Num buf;
c_cpy(buf, n);
c_clear(r);
int count = 0;
int max = flag == 1 ? NS : flag == 2 ? NS<<1: NS;
for(int i = 0; i < max; SPP(i)) for(int j = 0; j < (64 >> 2); SPP(j) ) {
c_div(buf, buf, dcm, rmd);
if(!(rmd[0] | buf[0])) break;
r[i] |= (rmd[0] << (j << 2));
SPP(count);
}
return count;
}
int c_dcode(Num r, Num n) {
return c_dcode_fun(r, n, 1);
}
/*
* type r : NUMITEM[NS<<1]
*/
int c_ldcode(NUMITEM* r, Num n) {
return c_dcode_fun(r, n, 2);
}
#define PS(p, i) (&p[i])
#define SPS(p, i) (p = PS(p, i))
#include <malloc.h>
int num_print(Num N) {
NUMITEM n[NS<<1] = {0};
size_t size = c_ldcode(n, N);
char* buffer = (char*)calloc(size, sizeof(char));
if(!buffer) return SS(0);
char* buf_p = buffer;
for(int i = SS(size); 0<=i; SSS(i)) {
*buf_p = (n[i>>4&15] >> ((i&15)<<2) & 15) | 48;
SPS(buf_p, 1);
}
*buf_p = '\0';
buf_p = buffer;
int count;
while(*buf_p == '0') SPS(buf_p, 1);
if(*buf_p == '\0') {
count = printf("%s", "0");
} else {
count = printf("%s", buf_p);
}
free(buffer);
return count;
}
#include <stdarg.h>
int system_printf(char* format, ...) {
va_list list;
va_start(list, format);
size_t size = 0;
while(format[SPP(size)]);
char* buffer = malloc(size);
if(!buffer) return SS(0);
char* buf_p = buffer;
while(*format) {
*buf_p = *format;
SPS(format, 1);
SPS(buf_p, 1);
}
*buf_p = '\0';
buf_p = buffer;
char* buf_pp = buf_p;
int count = 0;
#define count_add(print) { \
Num f = {count};\
Num s = {print}; \
c_add(f, f, s);\
count = f[0];\
}
while(*buf_pp) {
while(*buf_pp != '%') {
SPS(buf_pp, 1);
if(!*buf_pp) break;
}
if(!*buf_pp) {
count_add( printf("%s", buf_p) );
break;
}
*buf_pp = '\0';
count_add(printf("%s", buf_p));
*buf_pp = '%';
switch( *(SPS(buf_pp, 1)) ) {
case '%':
count_add(printf("%c", '%'));
break;
case 'd':
count_add(printf("%d", va_arg(list, int)));
break;
case 'f':
count_add(printf("%f", va_arg(list, double)));
break;
case 's':
count_add(printf("%s", va_arg(list, char*)));
break;
case 'c':
count_add(printf("%c", va_arg(list, int)));
break;
case 'n':
count_add(num_print(va_arg(list, NUMITEM*)));
break;
case '\0':
count_add(printf("%c", '%'));
break;
default:
count_add(printf("%%%c", *buf_pp));
break;
}
if(!*buf_pp) break;
SPS(buf_pp, 1);
buf_p = buf_pp;
}
#undef count_add
va_end(list);
free(buffer);
return count;
}
int num_read(Num r, char* value) {
Num dcm = {10}, buffer, point = {1}, str_0 = {'0'};
const char* start = PS(value, SS(0));
char* val_p = value;
if(!*val_p) return SS(0);
while( val_p[1] ) val_p = &val_p[1];
c_clear(r);
while(start != val_p) {
Num n = {*val_p};
if('0' <= n[0] && n[0] <= '9'); else continue;
c_sub(n, n, str_0);
c_mul(n, n, point);
c_add(r, r, n);
c_mul(point, point, dcm);
//SPS(val_p, SS(0));
val_p--;
}
return 0;
}
char* num_strdup(Num num) {
NUMITEM dn[NS<<1] = {0}; int size = c_ldcode(dn, num);
if(size == 0) {
char* buf = calloc(2, sizeof(char));
if(!buf) return NULL;
buf[0] = '0';
return buf;
}
char* buf = malloc(PP(size));
if(!buf) return NULL;
buf[size] = '\0';
for(int i = SS(size), j = 0; 0<=i; SSS(i), SPP(j)) {
buf[j] = ((dn[(i>>4)] >> ((i&15)<<2)) & 15) | '0';
}
return buf;
}
typedef struct Node {
void* d;
struct Node* n;
} Node;
Node* Node_push(Node* head, void* d) {
Node* node = malloc(sizeof(Node));
if(!node) return NULL;
node->d = d, node->n = head;
return node;
}
Node* Node_free(Node* node) {
if(!node) return NULL;
Node* r = Node_free(node->n);
free(node->d);
free(node);
return r;
}
typedef struct Array {
void** d;
size_t c, s;
} Array;
void* Array_push(Array* arr, void* s) {
arr->d[arr->s] = s;
arr->s = PP(arr->s);
return s;
}
Array* Array_free(Array* arr) {
free(arr->d); free(arr);
return NULL;
}
Array* NodeToArray(Node* node) {
static int count = 0;
if(!node) {
if(count == 0) return NULL;
Array* arr = malloc( sizeof(Array) );
if(!arr) return NULL;
arr->d = calloc( count, sizeof(void*) );
arr->c = 0;
arr->s = count;
return arr;
}
void* d = node->d;
SPP(count);
Array* arr = NodeToArray(node->n);
if(arr == NULL) {
count = 0; return NULL;
}
arr->d[arr->c] = d;
arr->c = PP(arr->c);
free(node);
SSS(count);
return arr;
}
char* str_cpy(char* str) {
int size = 0;
while(str[size]) SPP(size);
PP(size);
char* buffer = malloc(size);
if(!buffer) return NULL;
char* buffer_p = buffer;
char* str_p = str;
while(*str_p) {
*buffer_p = *str_p;
SPS(str_p, 1);
SPS(buffer_p, 1);
}
*buffer_p = '\0';
return buffer;
}
int isNumber(char* str) {
while(*str) {
if('0' <= *str && *str <= '9'); else return 0;
SPS(str, 1);
}
return 1;
}
// 이 함수를 보는자, 희망을 버려라!
char* sum(char* input) {
Array* array = NULL;
{
Node* node = NULL;
char* buf = str_cpy(input);
char swap_buffer = '\0';
char* buf_f = buf;
char* buf_p = buf;
while(*buf_p) {
switch( *buf_p ) {
case '+': case '-': case '*': case '/': case '%': case '(': case ')': SPS(buf_p, 1);
break;
case '\0':
continue;
break;
default:
if('0' <= *buf_p && *buf_p <= '9') while( *buf_p && ('0' <= *buf_p && *buf_p <= '9') ) { SPS(buf_p, 1); }
else {
SPS(buf_p, 1);
buf_f = buf_p;
continue;
}
break;
}
swap_buffer = *buf_p;
*buf_p = '\0';
char* str = str_cpy(buf_f);
*buf_p = swap_buffer;
{
Node* r = Node_push(node, str);
if(r == NULL) {
node = Node_free(node);
return NULL;
}
node = r;
}
buf_f = buf_p;
}
free(buf);
array = NodeToArray(node);
}
if(array == NULL) return NULL;
char* symarr[] = {
"*/%", "+-", ""
};
Node* bracket_node = NULL;
for(int point = 0; point <= array->c; SPP(point)){
int start = 0;
if(point == array->c) {
goto GOTO_FUNCTION;
} else switch(*(char*)array->d[point]) {
case '(':
{
int* d = malloc(sizeof(int));
if(!d) goto GOTO_ERROR;
*d = point;
Node* r = Node_push(bracket_node, d);
if(!r) {
free(d);
goto GOTO_ERROR;
}
bracket_node = r;
}
break;
case ')':
{
int d;
if(bracket_node) {
Node* n = bracket_node;
bracket_node = n->n;
d = *(int*)n->d;
free(n->d);
free(n);
} else {
bracket_node = Node_free(bracket_node);
goto GOTO_ERROR;
}
for(int j = d, h = PP(d); h < array->c; SPP(j), SPP(h)) {
array->d[j] = array->d[h];
}
SSS(array->c);
SSS(point);
start = d;
goto GOTO_FUNCTION;
GOTO_RETURN:
free(array->d[point]);
for(int i = point, j = PP(point); j < array->c; SPP(j), SPP(i)) {
array->d[i] = array->d[j];
}
SSS(array->c);
SSS(point);
continue;
}
break;
case '\0':
GOTO_FUNCTION:
{
//printf("%d pc: %d %d %d \n", __LINE__, start, point, array->c);
char** symarr_ptr = symarr;
while(**symarr_ptr) {
for(int i = start; i <= point && i < array->c; SPP(i)) {
char* sa_pp = *symarr_ptr;
while(*sa_pp) {
if( *(char*)(array->d[i]) == *sa_pp) break;
SPS(sa_pp, 1);
} if ( *sa_pp && 0 < i && PP(i) < array->c ) {
int flag = isNumber(array->d[SS(i)]) << 1 | isNumber(array->d[PP(i)]);
if(flag == 3) {
Num a, b, c; num_read(a, array->d[SS(i)]), num_read(b, array->d[PP(i)]);
switch (*sa_pp) {
case '+':
c_add(c, a, b);
break;
case '-':
c_sub(c, a, b);
break;
case '*':
c_mul(c, a, b);
break;
case '/':
c_div(c, a, b, nullnum);
break;
case '%':
c_div(nullnum, a, b, c);
break;
}
char* r = num_strdup(c);
if(!r) goto GOTO_ERROR;
free(array->d[SS(i)]), free(array->d[i]), free(array->d[PP(i)]);
array->d[SS(i)] = r;
for( int j = i, h = PP(PP(i)); h < array->c; SPP(j), SPP(h) ) {
array->d[j] = array->d[h];
}
array->c = SS(SS(array->c));
point = SS(SS(point));
SSS(i);
}
}
}
SPS(symarr_ptr, 1);
}
if(point < array->c) goto GOTO_RETURN;
break;
}
}
}
//for(int i = 0; i < array->c; SPP(i)) printf("%s ", array->d[i]);
if( '0' <= *(char*)array->d[0] && *(char*)array->d[0] <= '9' ); else goto GOTO_ERROR;
char* buf = str_cpy(array->d[0]);
array = Array_free(array);
return buf;
GOTO_ERROR:
array = Array_free(array);
return NULL;
}
int system_scanf(char* format, ...) {
va_list list;
va_start(list, format);
Num count = {0};
char* str = str_cpy(format);
if(str) {
char* str_f = str;
char* str_p = str;
for(; *str_p; SPS(str_p, 1) ) {
char* ch_p = PS(str_p, 1);
if(*str_p == '%') {
GOTO_FIRST:
switch(*ch_p) {
case '\0':
break;
case '[':
while(*ch_p && *ch_p != ']') SPS(ch_p, 1);
SPS(ch_p, 1);
break;
case 'n':
{
#define fmend "%[0-9]"
int size = sizeof(fmend);
{
char* p = str_f;
while(*p && p != str_p) {
SPP(size);
SPS(p, 1);
}
}
char* format = calloc(PP(size), sizeof(char));
if(format == NULL) return -1;
for(int i = 0, j = -1; i < size; SPP(i)) {
if(&str_f[i] == str_p) j = 0;
if(j != -1) {
format[i] = fmend[j];
SPP(j);
} else {
format[i] = str_f[i];
}
}
format[size] = '\0';
char buf[NS<<4|1];
Num r = {scanf(format, buf)};
buf[NS<<4] = '\0';
num_read(va_arg(list, void*), buf);
if(r[0] == SS(0)) return SS(0);
c_add(count, count, r);
SPS(ch_p, 1);
str_f = str_p = ch_p;
#undef fmend
continue;
}
break;
case 'c': case 'd': case 'f': case 's':
SPS(ch_p, 1);
break;
default:
if(*ch_p == 'l' || '0' <= *ch_p && *ch_p <= '9' ) {
SPS(ch_p, 1); goto GOTO_FIRST;
}
break;
}
char ch = *ch_p;
*ch_p = '\0';
Num r = {scanf(str_f, va_arg(list, void*))};
if(r[0] == SS(0)) return SS(0);
c_add(count, count, r);
*ch_p = ch;
str_f = str_p = ch_p;
}
}
free(str);
} else {
return -1;
}
va_end(list);
return 0;
}
//main.c
int main(int argc, char** argv) {
char buffer[1024] = {0};
system_printf("system_begin, hello world\n\n");
while(1) {
system_printf("enter: ");
if( system_scanf(" %1024[^\n]", buffer) == SS(0)) {
system_printf("error\n");
} else if(!buffer[1]) {
if(buffer[0] == 'q') break;
else if(buffer[0] == 'h') system_printf("%s\n", "input 0-9 +-*/% ()");
else if('0' <= buffer[0] && buffer[0] <= '9') system_printf(" = %c\n", buffer[0]);
else system_printf("error\n");
} else {
char* str = sum(buffer);
if(!str) {
system_printf("error\n");
} else {
system_printf(" = %s\n", str);
}
}
}
system_printf("\nsystem_end, bye!\n");
return 0;
}