From 589128d8a816583787a61574eb30dd120a5dbc46 Mon Sep 17 00:00:00 2001 From: bji0914 <48460120+bji0914@users.noreply.github.com> Date: Tue, 26 Nov 2019 03:44:54 +0900 Subject: [PATCH] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9E=85=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=20=EC=88=98=EC=A0=95=20&=20=ED=9B=84=EC=9C=84=20?= =?UTF-8?q?=EC=97=B0=EC=82=B0=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80(?= =?UTF-8?q?=EC=86=8C=EC=88=98=EC=A0=90=20=EC=B2=98=EB=A6=AC=20=EB=AF=B8?= =?UTF-8?q?=EC=99=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PBL_1 | 319 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 308 insertions(+), 11 deletions(-) diff --git a/PBL_1 b/PBL_1 index 912ab3c..d84df75 100644 --- a/PBL_1 +++ b/PBL_1 @@ -4,6 +4,14 @@ #include #define print printf #include //isspace, isdigit 함수가 선언된 헤더 파일 +#include +#include +#include +#include + +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 int top, size; int *stack; @@ -15,6 +23,9 @@ char* fillZeroInt(char*, char*); char* fillZeroDec(char*, char*); char* calPlus(char*, char*); char* calMinus(char*, char*); +char* removeDot(char *str); // 곰셈할 때 .을 제거하는 함수. +char* addDot(char *str, int dot); // 계산 후 .을 추가하는 함수. +char* calMul(char *a, char *b); void init_stack() { top = -1; } int push(int t); int pop(); @@ -24,13 +35,38 @@ int is_operator(int k) { return (k == '+' || k == '-' || k == '*' || k == '/'); int is_legal(char *s); // 후위표기법 수식이 적접한가 체크 int precedence(int op); // 연산자의 우선순위를 수치로 변환해준다. void postfix(char *dst, char*src);// 중위표기법을 후위표기법으로 변환 +int calc(char *p); //후위표기법 계산 // end definition int main(int argc, char *argv[]) { char *input; char *post_fix; + char *filename; + int fp, readn; + int answer; + + // 이 프로그램이 실행되기 위해서는 파일이름을 인자로 받는다. + // 그러므로 인자를 체크해주어야 한다. + // 만약 인자가 부족하다면, 프로그램의 사용방법을 출력하고 종료한다. + if (argc != 2) + { + printf("Usage : %s [file]\n", argv[0]); + return 1; + } + + // filename 이 argv[1] 을 가리킨다. + // argv[1] 을 그대로 사용해도 되겠지만, 코드의 가독성을 위해서 + // 다른 변수이름을 사용하도록 했다. + filename = argv[1]; + fp = open(filename, O_RDONLY); // 파일을 읽기전용 모드로 연다. + if (fp < 0) + { + perror("file open err :"); + return 0; + } - //FILE *fp = fopen(argv[1],"r"); + /* + // 윈도우용 파일 입출력 FILE *fp = fopen("test.txt", "r"); if (fp == NULL) { printf("error\n"); @@ -39,6 +75,9 @@ int main(int argc, char *argv[]) { fseek(fp, 0, SEEK_END); //파일 포인터를 파일의 끝으로 이동시킴 size = ftell(fp); //파일 포인터의 현재 위치를 얻음 + */ + + size = lseek(fp, 0, SEEK_END); input = malloc(size + 1); //파일 크기 + 1바이트(문자열 마지막의 NULL)만큼 동적 메모리 할당 post_fix = malloc(size + 1); @@ -46,16 +85,39 @@ int main(int argc, char *argv[]) { memset(input, 0, size + 1); //파일 크기 + 1바이트만큼 메모리를 0으로 초기화 memset(post_fix, 0, size + 1); - rewind(fp); //파일 포인터를 파일의 처음으로 이동시킴 + lseek(fp, 0, 0); + + /* 윈도우용 파일 입출력 + rewind(fp); // 파일 포인터를 파일의 처음으로 이동시킴 fread(input, size, 1, fp); //파일 크기만큼 값을 읽음 + */ + + // read 함수를 이용해서, 파일지시자로 부터 데이터를 읽어들인다. + // read 함수는 읽어들인 데이터의 크기를 리턴한다. + // 더이상 읽을 데이터가 없다면 0을 리턴하니, 그때 while 루프를 빠져나오면 된다. + while ((readn = read(fp, input, size)) > 0) + { + // 읽어들인 데이터의 크기 만큼을 화면에 출력한다. + write(STDOUT, input, readn); + } - printf("%s\nsize: %d\n", input, size); + //printf("%s\nsize: %d\n", input, size); postfix(post_fix, input); printf("\nPostfix : %s", post_fix); - fclose(fp); - free(input); + if (!is_legal(post_fix)) { + print("\n!! Unavailable input !!\n"); + return 1; + } + answer = calc(post_fix); + printf("\nAnswer : %d\n", answer); + close(fp); + // fclose(fp); //윈도우용 + free(input); + free(post_fix); + free(stack); + /* A = malloc(sizeof(char) * 50); B = malloc(sizeof(char) * 50); result = malloc(sizeof(char) * 50); @@ -65,12 +127,13 @@ int main(int argc, char *argv[]) { B = fillZeroInt(A, B); A = fillZeroDec(B, A); B = fillZeroDec(A, B); - - // result = calPlus(A, B); // result에 덧셈 결과 저장 - result = calMinus(A, B); // result에 뺄셈 결과 저장 + */ + // result = calPlus(A, B); // result에 덧셈 결과 저장 + //result = calMinus(A, B); // result에 뺄셈 결과 저장 // findOperator(input); - printf("A : %s \nB : %s \n", A, B); // 현재 A, B값 (자리수까지 맞추어져있음) - printf("result : %s\n", result); + //printf("A : %s \nB : %s \n", A, B); // 현재 A, B값 (자리수까지 맞추어져있음) + //printf("result : %s\n", result); + return 0; } // end main() @@ -81,7 +144,41 @@ char* calPlus(char *X, char*Y) { // 덧셈 int lengthA = strlen(A); temp = malloc(sizeof(char)); returningResult = malloc(sizeof(char) * strlen(X)); - for (i = 0; i < lengthA - 1; i++, A++, B++) continue; // A와 B의 포인터 위치를 맨 끝으로 이동하여 맨 뒤부터 계산하도록 함 + + if (X[0] == '-') + { + if (Y[0] == '-') // -1 + -3 + { + *X = *X + 1; //pointer이동해서 X값에서 음수 부호 빼주기 + *Y = *Y + 1; + char *result = calPlus(X, Y); + char *finalResult = malloc(strlen(result) + 1); + *&finalResult[1] = *result; + *&finalResult[0] = '-'; + free(result); + return finalResult; + } + else // -1 + 3 + { + *X = *X + 1; + return calMinus(Y, X); //X에서 -만 빼기 + } + + } + else if (Y[0] == '-') // 1 + (-3) + { + *Y = *Y + 1; + char *result = calMinus(Y, X); + char *finalResult = malloc(strlen(result) + 1); + *&finalResult[1] = *result; + *&finalResult[0] = '-'; + free(result); + return finalResult; + } + + else + + for (i = 0; i < lengthA - 1; i++, A++, B++) continue; // A와 B의 포인터 위치를 맨 끝으로 이동하여 맨 뒤부터 계산하도록 함 for (i = lengthA - 1; i >= 0; i--, A--, B--) { // 맨 뒤부터 앞으로 한칸씩 수행 if (*A == '.' || *B == '.') { // 소수점을 만나게 되면 점을 찍고 다음 반복 수행 returningResult[i] = '.'; @@ -198,6 +295,9 @@ void findOperator(char* input) { break; case '*': // 곱셈 * break; + case ' ': + case '.': + break; default: // 잘못 입력된 경우 print("\n!! Unavailable input !!\n"); exit(0); @@ -232,6 +332,9 @@ int is_legal(char *s) { f--; } else { + if (!isdigit(*s) || !(*s) == '.') { + return 0; + } f++; while (!isspace(*s)) { s++; @@ -289,3 +392,197 @@ void postfix(char *dst, char *src) { dst--; *dst = 0; } +char* removeDot(char *str) // 곰셈할 때 .을 제거하는 함수. +{ + int cnt = 0; + char *ptr; + char *a = malloc(sizeof(char) * 30); + char *b = malloc(sizeof(char) * 30); + char *c = malloc(sizeof(char) * 30); + strcpy(a, str); + ptr = strtok(a, "."); + while (ptr != NULL) { + if (cnt == 0) b = ptr; + else c = ptr; + ptr = strtok(NULL, "."); + cnt++; + } + strcat(b, c); + return b; +} +char* addDot(char *str, int dot) // 계산 후 .을 추가하는 함수. +{ + int i; + char *answer = malloc(sizeof(char) * 20); + char *temp = malloc(sizeof(char) * 20); + memset(answer, 'X', sizeof(char) * 20); + memset(temp, 'X', sizeof(char) * 20); + strcpy(answer, str); + int len = strlen(answer); + temp[len] = '\0'; + for (i = 0; i < len + 1; ++i, answer++) + { + if (i + dot + 1 == len) temp[i] = '.'; + else temp[i] = *answer; + } + return temp; +} +char* calMul(char *a, char *b) +{ + int i, j, sum, k, strlenA, strlenB, dot = 0, cnt = 0; + char one; + char *ptr; + char *result = malloc(sizeof(char)*strlen(a)*strlen(b)); + char *answer = malloc(sizeof(char)*strlen(a)*strlen(b)); + char *temp = malloc(sizeof(char)*strlen(a)*strlen(b)); + char *temp2 = malloc(sizeof(char)*strlen(a)*strlen(b)); + char *temp3 = malloc(sizeof(char)*strlen(a)*strlen(b)); + char *c = malloc(sizeof(char)*strlen(a)*strlen(b)); + char *d = malloc(sizeof(char)*strlen(a)*strlen(b)); + memset(answer, 'X', sizeof(char)*strlen(a)*strlen(b)); + memset(temp, 'X', sizeof(char)*strlen(a)*strlen(b)); + memset(temp2, 'X', sizeof(char)*strlen(a)*strlen(b)); + memset(temp3, 'X', sizeof(char)*strlen(a)*strlen(b)); + + + result = strchr(a, '.'); + + if (result != NULL)// a에 .이 있는지 검사 있으면 제거를 한다 + { + c = removeDot(a); + strlenA = strlen(a) - 1; + dot = strlen(a) - findDot(a) - 1 + dot; + } + else + { + c = a; + strlenA = strlen(a); + + } + cnt = 0; + + + result = strchr(b, '.'); + + if (result != NULL)// b에 .이 있는지 검사 있으면 제거를 한다 + { + d = removeDot(b); + strlenB = strlen(b) - 1; + dot = strlen(b) - findDot(b) - 1 + dot; + } + else + { + d = b; + strlenB = strlen(b); + + } + cnt = 0; + + for (i = 0; i < strlenA - 1; i++, c++) continue;// 각 수의 포인터를 가장 끝으로 옮긴다. + for (j = 0; j < strlenB - 1; j++, d++) continue; + sum = 0; + for (i = strlenB; i > 0; i--, d--)// 곱하기를 한다. + { + answer[strlenA + cnt + 1] = '\0'; + for (j = strlenA + cnt; j > strlenA; j--) + { + answer[j] = '0'; + } + for (j = strlenA; j > 0; j--, c--) + { + int oneA = *c - 48; + int oneB = *d - 48; + sum = oneA * oneB + sum; + if (sum > 9) + { + one = (sum % 10) + 48; + sum = sum / 10; + } + else + { + one = sum + 48; + sum = 0; + } + answer[j] = one; + } + if (sum > 0) + { + answer[j] = sum + 48; + } + + if (answer[0] == 'X') { + strncpy(temp, answer + 1, strlenA + cnt + 1); + answer = temp; + } + + if (cnt == 0) // 가장 처음에 계산된 값을 빈 공간에 담는다. + { + strcpy(temp2, answer); + } + + else + { + + if (strlen(answer) == strlen(temp2)) // 합계에 계산된 값을 계속 넣는다. + { + strcpy(temp2, calPlus(answer, temp2)); + + } + else if (strlen(answer) > strlen(temp2)) + { + strcpy(temp2, (fillZeroInt(answer, temp2))); + strcpy(temp2, calPlus(answer, temp2)); + } + else if (strlen(answer) < strlen(temp2)) + { + strcpy(answer, (fillZeroInt(temp2, answer))); + strcpy(temp2, calPlus(answer, temp2)); + } + } + cnt++; + sum = 0; + memset(answer, 'X', sizeof(char)*strlen(a)*strlen(b)); + for (k = 0; k < strlenA; k++, c++) continue; + } + if (dot == 0) return temp2; + else return addDot(temp2, dot); // .이 있었던 경우 계산후에 다시 추가한다. +} +int calc(char *p) { + int i; + init_stack(); + while (*p) { + if (*p >= '0' && *p <= '9') { + i = 0; + do { + i = i * 10 + *p - '0'; + p++; + } while (*p >= '0' && *p <= '9'); + push(i); + } + else if (*p == '.') {//소수부 연산..? + p++; + } + else if (*p == '+') { + push(pop() + pop()); + p++; + } + else if (*p == '*') { + push(pop() * pop()); + p++; + } + else if (*p == '-') { + i = pop(); + push(pop() - i); + p++; + } + else if (*p == '/') { + i = pop(); + push(pop() / i); + p++; + } + else { + p++; + } + } + return pop(); +}