티스토리 뷰
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값을 반환한다. 그걸 이용한 것이다.