728x90

apm setup 설치

http://software.naver.com/software/summary.nhn?softwareId=MFS_111815

 

 

root password는 apmsetup (변경가능)

 

 

MySQL monitor 실행 (cmd또는 apm setup모니터에서 실행)

 

1
mysql -u아이디 -p비밀번호
1
mysql -h호스트주소 -p포트번호 -u아이디 -p비밀번호

 

 

C:\Users\PKNU>mysql -uroot -p    // -u는 user명 -p는 password인데 보안상 바로 입력하지 않고 다음줄에서 입력하는 것이 좋다.
Enter password: ****
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 5.1.41-community MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

 

 

SQL문은 세미콜론으로 구분, 키워드는 대소문자 구분이 없다.

 

 

MySQL Workbench 를 통해 실행한 결과 (https://dev.mysql.com/downloads/workbench/

 

 

// 명령어 입력도중 취소하려면 \c 입력 

mysql> select
    -> user()
    -> \c    // ->는 다음 줄을 기다린다는 의미
mysql>    // 새 명령을 받아들일 준비가 되었음

 

 

//  데이터베이스 목록 보기 (show) 

1
SHOW DATABASES;


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| phpmyadmin         |
+--------------------+
3 rows in set (0.00 sec)

mysql>

 

 

// 데이터베이스 생성 및 선택

생성

1
CREATE DATABASE `데이터베이스명` CHARACTER SET utf8 COLLATE utf8_general_ci;

선택

1
USE `데이터베이스명`


mysql> create database rutel;    // rutel 데이터베이스 생성
Query OK, 1 row affected (0.00 sec)


mysql> use rutel;                    // rutel 데이터베이스 선택
Database changed
mysql>

 


// mysql 시작할 때, 데이터베이스(rutel)를 선택

C:\Windows\System32>mysql -hlocalhost -uroot -p rutel
Enter password: ****
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 5.1.41-community MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.



// show를 통해 rutel 데이터베이스가 존재함을 볼 수 있다.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| rutel               |
| mysql              |
| phpmyadmin         |
+--------------------+
4 rows in set (0.00 sec)



// table 보기

1
SHOW tables;


mysql> show tables;

Empty set (0.00 sec)


데이터베이스의 설계

DB는 테이블들의 그룹이라고 할 수 있다.


pet table

애완동물 이름(name), 소유주(owner), 종(species), 암수(sex), 출생일(birth, death)


나이 대신 출생일을 속성으로 두는 이유?

: 나이는 계속 변하며, 출생일은 고정. 출생일을 통해 생일 이벤트, 사망일을 통해 수명을 알 수 있다.

데이터 베이스에선 설계단계에서부터 이러한 것들을 고려하여야 한다.


// 테이블 생성 (varchar, char, date는 자료형)

mysql> create table pet (name varchar(20), owner varchar(20),

    -> species varchar(20), sex char(2), birth date, death date);

Query OK, 0 rows affected (0.01 sec)


CREATE TABLE score (    

    학번  tinyint NOT NULL ,

    성명  varchar(4) NOT NULL ,

    국어  tinyint NOT NULL ,

    영어  tinyint NOT NULL ,

    수학  tinyint NOT NULL ,

    총점  tinyint NOT NULL ,

    평균  tinyint NOT NULL ,

    등급  char(2) NOT NULL ,

    PRIMARY KEY (학번)

);



varchar는 가변길이 문자열을 뜻한다.


//  테이블 스키마 열람 (describe또는 desc로 줄여써도 된다)

1
DESC `테이블명`

스키마 : 테이블에 적재될 데이터의 구조와 형식을 정의 하는 것


데이터 타입 목록


Var type은 입력받은 데이터 만큼만 공간을 차지하며 유연하며, 공백도 하나의 문자로 취급한다. ('AA' != 'AA ')

고정 문자는 검색의 성능면에서 유리한 장점이 있다고 하지만 Var type이 크게 성능에 영향을 주는건 아니고 유연하기에 Var type을 주로 사용한다.

 (참고 : http://okky.kr/article/217655)


길이가 절대 바뀔 일이 없는 데이터는 CHAR를 사용할 수도 있겠다. (예 : 주민번호)


enum은 열거형으로, 성별같이 정해진 값을 강제할 수 있다.


name, owner...와 같은 컬럼들을 갖는 테이블을 볼 수 있다.


// 레코드 입력하기(Insertion of records)

mysql> insert into pet

    -> values('Ludwig', 'rutel', 'dog', 'm', '2017-03-07', NULL);

Query OK, 1 row affected (0.00 sec)



// SELECT 질의로 검색하기

select * from pet;




// UPDATE 구문을 통한 데이터 수정

mysql> UPDATE pet

    -> SET species = "cat"    // 종을 cat으로 변경

    -> WHERE owner = "rutel";    // 소유자가 "rutel"인 것을 찾아

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1  Warnings: 0    // match되는 레코드가 한 건, 변경된 레코드가 1건, 경고(문제) 없음





// 테이블 데이터 제거 (테이블 구조를 제거하는 것이 아니다)

mysql> DELETE FROM pet;

'DB' 카테고리의 다른 글

데이터 베이스 기초  (0) 2017.06.14
SQL injection (SQL 삽입)  (0) 2017.06.01
MySQL 기초 공부  (0) 2017.05.30
SQL Server 2014 설치방법  (0) 2017.03.17
SQLD 관련 자료 & 사이트  (0) 2017.03.05
728x90


구루비 SQLP 연구회 - http://wiki.gurubee.net/pages/viewpage.action?pageId=27426887



KDB 시험예제

SQL자격검정시험 예제(2010 10).pdf


요약 정리 - http://blog.naver.com/liberty264/220567987579



SQL 전문가 되어보기 WikiDocs - https://wikidocs.net/book/159



시험 후기

http://blog.naver.com/senticri/220240528846

http://118k.tistory.com/170



Study_Room_Doc_02_SQLD_예상문제(기출21회참고).pdf

Study_Room_Doc_02_SQLD_예상문제해답(기출21회참고).pdf


'DB' 카테고리의 다른 글

데이터 베이스 기초  (0) 2017.06.14
SQL injection (SQL 삽입)  (0) 2017.06.01
MySQL 기초 공부  (0) 2017.05.30
SQL Server 2014 설치방법  (0) 2017.03.17
MySQL 설치 및 기초  (0) 2017.03.06
728x90

https://github.com/shimat/opencvsharp




PM> Install-Package OpenCvSharp3-AnyCPU -Version 3.2.0.20170126



OpenCvSharp 레퍼런스

https://shimat.github.io/opencvsharp_docs/html/d75eb659-6335-53f6-af7a-81814a21ab7f.htm


한글OpenCVSharp1_1.chm



728x90

PowerShell script to disable suspend

https://blogs.msdn.microsoft.com/usbcoreblog/2013/10/31/help-after-installing-windows-8-1-my-usb-drive-disappears-or-file-transfers-stop-unexpectedly/



다음의 파워쉘 스크립트를 메모장에 복붙해서 ToggleSuspend.ps1 으로 저장

https://colorscripter.com/s/1FCZ4KS



ctrl+shift 우클릭 후 명령창 열기(admin) 실행


*.ps1 파일이 있는 경로에서 다음의 명령 입력

Powershell -ExecutionPolicy Bypass -NoProfile -File ToggleSuspend.ps1


드라이브 확인하고 번호 입력 후 엔터



728x90

 

 

// 문자를 입력받고 입력된 문자의 수 출력하기

#include <stdio.h>


void ClearLineFrom_ReadBuffer(void)

{

while (getchar() != '\n');

}


int main(void)

{

int total = 0;

char input;


while (1)

{

fputs("문자 입력 (종료하려면 Ctrl+Z): ", stdout);

input = getchar();

if (input == EOF)

break;


ClearLineFrom_ReadBuffer();

total++;

}


printf("입력된 문자 갯수: %d \n", total);

return 0;

}



// 숫자 n개만큼 입력받고 최대,최소값, 합, 평균 출력하기

#include <stdio.h>


#define data_num 7


int main(void)

{

int iNum;

int cnt=1; // 최초1회 입력받고 이후 loop

int max, min, sum=0;

double avg;

// 최소값과 최대값이 0으로 고정되지 않도록 최초 1회 입력받음

printf("정수 입력 : ");

scanf("%d", &iNum);

max = min = sum = iNum;


// 이후 남은 자료갯수만큼 입력받음

for (cnt; cnt < data_num; cnt++)

{

printf("정수 입력 : ");

scanf("%d", &iNum);

if (iNum > max)

max = iNum;


if (iNum < min)

min = iNum;

sum = sum + iNum;

}


avg = (double)sum / data_num;

printf("최대값 %d, 최소값 %d, 합 %d, 평균 %f \n", max, min, sum, avg);


return 0;

}


// 10진수->n진수 변환 (재귀함수)

#include <stdio.h>

#define digit 2    // 2진수


void conv_bin(num)

{

int bin;

if (num > 0)

{

bin = num % digit;

num = num / digit;

conv_bin(num);

printf("%d", bin);

}

else

return;

}


int main(void)

{

int num;

scanf("%d", &num);

conv_bin(num);


return 0;

}

'Study > C' 카테고리의 다른 글

size_t  (0) 2017.05.29
enum, auto, 구조체  (0) 2017.03.24
c 복습  (0) 2016.11.03
파일의 분할과 헤더파일의 디자인  (0) 2016.08.30
선행처리기와 매크로2  (0) 2016.08.30
728x90

TCP, 그리고 UDP 쉽게 알아보는 두 개념과 차이점

원문보기: 
http://www.inven.co.kr/webzine/news/?news=165870#csidx4db9516eea5f377b7f80cb9c3f102aa 

728x90

128usart.7z

main.c

SeialTest (3).7z


---------------------------------

SeialTest.7z



#include <avr/io.h>

#include <util/delay.h>


#define  CLR   0x01      //Clear Display 명령

#define  HOME  0x02      //Return Home 명령 

#define  FNC   0x38      //Function Set 명령 0b00111000

                //Data Length = 8bit. 행수 2행, 문자 폰트 5x8


#define CTL PORTL

#define DB PORTD


#define    RXC          7


void uart0_init(void)

{

UCSR0A = 0x00;

  UCSR0B = 0x18; //Enable transmitter

  UCSR0C = 0X06;        // No psrity, 1stop bit, 8bit data


  UBRR0L = 0x67; //set baud rate lo 16Mhz baud rate 9600!!

  UBRR0H = 0x00; //set baud rate hi

}


unsigned char USART_Receive(void)

{

/* Wait for data to be received */

while(!(UCSR0A &(1<<RXC)))

;


/* Get and return received data from buffer */

return UDR0;

}


void LCD_PortSetting(void)

{

  DDRD = 0xFF;        //data bus line

  DDRL = 0xFF;        //control line (0~2 제어핀 사용)

  //D0: RS ,D1: R/W ,D2: EN

}


void IR_Write(unsigned char Data)  

{

  CTL &= 0xFC;    //RS = 0, Write Enable

  _delay_us(1);    //Enable 까지 최소 대기 시간 40ns

  CTL |= 0x04;    //Enable 활성화

  _delay_us(1);    //

  DB = Data;    //Data

  _delay_us(1);

  CTL = 0b00000010;  //Disable, Read Mode  


}


void DR_Write(unsigned char Data)

{

  CTL = 0x01;    //RS = 1, Write Enable

  _delay_us(1);    //Enable 까지 최소 대기 시간 40ns

  CTL |= 0x04;    //Enable 활성화

  _delay_us(1);    //

  DB = Data;    //Data

  _delay_us(1);

  CTL = 0b00000010;  //Disable, Read Mode  

}


void LCD_Char(unsigned char ucChar)

{

  _delay_ms(1); // 명령어 쓰기 전 일정 시간 지연, Busy Flage 확인 대용

  DR_Write(ucChar);  

}


void LCD_Position(unsigned char ucCol, const char ucRow)

{

    IR_Write(0x80 | (ucRow + ucCol * 0x40));

}



void LCD_String(unsigned char ucLine,unsigned char ucRow, const char* ccString)        //    문자열 출력 함수

{                                                    // ucPosition 값에 따라 LCD_Position 값이 달라짐

    LCD_Position(ucLine, ucRow);

    while(*ccString != 0)                            //    *ccString이 null을 가리킬때까지

    {

        LCD_Char(*ccString);

        ccString++;                                    //    문자열의 주소값이 자료형만큼 증가

        if(*ccString <= 0x0F)

        {

            LCD_Position(1,0);

            _delay_ms(2);

        }

    }

}



void LCD_drive()

{

  _delay_ms(50);

  IR_Write(FNC);

  _delay_ms(5);

  IR_Write(FNC);

  _delay_us(100);

  IR_Write(FNC);

  _delay_ms(2);

  IR_Write(0x0E); // DDD RAM내용 표시, 커서 ON, 커서 깜빡임 OFF

  _delay_ms(2);  

  IR_Write(CLR); // Display Clear

  _delay_ms(30);

  IR_Write(0x06); // Entry Mode Set, 커서위치를 오른쪽으로 증가

  _delay_ms(2);

}



void LCD_Usart()

{

int cnt=0;

LCD_Delete();

_delay_ms(2);

LCD_Position(0,0);

while(1)

{

while((UCSR0A&0x80)==0x80)

{

LCD_Char(UDR0);

cnt++;

if(cnt==16)

{

cnt=0;

LCD_Delete();

_delay_ms(2);

}

}

}

}


void LCD_Delete(void)

{

    _delay_ms(1);

    IR_Write(0x01);

}


int main(void)

{

uart0_init();

  LCD_PortSetting();

  LCD_drive();    

  _delay_ms(2);


  DDRB = 0xFF;

PORTB = 0x00;


while(1)

{

LCD_Usart();

}

  return 0;

}



---------------------------------------------------------------------------

















#include <avr/io.h>


/////////// USART0 ///////////////////////////////////////////////

#define UDR0 (*((volatile unsigned char*)0xC6))


#define UCSR0A (*((volatile unsigned char*)0xC0))

#define UCSR0B (*((volatile unsigned char*)0xC1))

#define UCSR0C (*((volatile unsigned char*)0xC2))


#define UBRR0L (*((volatile unsigned char*)0xC4))

#define UBRR0H (*((volatile unsigned char*)0xC5))


#define    TXEN         3

#define    RXEN         4

#define    USBS        3

#define    UCSZ0        1

#define    UDRE        5

#define    RXC          7



#define FOSC 16000000 // Clock Speed

#define BAUD 9600 // Serial 

#define MYUBRR FOSC/16l/BAUD-1


void USART_Init(unsigned int ubrr);

void USART_Transmit(unsigned char data);

unsigned char USART_Receive(void);


int main(void)

{

int i;

USART_Init(MYUBRR);

USART_Transmit("T");

DDRB = 0xFF;

PORTB = 0x00;


while(1)

{

switch(USART_Receive())

{

case '1' : 

PORTB = 0xFF;

break;

case '2' :

PORTB = 0x00;

break;

case '3' :

PORTA = 0xFB;

break;

}

}

return 0;

}


void USART_Init(unsigned int ubrr)

{

/* Set baud rate */

UBRR0H = (unsigned char) (ubrr>>8);

UBRR0L = (unsigned char) ubrr;

/* Enable receiver and transmitter */

UCSR0B = (1<<RXEN) | (1<<TXEN);

/* Set frame format : 8data, 1stop bit */

UCSR0C = 3<<UCSZ0;

}


void USART_Transmit(unsigned char data)

{

/* Wait for empty transmit buffer */

while(! (UCSR0A & (1<<UDRE)))

;

UDR0 = data;

}


unsigned char USART_Receive(void)

{

/* Wait for data to be received */

while(!(UCSR0A &(1<<RXC)))

;


/* Get and return received data from buffer */

return UDR0;

}



'Study > Embedded' 카테고리의 다른 글

아두이노 LCD  (0) 2017.06.01
아두이노 기초  (0) 2017.05.25
7/21 Atmega128 포트/ win32 api  (0) 2016.07.21
7/8 LCD제어2  (0) 2016.07.08
7/5 LCD 제어  (0) 2016.07.05
728x90

EditMode에서 실시간 반영


[ExecuteInEditMode] 키워드를 스크립트에서 class위에 추가


1
2
3
[ExecuteInEditMode]
public class UIRoot : MonoBehaviour
{ ... }
cs


'Study > Unity Engine' 카테고리의 다른 글

유니티3d 로드쇼 후기  (0) 2016.10.21
728x90

vs2015-wpf

Save the Humans.7z



wpf-user guide

WPF_user_guide.7z.001

WPF_user_guide.7z.002



wpf 연습(if~else문 활용)

우상단 체크박스에 체크하지 않으면 Text block에 위와 같은 문구가 뜬다.

체크 후에 버튼을 눌러보면 처음엔 오른쪽-다시 한번 눌렀을 땐 왼쪽으로 정렬이 된다. 


처음 실행시 text에 right가 아니기 때문에 else문이 실행되고 text속성이 right로 변경, HorizontalAlignment 속성도 right로 변경된다.

다시 한번 눌렀을 때는 if문이 만족되어 각각 left로 변경됨을 볼 수 있다.


아래는 그리드에 대한 재멀(xaml) 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<Window x:Class="Practice_Using_IfElse.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Practice_Using_IfElse"
        mc:Ignorable="d"
        Title="MainWindow" Height="192" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button x:Name="changeText" Content="Change the lable if checked" 
        HorizontalAlignment="Center" VerticalAlignment="Center" Click="changeText_Click"/>
 
        <CheckBox x:Name="enableCheckbox" Content="Enable lable changing" Grid.Column="1" 
        HorizontalAlignment="Center" VerticalAlignment="Center"/>
 
        <TextBlock x:Name="labelToChange" Grid.Row="1" TextWrapping="Wrap" Text="Press the button to change my text" 
        Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Window>
cs


xaml.cs 코드의 일부분 (이벤트 핸들러 메서드에 대한 C# 코드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 private void changeText_Click(object sender, RoutedEventArgs e)
        {
            if (enableCheckbox.IsChecked == true)
            {
                if(labelToChange.Text == "Right")
                {
                    labelToChange.Text = "Left";
                    labelToChange.HorizontalAlignment = HorizontalAlignment.Left;
                }
                else
                {
                    labelToChange.Text = "Right";
                    labelToChange.HorizontalAlignment = HorizontalAlignment.Right;
                }
            }
            else
            {
                labelToChange.Text = "Text changing is disabled";
                labelToChange.HorizontalAlignment = HorizontalAlignment.Center;
            }
        }
cs


'Study > C#' 카테고리의 다른 글

C# 클래스, 메소드  (0) 2017.04.04
c# 복습  (0) 2017.03.31
5/27 업무일지 c#학생성적관리(콘솔)  (0) 2016.05.27
c# 클래스 복습2  (0) 2016.05.23
c# 스터디일지 -클래스  (0) 2016.05.22
728x90

수식계산을 위해 고려해야할 두가지

1. 소괄호 먼저 연산

2. 연산자 우선순위를 근거로 연산 



수식 표기법


중위 표기법 (infix notation)    ex) 5 + 2 / 7

: 수식내에 연산 순서 정보 없음. 소괄호와 연산자 우선 순위를 정의하여 연산 순서 명시. 일반적인 수식은 바로 infix



전위 표기법 (prefix notation)    ex) +5 / 2 7

후위 표기법 (postfix notation)    ex) 5 2 7 / +

