티스토리 뷰

프로그래밍/LISP

LIPS 4.

.가끔은 2021. 10. 16. 21:47
반응형

repeat 반복문

똑같은 명령을 반복하고자 할 때 사용한다. 

1. (repeat)의 설명 

(repeat <정수 또는 정수 형식의 변수> 
 <명령문 1> 
 <명령문 2> 
 <명령문 3> 


위의 '정수'부분은 꼭 1,2,3,4... 같은 정수만 써야 한다. 
1.0, 2.0, 3.0과 같이 소수점이 붙은 정수 같은 숫자들도 안된다. 
지금은 소숫점을 숫자로 써놓아서 당연히 이해하겠지만 
정수 자리에 변수가 들어가면 변수가 꼭 정수형인지 확인해야 한다. 

2. 바로 예제로 들어가 보자 

아래의 예제는 n 값을 초기값인 1로 설정하고 
10번을 반복하면서 1씩 더해간다. 
결괏값인 'n'은 '11'이 된다. 

(defun c:test1() 
(setq n 1) ; 초기값 n ← 1 로 설정한다. 
(repeat 10 ; 10번을 반복한다. 
(setq n (+ 1 n)); n ← n+1 
); End of repeat 
); End of Defun


3. 지금까지의 배운 명령어를 바탕으로 10개의 원을 그리는 리습을 만들어 보자. 
x좌표를 2 만큼이 증가하면서 반지름 3인 원을 10개 그리는 예제이다. 

(defun c:test2() 
(setq x 0 y 0 z 0); 각각 x=0, y=0, z=0으로 설정 
(setq n 10) ; n(반복횟수)=10회로 설정 
(repeat n 
(setq pt (list x y z)) 
(command "circle" pt "3"); 반지름이 3인 원을 pt 즉 (x y z)에 그린다. 
(setq x (+ 2 x)); x좌표값에 2만큼을 더한다. 
) 
(princ))

 

ssget 객체 선택(다중)

캐드의 객체를 선택하는 명령이다. 

우선 캐드의 text창에서 (ssget)라고 타이핑해보자. 
그러면 'Selete Object : '라고 선택하라고 나온다. 
선택하고 나면 그 결괏값도 텍스트 창에 출력된다. 

- ssget 적용예제 

객체를 선택하여서 색을 Green으로 바꾸어 보자. 

(defun c:test1() 
(prompt "\n녹색으로 바꿀 객체를 선택하시오. "); 화면에 메세지 표시 
(setq ent (ssget)); 객체를 선택하여 ent 라는 변수에 담아 둠 
(command "change" ent "" "p" "c" "green" "") 
; change 라는 모두다 아는 명령으로 ent의 색을 변화하는 부분 
; ent 위에 "" 는 객체를 선택후 엔터를 입력해야 선택을 종료하므로 표시를 꼭 해줘야 하고, 
; "green" 뒤의 ""를 삽입해야 change 명령을 종료한다. 
; 위의 "" 두 군데를 한번씩 삭제해 보면서 에러나는 모습을 확인하기 바란다. 
(princ))

 

entsel 객체 선택

(ssget)는 여러개를 선택할 수 있는 것과는 달리 entity 딱 한 개만 선택할 수 있다. 
이때, 선택한 entity와 선택한 점의 좌표를 돌려받을 수 있다. 

이것도 마찬가지로 캐드화면에서 그냥 (entsel)라고 타이핑해보자 
'Select object: '라는 메시지에서 entity 하나를 선택하면 
아래와 비슷한 글자가 나온다. 

(<Entity name: 29418260ea0> (10.9331 -7.29281 0.0))

이것도 ()안에 묶여 있고 LIST형태이다. 
name: 이것은 내가 선택한 entity 이름이고, 
(10.9331 -7.29281 0.0) 이것은 선택한 점의 좌표이다. 

- 예제를 통해 알아보자. 

<예제 1> 이번에도 한 개의 entity를 선택해서 색을 빨강으로 바꾸어 보자. 

(defun c:test2() 
(setq ent (entsel)) 
(command "change" ent "" "p" "c" "red" "") 
(princ))



<예제 2> 이번엔 선택한 entity를 빨강으로 변경하고 선택한 위치에 반지름 10인 원을 하나 그려보자. 

(defun c:test2() 
(setq ent (entsel)) 
(command "change" ent "" "p" "c" "red" "") 
(command "circle" (cadr ent) "10") 
(princ))



위에서 (10.9331 -7.29281 0.0)도 리스트이므로, 두 번째 좌표를 얻으려면 앞에서 강의했던 것과 같이 (car) 명령을 사용하면 첫 번째 리스트 요소를 (cadr) 명령을 사용하면 두 번째 리스트 요소 (즉, 좌표)를 얻을 수 있다. 

if~ 조건판단문


 (if (조건) (실행문 1) 
 (실행문 2) 
 ) 

1. (if) 명령문 
(조건) 이 참이면 (실행문 1)을 수행하고 거짓이면 (실행문 2)을 수행한다. 
 (실행문 2)는 생략될 수 있다. 

2. (조건) 이란? 
 (조건)은 판단 문이다. 즉 a=b , a>b , a<b , a<>b 등과 같다. 
여기서 주의할 점, 리습에서는 연산과 마찬가지로 조건 판단 문도 부호가 선행되고 비교 요소가 뒤에 나열된다. 
좌측은 일반적으로 쓰는 기호이고 우측은 리습에서 사용되는 조건문이다. 
a=b → (= a b)  a와 b가 같다 
a>b → (> a b)  a가 b보다 크다 
a<b → (< a b)  a가 b보다 작다 
a<>b→ (/= a b)  a와 b가 다르다 
a>=b→ (>= a b)  a가 b보다 크거나 같다 
a<=b→ (>= a b)  a가 b보다 작거나 같다 

<예제 1> 캐드 명령 창에서 다음과 같이 타이핑해보자. 

 (= 1 1) 

결괏값은 'T' 일 것이다. 참이라는 뜻이다. 

 <예제 2> 캐드 명령 창에서 다음과 같이 타이핑해보자. 

 (> 1 2) 

결괏값은 'nil' 일 것이다. 거짓이라는 뜻이다. 
 "F"로 나오지 않고 'nil'로 나오는 것에 유의하자. 

3. if문의 예제를 한번 보자. 

(defun c:test1() 
 (setq a 1 b 2 ) 
(if (> a b) 
 (setq c 3) ;a>b 인지 판단하여 참이면 c=3 
 (setq c 4) ;아니면 c=4 
) ;end if
) ;end fun



위를 실행시켜보면 a>b 는 거짓이므로 c의 값은 당연히 4이다. 
if문을 위에처럼 참일 경우와 거짓일 경우를 두줄로 나누어 쓰면 
보기에 편리하다. 위의 (if~) 문을 한 줄로 써보겠다. 

(if (> a b) (setq c 3) (setq c 4)) 

위와 같이 써도 실행엔 아무 문제가 없다. 하지만 코드가 길어지면 실수하기 쉽기에 구분지어서 코딩하는 연습을 해두자. 

4. 좀 더 유용한 예제를 해보자 

숫자 두 개를 받아서 두 번째 받아들인 숫자가 '0'이 아니면 첫 번째 숫자를 두 번째 숫자로 나누는 리습이다. 

(defun c:test3() 
(setq num1 (getreal "첫번째 숫자를 입력하시오 : ");첫번째 실수 입력받음 
       num2 (getreal "두번째 숫자를 입력하시오 : ");두번째 실수 입력받음 ) 
(if (/= num2 0) (setq num3 (/ num1 num2));두번째숫자가 '0'이 아니면 나누기 
(prompt "0으로 나눌수 없습니다.") ;'0'이면 메세지 출력 
) ;end if
(princ num3)
(princ)
)
반응형

progn~ 조건 판단 문의 그룹화


1. (progn~) 
 (progn~)은 (if~) 문과 함께 쓰이며 명령어들을 그룹화하여 
 묶어 주는 역할을 한다. 

2. 왜 (progn)으로 묶어 주어야 하는가? 

 (if 조건 (실행문 1) 
(실행문 2) 
 ) 

여기서 (실행문 1)과 (실행문 2)는 하나의 괄호() 안에 묶여 있었다. 
그러나 하나의 명령어가 아니라 여러 개를 작성할 때 (progn)으로 묶어 줄 때 사용한다.

3. 다음의 예제에서 확인해보자.  

 우리는 a<b 판단이 참인 경우 c=3, d=4 로 만들어 주고  거짓이면 e=5, f=6 으로 해주어 보자. 

 <예제 1> 

(defun c:test1() 
 (setq a 1) ; a=1 
 (setq b 2) ; b=2 
  (if (< a b) (setq c 3) ; 참이면 c=3 
  (setq d 4) ; 참이면 d=4를 실행하고 싶지만 프로그램은 거짓이면 d=4 를 실행한다.
  (setq e 5) ; 참과 거짓을 다 판단했는데 다시 ()가 나와서 에러 
  (setq f 6) ; 물론 에러 
  ) ; end if
 ) 

 <예제 2> 

(defun c:test2() 
 (setq a 1) ; a=1 
 (setq b 2) ; b=2 
 (if (< a b) ; a<b 인가? 판단. 당연히 참(1<2) 
 (progn ; 참이면 (progn)으로 묶인 구문 실행 
  (setq c 3) ; 참일 때 실행 c=3 
  (setq d 4) ; 참일 때 실행 d=4 
  ) 
 (progn ; 거짓일 때 (progn)으로 묶인 구문 실행 
  (setq e 5) ; 거짓일 때 e=5 
  (setq f 6) ; 거짓일때 f=6 
  ) 
 ) ; end  if
 ) 

위의 예제에서 <예제 1>은 에러가 난다. 
왜냐하면 (if) 문은 두 개의 괄호()만을 받아들여서 참과 거짓일 때 각각 실행하는데 
<예제 1>은 (if) 문 안에 괄호가 4개나 있다. 
그러기 때문에 <예제 2>와 같이 (progn)으로 그룹으로 만들어서 묶어주면 
(if) 문은 (progn)으로 묶인 모든 명령을 실행한다. 
좀 말이 어려웠다. 아래의 예제를 보면서 다시 이해해 보자. 

4. 예제 

 두 개의 숫자를 입력받아서 a >= b 이면 c = a - b , d = "[a > b]"를 
a <= b 이면 c = b - a , d = "[a < b]"를 출력하는 리습을 만들어 보자. 

(defun c:test3() 
 (setq a (getreal "\n1st Number :")); \n한줄넘기기 기호 
 (setq b (getreal "\n2nd Number :")) 
 (if (>= a b) 
  (progn; 참일때 실행하는 그룹 
   (prompt "a - b = ") 
   (setq c (- a b)) 
   (setq d " [a > b]") 
   (princ c) 
   (prompt d) 
  ); end of 참 progn 
  (progn; 거짓일때 실행하는 그룹 
   (prompt "b - a = ") 
   (setq c (- b a)) 
   (setq d " [a < b]") 
   (princ c) 
   (prompt d) 
  ); end of 거짓 progn 
 ); end of if 
(princ))



5. 조건이 참일 때만 실행하고 거짓일 때는 다음 구문으로 보낼 때 

(if) 문에서 거짓일 때의 실행 구문을 생략할 수 있다. 
아래와 같이 거짓일 때 실행할 문이 없다면 그냥 (if)의 괄호를 닫아버리자. 

 (if 조건문 
(progn 
 (참 실행문 1) 
 (참 실행문 2) 
 (참 실행문 3) 
 ) 
 ) 

 <예제 1> 입력한 숫자가 10보다 클 때만 텍스트 창에 "O.K."와 
"에러가 없습니다" 글 보내기 

(defun c:test4() 
 (setq a (getreal "숫자를 입력하시오 " )) 
 (if (> a 10) 
(progn 
 (prompt "\nO.K") ; \n은 한 줄 넘기기 기호 
(prompt "\n에러가 없습니다") 

 ) 
(princ)) 

 

조건문 cond


(cond ~)문은 조건이 여러 가지 있을 경우에 사용하면 좋다. 
(if~) 문의 연속이라고 보아도 좋다.
다른 언어의 select case문과 같다

예제를 보면서 익혀보겠다. cond 다음의 괄호 개수를 유념하자. 

1. (cond~)의 예제 

아래의 예제는 1~5 사이의 숫자를 입력받아서 받은 숫자를 다시 "a="와 
함께 입력받은 숫자를 표시하고 1~5 밖의 숫자면 "Out of Range."라고 
표시하는 리습이다. 

(defun c:test1() 
(setq a (getint "input number (1~5) : ")) 
(cond 
((= a 1) (prompt "a=1")) ;조건1 (a=1)일경우만 수행 
((= a 2) (prompt "a=2")) ;조건2 (a=2)일경우만 수행 
((= a 3) (prompt "a=3")) ;조건3 (a=3)일경우만 수행 
((= a 4) (prompt "a=4")) ;조건4 (a=4)일경우만 수행 
((= a 5) (prompt "a=5")) ;조건5 (a=5)일경우만 수행 
((prompt "Out of range."))  

(princ)) 

2. 위의 1번 예제를 (if~) 문으로 구현해 보자. 

(defun c:test2() 
(setq a (getint "input number (1~5) : ")) 
(if (= a 1) (prompt "a=1")) ;조건1 (a=1)일경우 
(if (= a 2) (prompt "a=2")) ;조건2 (a=2)일경우 
(if (= a 3) (prompt "a=3")) ;조건2 (a=3)일경우 
(if (= a 4) (prompt "a=4")) ;조건2 (a=4)일경우 
(if (= a 5) (prompt "a=5")) ;조건2 (a=5)일경우 
(if (or (< a 1) (> a 5)) 
(prompt "Out of range.") 

(princ)) 


3. 다중 (if~)문으로도 사용할 수 있다. 
위의 예제와 비슷하지만, 위의 예제는 a 값에 따라 각각 한 줄씩 
모두 체크한다. 
하지만 아래의 예제는 거짓일 때만 다음 줄로 순서가 넘어가며 
참이면 결괏값을 출력하고 (if) 문을 그대로 빠져나간다. 

(defun c:test3() 
(setq a (getint "input number (1~5) : ")) 
(if (= a 1) (prompt "a=1"); a=1 일 때만 수행하고 (if) 종결 
(if (= a 2) (prompt "a=2"); a=1 이 아니면 수행 
(if (= a 3) (prompt "a=3"); a=1 도 a=2도 아니면 수행 
(if (= a 4) (prompt "a=4"); a=3 도 아니면 수행 
(if (= a 5) (prompt "a=5"); a=4도 아니면 수행 
(prompt "Out of Range"); a=5도 아니면 수행 
 ) 
 ) 
 ) 
 ) 

(princ)) 

while 반복문

 

(while (조건) 
 (실행문 1) 
 (실행문 2) 
 (실행문 3) 
......... 
 ) 

조건이 참이면 실행문을 계속 실행한다. 
달리 말해서 거짓일 때까지 while문이 실행된다.

2. 예제 1 

1부터 100까지 더하는 리습을 구현해 보자. 

(defun c:test1() 
 (setq sum 0) ; sum 변수는 합계를 의미하는 변수, 0으로 초기화 
 (setq a 1) ; 더해질 숫자 a 를 0 으로 초기화 
 (while (< a 101); a가 100보다 작으면 실행문(더하기)을 실행 
  (setq sum (+ sum a)); 현재의 합에 a 값을 더함 
  (setq a (1+ a)); 현재의 a 값에 1 더함 
 ) ;end while  
 (prompt "\nSum=") 
 (princ sum) 
 (princ))

  

3. 예제 2 

위의 예제 1을 (repeat) 함수로 한번 구현해 보자  

(defun c:test2() 
 (setq sum 0) 
 (setq a 1) 

 (repeat 100 
 (setq sum (+ sum a)) 
 (setq a (+ 1 a)) 
 ) 

 (prompt "\nSum=") 
 (princ sum) 
 (princ))



3. 예제 3 

사용자가 숫자 입력을 하도록 해보자. 
숫자 입력을 하지 않고 엔터를 누르면 계속적으로 숫자를 입력하라고 요구해보자. 

(defun c:test3() 
 (setq a nil); a값을 초기값을 nil로 한다. 
 (while (= a nil);a값이 nil이면 계속 input 요청 
 (setq a (getreal "Input Number : ")) 
 ) 
)

  

아무 입력 없이 엔터나 스페이스를 누르면 nil값을 반환한다. 그걸 이용한 것이다. 

반응형

'프로그래밍 > LISP' 카테고리의 다른 글

LISP 6.  (0) 2021.10.27
LISP 5.  (0) 2021.10.20
LISP 3.  (1) 2021.10.13
LISP 2.  (0) 2021.10.09
LISP 1.  (0) 2021.10.06
댓글