Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
319 changes: 308 additions & 11 deletions PBL_1
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
#include <string.h>
#define print printf
#include<ctype.h> //isspace, isdigit 함수가 선언된 헤더 파일
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

#define STDIN 0
#define STDOUT 1
#define STDERR 2

int top, size;
int *stack;
Expand All @@ -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();
Expand All @@ -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");
Expand All @@ -39,23 +75,49 @@ 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);
stack = malloc(sizeof(int) * size);
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);
Expand All @@ -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()

Expand All @@ -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] = '.';
Expand Down Expand Up @@ -198,6 +295,9 @@ void findOperator(char* input) {
break;
case '*': // 곱셈 *
break;
case ' ':
case '.':
break;
default: // 잘못 입력된 경우
print("\n!! Unavailable input !!\n");
exit(0);
Expand Down Expand Up @@ -232,6 +332,9 @@ int is_legal(char *s) {
f--;
}
else {
if (!isdigit(*s) || !(*s) == '.') {
return 0;
}
f++;
while (!isspace(*s)) {
s++;
Expand Down Expand Up @@ -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();
}