: 전위와 후위는 수식내에 연산순서의 정보가 담겨있다. 따라서 소괄호가 필요없고 연산 우선순위를 결정할 필요가 없다.



중위 표기법은 우리가 이해하기는 쉽다. 하지만 연산자 우선 순위를 조절하기 위해 소괄호가 필요하다.

따라서, 수식의 값을 구하기 쉽고 괄호없이 표현이 정확한 후위 표기법을 사용한다. 


stack을 이용한 중위 -> 후위 수식 변환 과정


 수식을 이루는 왼쪽 문자부터 하나씩 처리


1. 피 연산자는 오른쪽(변환된 수식이 위치할 자리)으로 이동

2. 연산자는 쟁반(stack)으로 이동




3. stack에 기존 연산자가 있을 때는?


stack에 위치한 연산자 우선 순위가 높으면

-> stack에 위치한 연산자를 꺼내 오른쪽으로 이동, 새 연산자를 stack으로 이동


stack에 위치한 연산자 우선 순위가 낮으면

-> stack에 위치한 연산자 위에 새 연산자 쌓음


서로의 연산자 우선 순위가 같다면

-> stack에 위치한 연산자 우선 순위가 높다고 가정하여 오른쪽으로 옮기고, 새 연산자를 stack으로 이동


 둘 이상의 연산자가 쌓여있을 때에도 1:1로 계속 비교하여 진행해야 한다.



4. 마지막으로 위와 같이 쟁반(stack)의 데이터 차례대로 꺼내 옮김




중위 -> 후위 수식 변환 과정 : 소괄호 고려




) 연산자를 만나면 stack의 data를 ( 연산자 만날때까지 오른쪽으로 옮긴다. 그리고 괄호는 사라진다.

위의 그림에서도 이 같은 과정을 거친 후,  / 연산자를 stack으로 4를 오른쪽으로 옮기고 마지막으로 stack의 데이터( / )를 꺼내 옮긴다.


-> 1 2 3 * + 4 /




중위 -> 후위 수식 변환 프로그램 구현



위의 과정을 코드로 옮기면 다음과 같다.


일단 stack의 정의와 연결리스트 초기화는 이전 포스팅 참조 (http://smart2016.tistory.com/113)


1
2
3
4
5
6
7
8
9
void ConvToRPN(char MExp[])
{ . . . .}
 
int main(void)
{
    char MExp[] = "3-2+4";
    ConvToRPN(MExp);
    . . . .
}
cs


 중위 표기법 수식을 배열에 담아 함수 인자로 전달, 호출된 함수의 인자 MExp에는 변환된 수식이 담기도록 한다.


아래 함수는 연산자의 우선 순위 정보를 반환하는 함수로 ConvToRPN의 helper function이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int GetOpPrec(char op)// Operator precedence
{
    switch (op)    
    {
    case '*':
    case '/':
        return 3;    // 최우선 연산 순위
 
    case '+':
    case '-':
        return 2;
 
    case '(':
        return 1;        
    }
 
    return -1;    // 연산자가 아닐 때 return값
}
cs


( 는 ) 연산자가 등장할 때까지 stack에 남아있어야 하기 때문에 우선순위가 가장 낮다 ( 1 )

 ) 연산자는 stack으로 가지 않기 때문에 return 값 정의 없음



두 연산자 우선순위 비교결과를 반환하는 함수 - ConvToRPN의 실질적인 helper function

op1이 우선순위가 높다면 1 반환, op2가 높다면 -1 반환, 같다면 0 을 반환하도록 정의

1
2
3
4
5
6
7
8
9
10
11
12
int WhoPrecOp(char op1, char op2)
{
    int op1Prec = GetOpPrec(op1);
    int op2Prec = GetOpPrec(op2);
 
    if (op1Prec > op2Prec)
        return 1;
    else if (op1Prec < op2Prec)
        return -1;
    else // 우선순위 같음
        return 0;
}
cs




후위 표기법의 수식 계산

1. 피연산자는 stack으로 옮김

2. 연산자를 만나면 stack에서 두개의 피연산자를 꺼내 계산

3. 계산결과를 다시 stack에 넣음


stack을 이용한 계산기

//stack을 이용한 계산기

#include <stdio.h>
#include <stdlib.h>

#define STACKSIZE 100

int stack[STACKSIZE];
int top;

////////////////////////////////////////////////////////////////////////// 스택 초기화
void init_stack(void)
{
	top = -1;
}

////////////////////////////////////////////////////////////////////////// push
int push(int t)
{
	if (top >= STACKSIZE - 1)
	{
		printf("\n   Stack overflow.");
		exit(1);
	}
	stack[++top] = t;
	return t;
}

////////////////////////////////////////////////////////////////////////// pop
int pop(void)
{
	if (top < 0)
	{
		printf("\n   Stack underflow.");
		exit(1);
	}
	return stack[top--];
}

////////////////////////////////////////////////////////////////////////// 스택 top의 값 구한다.
int get_stack_top(void)
{
	return (top < 0) ? -1 : stack[top];
}

////////////////////////////////////////////////////////////////////////// 스택이 비어있는지 확인
int is_stack_empry(void)
{
	return (top < 0);
}

////////////////////////////////////////////////////////////////////////// 연산자 확인
// 이후 확장시 변경
int is_operator(int k)
{
	return (k == '+' || k == '-' || k == '*' || k == '/');
}

////////////////////////////////////////////////////////////////////////// 피연산사 확인
int is_operand(int src)
{
	return (src >= '0' && src <= '9');
}

////////////////////////////////////////////////////////////////////////// 후위 표기법 적합성 확인
int is_legal(char *s)
{
	int f = 0;
	while (*s)
	{
		while (*s == ' ') // remove space
			s++;
		if (is_operator(*s))
			f--; // 연산자이면 감소
		else
		{
			f++; // 피연산자이면 증가
			while (*s != ' ')
				s++;
		}
		if (f < 1) break; // f가 1보다 적으면 언더플로
		s++;
	}
	return (f == 1); // 피연산자의 수 - 연산자의 수 = 1;
}

////////////////////////////////////////////////////////////////////////// 연산자의 우선순위를 수치로 변환
int precedence(int op)
{
	if (op == '(') return 0;
	if (op == '+' || op == '-') return 1;
	if (op == '*' || op == '/') return 2;
	else return 3;
}

////////////////////////////////////////////////////////////////////////// 중위표기법을 후위표기법으로 변환
// dst : 후위표기법으로 변환한 식 저장, src : 중위 표기법이 저장된 인자
void postfix(char *dst, char *src)
{
	//   char c;
	init_stack(); // 스택 초기화
	while (*src) // 중위 표기법이 남아있는 동안
	{
		if (*src == '(') // '('를 만나면 스택에 푸시
		{
			push(*src);
			src++;
		}
		else if (*src == ')') // ')'를 만나면 '('가 나올 때까지 팝
		{
			while (get_stack_top() != '(')
			{
				*dst++ = pop();
				*dst++ = ' ';
			}
			pop(); // '('는 버린다.
			src++;
		}
		else if (is_operator(*src)) // 연산자
		{
			while (!is_stack_empry() && precedence(get_stack_top()) >= precedence(*src))
			{ // 자신보다 높은 우선순위의 연산자는 스택에서 팝
				*dst++ = pop();
				*dst++ = ' ';
			}
			push(*src); // 자신을 push
			src++;
		}
		else if (is_operand(*src))
		{
			do {
				*dst++ = *src++;
			} while (is_operand(*src));
			*dst++ = ' ';
		}
		else src++;
		// 설정한 문자 외의 값들은 무시한다. 공백, 오타 등.
	}
	while (!is_stack_empry())
	{ // 스택에 남은 연산자를 모두 팝
		*dst++ = pop();
		*dst++ = ' ';
	}
	dst--; // ' '제거
	*dst = 0;
}

int calc(char *p)
{ // 후위표기법 수식을 연산
	int i;
	init_stack();
	while (*p)
	{
		if (is_operand(*p))
		{
			i = 0;
			do {
				i = i * 10 + *p - '0';
				p++;
			} while (*p >= '0' && *p <= '9');
			push(i); // 피연산자는 스택에 푸시.
		}
		else if (*p == '+')
		{ // 연산자가 팝 두 번해서 계산하여 그 결과를 푸시
			push(pop() + pop());
			p++;
		}
		else if (*p == '*')
		{
			push(pop() * pop());
			p++;
		}
		// '-'와 '/'는 교환 법칙이 성립하지 않는다. push(pop() - pop())에서 어느 pop이 먼저인지 컴파일러에 따라 다르다.
		else if (*p == '-')
		{
			i = pop();
			push(pop() - i);
			p++;
		}
		else if (*p == '/')
		{
			i = pop();
			push(pop() / i);
			p++;
		}
		else p++;
	}
	return pop(); // 연산 결과
}

int main()
{
	int r;
	char exp[256];
	char argv[] = { 0 };
	char postExp1[50] = { 0 };
		
	printf("수식 입력: ");
	fgets(postExp1, sizeof(postExp1), stdin);
	postExp1[strlen(postExp1) - 1] = 0;
	
	postfix(exp, postExp1); // 후위표기법으로 바꿈
	printf("\nPostfix : %s", exp);

	if (!is_legal(exp)) // 수식이 적법한가 점검
	{
		printf("\n Expression is not legal!");
		exit(1);
	}
	r = calc(exp); // 연산
	printf("\nAnswer : %d \n", r);
	
	return 0;
}



'Data Structure' 카테고리의 다른 글

자료 구조 - Stack  (0) 2016.11.05
연결리스트와 파일 입출력  (0) 2016.11.02
이진 트리의 구현과 순회(Traversal)  (0) 2016.09.12
Binary Tree  (0) 2016.09.12
Doubly Linked List  (0) 2016.09.09

+ Recent posts