키스맥 - 4th Dimension 매킨토시 전문 웹 매거진 웹진

  + 파일메이커 기초편
  + 4th Dimension
  + 리얼베이직
  + OS X 10.3
  + 홈페이지 만들기
  + 포토샵 강좌
  + 디카 완전정복
  + 실무로 배우는 Quark
  + MLayout
  + iPod 강좌
  + html 강좌
  + 간단매뉴얼&팁
  + 5세대 iPod 강좌
  + iTunes 한 컷 강좌
  + iPod 한컷강좌
            


Chapter16. 4D의 지정 연산자와 컴파일러 지시어


이번 시간에는 4th Dimension의 지정 연산자와 컴파일러 지시어에 대하여 살펴보도록 하겠습니다. 사실 오늘 배우게 되는 내용은 조금 머리아플지도 모르겠습니다.^^ 하지만 최대한 쉬운 말로 표현하도록 노력하겠습니다. 더불어 간단한 문법에 대한 실제 예제도 함께 첨부하였습니다.

학습 순서 1 : 지정 연산자와 컴파일러 지시어.
학습 순서 2 : 질문 및 답변.



1. 지정 연산자와 컴파일러 지시어.


4th Dimension에서 사용하는 지정 연산자 기호는 ":=" 부호의 조합으로 사용합니다. 사용 예제는 아래와 같습니다.

예제 1)
NumberTotal := 1 + 3

지정 연산자를 기준으로 오른쪽에 있는 내용을 왼쪽에 있는 변수(Variable)에 넣고자 할 때 사용합니다.

변수 : 값이 변하는 수 (NumberTotal)
상수 : 값이 변하지 않는 고정적인 수 (1 + 3)

일반적으로 변수는 개발자의 필요에 의해 마음껏 만들어질 수 있습니다. 그렇다고 해서 무조건 만들수는 없고 컴파일러(Compiler) 지시어를 먼저 선언하고 변수를 사용하는 방법을 권장하고 싶습니다.

한가지 예를 들지요. 만약에 여러분이 변수 하나를 만든다고 가정합시다. 그런데 컴퓨터는 여러분이 어떤 변수를 만들지 전혀 예상을 하지 못합니다. 숫자가 들어가는 변수를 만들지 또는 문자가 들어가는 변수를 만들지 또는 날짜가 들어가는 변수를 만들지... 등등을 말입니다. 그러므로 4th Dimension은 맨 처음 만들어진 변수에 들어오는 값을 기준으로 변수 타입(Variable Type)을 자동으로 지정하게 됩니다.

예제 2)
NameID := "ABCDEFG"

위의 예제에서 등장하는 변수명은 "NameID"가 됩니다. 그리고 "ABCDEFG"라는 문자열은 문자열 상수가 되고요.
위 예제 문장은 "ABCDEFG"라는 문자열 상수를 "NameID" 변수 속에 넣겠다는 뜻이 되므로 4th Dimension은 "NameID" 변수를 자동적으로 문자열 변수로 인식하게 됩니다. 하지만 곧바로 "NameID" 변수의 타입(Type)을 미리 지정하지 않았다는 것을 눈치채고 "NameID" 변수를 강제적으로 Text Type으로 지정해 버립니다.

String Type : 영문을 기준으로 255 글자까지만 인식합니다.
Text Type : 영문을 기준으로 32,000 글자까지만 인식합니다.

예제 2번에서 보는 것과 같이 "ABCDEFG" 문장은 7 글자 밖에 안됩니다. 그런데 컴파일러(Compiler) 지시어를 먼저 선언하지 않았으므로 4th Dimension은 "NameID" 변수의 타입을 32,000 글자까지 입력이 가능한 텍스트 타입(Text Type) 속성으로 지정해 버립니다. 이렇게 되면 메모리(Memory 또는 Ram)의 낭비가 되겠지요? 이런 변수가 수십개에서 수백개 사용되었다면 그 낭비되는 용량이 얼마나 많겠습니까. 이와 같은 이유로 변수를 만들기 앞서 미리 변수 선언을 먼저 하는 습관을 들이시면 좋습니다. 이를 적용한 예제는 아래와 같습니다.

예제 3)
C_STRING (7;NameID)

NameID := "ABCDEFG"

이와 같이 C_STRING이라는 컴파일러(Compiler) 지시어를 통해 먼저 변수를 선언하고(개발자가 만들어 사용할 변수 이름과 크기) 사용하는 것이 바람직합니다. 만약에 255글자가 넘는 문장을 넘겨받을 필요가 있을 때에는 32,000글자까지 인식이 가능한 C_TEXT 컴파일러 지시어를 사용해야할 것입니다. ^^

C_TEXT (MemoText)
MemoText := "동해물과 백두산이 마르고 닳도록 하나님이 보우하사 우리나라 만세..."

예제 4)
C_STRING (4;NameID)

NameID := "ABCDEFG"

위의 예제를 설명하면 다음과 같습니다. "NameID"라는 스트링 변수를 4글자까지만 인식하도록 미리 선언했습니다. 그런데 "NameID" 변수에 집어넣을 단어는 "ABCDEFG" 문장으로 총 7글자입니다. 그렇다면 "NameID"라는 스트링 변수에는 "ABCD"라는 4글자만 들어가게 됩니다. 이해가 되시지요?

그리고 제가 사용하는 실제 변수 선언 방법은 아래와 같습니다.

예제 5) 스트링 변수 만들때의 팁
C_STRING (7;vs07_NameID)

vs07_NameID := "ABCDEFG"

맨 앞의 v라는 글자는 Variable의 약자이고 s라는 글자는 컴파일러 지시어 C_STRING Type의 약자입니다. 합쳐서 vs가 되는거지요. 그리고 07이라는 것은 7글자까지만 허용하도록 한다는 정보를 함께 적어둔 것입니다. 이렇게 변수명을 작성하는 습관을 들여놓으면 수백개의 변수 가운데 하나의 변수 이름만 보더라도 이것은 어느 타입이며 그 길이는 어느정도인지를 한눈에 알아볼 수 있게 됩니다. 즉, 버그가 생겼을 때 이해가 빠르므로 쉬운 수정이(디버깅) 가능할 뿐 아니라 새로운 기능을 추가할 때에도 큰 도움을 얻을 수 있습니다.

예제 6) C_STRING 컴파일러 지시어의 실제 사용 예
C_STRING (6:vs06_Content1)
C_STRING (6;vs06_Content2)
C_STRING (12;vs12_Total)

vs06_Content1 := "동해물"
vs06_Content2 := "백두산"
vs12_Total := vs06_Content1 + vs06_Content2

참고 : 한글 1글자는 영문 2글자의 표시 영역과 같습니다.

결과 : 스트링 변수 "vs12_Total"의 최종 결과는 "동해물백두산"이 되겠습니다. 또 다른 방법은 아래와 같습니다

예제 7) C_STRING 컴파일러 지시어를 사용할 때의 팁
C_STRING (6;vs06_Content1;vs06_Content2)
C_STRING (12;vs12_Total)

vs06_Content1 := "동해물"
vs06_Content2 := "백두산"
vs12_Total := vs06_Content1 + vs06_Content2

참고 : C_STRING 컴파일러 지시어의 크기가 같을 때에는 ";" 구분자를 사용해서 옆으로 계속 입력하실 수 있습니다.

결과 : 스트링 변수 "vs12_Total"의 최종 결과는 "동해물백두산" 입니다. 똑같지요? ^^ 또 다른 방법은 아래와 같습니다.

예제 8) 문자열을 서로 조합할 때의 주의사항 1
C_STRING (12;vs12_Content1;vs12_Content2;vs12_Total)

vs12_Content1 := "동해물"
vs12_Content2 := "백두산"
vs12_Total := vs12_Content1 + vs12_Content2

참고 : "vs12_Content1", "vs12_Content2" 스트링 변수의 크기는 영문 기준으로 12글자이지만 실제 입력된 글자는 한글 3글자(영문으로는 6글자) 뿐입니다. 총 12글자를 넣을 수 있는 공간에 6글자만 들어간 셈이고 나머지 남은 부분은 자동적으로 인식하지 않습니다.

결과 : 스트링 변수 "vs12_Total"의 최종 결과는 "동해물백두산" 입니다.

예제 9) 문자열을 서로 조합할 때의 주의사항 2
C_STRING (10;vs10_Content1;vs10_Content2)
C_STRING (20;vs20_Total)

vs10_Content1 := "1234567890"
vs10_Content2 := "배워봅시다"
vs20_Total := vs10_Content1 + vs10_Content2

참고 : 따옴표 안에 기록된 숫자는 계산을 할 수 있는 숫자가 아닌 그냥 문자로 인식해 버립니다.

결과 : 스트링 변수 "vs20_Total"의 최종 결과는 "1234567890배워봅시다" 입니다.

예제 10) 소문자로 된 문자열을 대문자로 변경하기
C_STRING (5;vs05_Total)

vs05_Total := Uppercase ("abcde")

참고 : Uppercase 명령어는 소문자를 대문자로 전환할 때 사용합니다.

결과 : 스트링 변수 "vs05_Total"의 최종 결과는 "ABCDE" 입니다.

예제 11) 대문자로 된 문자열을 소문자로 변경하기
C_STRING (5;vs05_Total)

vs05_Total := Lowercase ("ABCDE")

참고 : Lowercase 명령어는 대문자를 소문자로 전환할 때 사용합니다.

결과 : 스트링 변수 "vs05_Total"의 최종 결과는 "abcde" 입니다.

예제 12) 덧셈 연산자
C_INTEGER (vi_Num1;vi_Num2;vi_NumTotal)

vi_Num1 := 100
vi_Num2 := 200
vi_NumTotal := vi_Num1 + vi_Num2

참고 1 : C_INTEGER 컴파일러 지시어는 숫자(2-byte Integer) -32,768~32,767까지의 정수 범위를 가지고 있습니다.
참고 2 : 덧셈 연산자 기호는 "+" 부호입니다.

결과 : 인티저 변수 "vi_NumTotal"의 최종 결과는 "300" 입니다.

예제 13) 뺄셈 연산자
C_INTEGER (vi_Num1;vi_Num2;vi_NumTotal)

vi_Num1 := 500
vi_Num2 := 300
vi_NumTotal := vi_Num1 - vi_Num2

참고 : 뺄셈 연산자 기호는 "-" 부호입니다.

결과 : 인티저 변수 "vi_NumTotal"의 최종 결과는 "200" 입니다.

예제 14) 곱셈 연산자
C_INTEGER (vi_Num1;vi_Num2;vi_NumTotal)

vi_Num1 := 5
vi_Num2 := 2
vi_NumTotal := vi_Num1 * vi_Num2

참고 : 곱셈 연산자 기호는 "*" 부호입니다.

결과 : 인티저 변수 "vi_NumTotal"의 최종 결과는 "10" 입니다.

예제 15) 나눗셈 연산자
C_INTEGER (vi_Num1;vi_Num2;vi_NumTotal)

vi_Num1 := 5
vi_Num2 := 2
vi_NumTotal := vi_Num1 / vi_Num2

참고 : 나눗셈 연산자 기호는 "/" 부호입니다.

결과 : 인티저 변수 "vi_NumTotal"의 최종 결과는 "2.5" 입니다.

예제 16) 정수 나눗셈 연산자
C_INTEGER (vi_Num1;vi_Num2;vi_NumTotal)

vi_Num1 := 5
vi_Num2 := 2
vi_NumTotal := vi_Num1 vi_Num2

참고 : 정수 나눗셈 연산자 기호는 "" 부호입니다.

결과 : 인티저 변수 "vi_NumTotal"의 최종 결과는 "2" 입니다.

주의 : 정수 나눗셈 연산자는 한글 로컬라이징 과정에서 Case of ~ End Case 의 조건 구분자(키워드) "" 기호와 동일(중복 및 충돌)하므로 사용할 수 없습니다. 할 수 없이 이 부분만큼은 아래와 같은 편법을 사용하셔야 합니다.

예제 17) 정수 나눗셈을 구현하는 편법
C_INTEGER (vi_Num1;vi_Num2;vi_NumTotal)

vi_Num1 := 5
vi_Num2 := 2
vi_NumTotal := vi_Num1 / vi_Num2
vi_NumTotal := Int(vi_NumTotal)

참고 : Int 명령어는 소숫점을 제외한 정수 부분만 돌려줍니다.

결과 : 인티저 변수 "vi_NumTotal"의 최종 결과는 "2" 입니다. 그러면 Int 명령어의 또 다른 사용법을 보시겠습니다.

예제 18) 정수 명령어
C_INTEGER (vi_NumTotal1;vi_NumTotal2)

vi_NumTotal1 := Int(123.4)
vi_NumTotal2 := Int(-123.4)

결과 1 : 인티저 변수 "vi_NumTotal1"의 최종 결과는 "123" 입니다.

결과 2 : 인티저 변수 "vi_NumTotal2"의 최종 결과는 "-124" 입니다.

예제 19) 나머지 연산지
C_INTEGER (vi_Num1;vi_Num2;vi_NumTotal)

vi_Num1 := 5
vi_Num2 := 2
vi_NumTotal := vi_Num1 % vi_Num2

참고 : 나머지 연산자 기호는 "%" 부호입니다.

결과 : 인티저 변수 "vi_NumTotal"의 최종 결과는 "1" 입니다.

예제 20) 지수 연산자
C_INTEGER (vi_Num1;vi_Num2;vi_NumTotal)

vi_Num1 := 2
vi_Num2 := 3
vi_NumTotal := vi_Num1 ^ vi_Num2

참고 : 지수 연산자 기호는 "^" 부호입니다.

결과 : 인티저 변수 "vi_NumTotal"의 최종 결과는 "8" 입니다.

예제 21) 일반적인 연산자 우선순위
C_INTEGER (vi_NumTotal)

vi_NumTotal := 3 + 4 * 5

참고 : 연산자의 우선순위는 왼쪽에서 오른쪽 순서로 차례대로 계산됩니다. (기본값)

결과 : 표현식 3+4가 먼저 계산되고(7) 거기에 5를 곱하므로 인티저 변수 "vi_NumTotal"의 최종 결과는 "35" 입니다.

예제 22) 괄호 기호가 있는 연산자의 우선순위
C_INTEGER (vi_NumTotal)

vi_NumTotal := 3 + (4 * 5)

참고 : 괄호 기호가 사용되었을 때에는 왼쪽에서 오른쪽으로 계산되는 우선순위가 무시됩니다. 즉, 괄호부터 계산합니다.

결과 : 표현식 4*5가 먼저 계산되고(20) 거기에 3를 더하므로 인티저 변수 "vi_NumTotal"의 최종 결과는 "23" 입니다.

이번에는 스트링 변수에 대한 재미있는 보너스입니다. ^^

예제 23) 같은 문자열의 반복
C_STRING (10;vs10_Total1;vs10_Total2)

vs10_Total1 := "ab"*5
vs10_Total2 := "AB"*5

결과 1 : 스트링 변수 "vs10_Total1"의 최종 결과는 "ababababab" 입니다.
결과 2 : 스트링 변수 "vs10_Total2"의 최종 결과는 "ABABABABAB" 입니다.

예제 24) 정수 상수와 문자 상수를 서로 더할 때
C_INTEGER (vi_Number)
C_STRING (5;vs05_Content)
C_STRING (10;vs10_Total)

vi_Number := 12345
vs05_Content := "abCDE"
vs10_Total := string(vi_Number) + vs05_Content

참고 : string 명령어는 숫자의 값을 강제적으로 문자로 인식하도록 변환합니다.

결과 : 스트링 변수 "vs10_Total"의 최종 결과는 "12345abCDE" 입니다.

주의 : vs10_Total := vi_Number + vs10_Content 이와 같은 문법은 에러를 발생합니다. ^^ 반드시 vi_Number 상수를 string 명령어로 감싸주어야 합니다.

예제 25) 이번에는 날짜 변수를 가지고 계산해 보도록 하겠습니다. ^^
C_DATE (vd_Date1;vd_Date2;vd_DateTotal)

vd_Date1 := !03.11.30!
vd_Date2 := !03.11.20!
vd_DateTotal:=vd_Date1-vd_Date2

참고 1 : 날짜 상수의 기호는 "!" 마침표 부호를 사용합니다.
참고 2 : 년도, 월, 일 사이의 구분자로는 "/" 또는 "." 기호를 사용합니다.
참고 3 : 년도는 2003이라고 입력하셔도 되고, 그냥 03이라고 세기년도를 생략하셔도 똑같이 인식합니다.
참고 4 : 2003.06.03 또는2003.6.3 또는 03.6.3 또는 03.06.03 모두 같은 내용이 되겠습니다.
참고 5 : 2003/06/03 또는2003/6/3 또는 03/6/3 또는 03/06/03 모두 같은 내용이 되겠습니다.

결과 : 날짜 변수 "vd_DateTotal"의 최종 결과는 "10" 입니다.

예제 26) 날짜 상수와 정수 상수를 더할 때
C_DATE (vd_Date;vd_DateTotal)
C_INTEGER (vi_DayNumber)

vd_Date := !03.11.20!
vi_DayNumber := 5
vd_DateTotal:=vd_Date+vi_DayNumber

결과 : 날짜 변수 "vd_DateTotal"의 최종 결과는 "03.11.25" 입니다.

예제 27) 날짜 상수와 정수 상수를 뺄 때
C_DATE (vd_Date;vd_DateTotal)
C_INTEGER (vi_DayNumber)

vd_Date := !03.11.20!
vi_DayNumber := 5
vd_DateTotal:=vd_Date-vi_DayNumber

결과 : 날짜 변수 "vd_DateTotal"의 최종 결과는 "03.11.15" 입니다.

예제 28) 이번에는 시간 변수를 가지고 계산해 보도록 하겠습니다. ^^
C_TIME (vh_Time1;vh_Time2;vh_TimeTotal)

vh_Time1 := ?13:05:30?
vh_Time2 := ?2:03:20?
vh_TimeTotal:=vh_Time1-vh_Time2

참고 1 : 시간 상수의 기호는 "?" 물음표 부호를 사용합니다.
참고 2 : 시간 사이의 구분자로는 ":" 기호를 사용합니다.
참고 3 : 시간의 주기는 24시간을 원칙으로 하며 계산할 때의 15시는 우리가 일반적으로 말하는 오후(PM) 3시를 가르킵니다.
참고 4 : 02:03:20(시:분:초) 또는 2:3:30 모두 같은 표현이 되겠습니다.

결과 : 시간 변수 "vh_TimeTotal"의 최종 결과는 "11:02:10" 입니다. 오전 11시 2분 10초를 뜻합니다. ^^

주의 1 : 시간 상수의 기호 "?" 물음표 기호는 로컬라이징되는 과정에서 역시 손실되었습니다.
주의 2 :그러므로 위 문장중 vh_Time1 := ?13:05:30? 이 부분까지 입력하시고 키보드의 리턴(Return) 키를 눌러 다음줄로 넘어가면 vh_Time1:=13530 이와 같이 엉뚱하게 변형되어 화면에 나타납니다.
주의 3 : 계속해서 위 문장중 vh_Time2 := ?2:03:20? 이 부분까지 입력하시고 키보드의 리턴(Return) 키를 눌러 다음줄로 넘어가면 vh_Time2:=2320 이와 같이 엉뚱하게 변형되어 화면에 나타납니다.
할 수 없이 아래의 편법을 사용하셔야 합니다. ^^

예제 29) 시간 상수끼리 뺄 때
C_TIME (vh_Time1;vh_Time2;vh_TimeTotal)

vh_Time1 := time("13:05:30")
vh_Time2 := time("2:03:20")
vh_TimeTotal:=vh_Time1-vh_Time2

참고 : time 명령어는 따옴표 안에 서술한 문자열을 시간 상수로 강제적으로 변환합니다.

결과 : 시간 변수 "vh_TimeTotal"의 최종 결과는 "11:02:10" 입니다. 오전 11시 2분 10초를 뜻합니다. ^^

예제 30) 시간 상수끼리 더할 때
C_TIME (vh_Time1;vh_Time2;vh_TimeTotal)

vh_Time1 := time("10:05:30")
vh_Time2 := time("1:3:20")
vh_TimeTotal:=vh_Time1+vh_Time2

결과 : 시간 변수 "vh_TimeTotal"의 최종 결과는 "11:08:50" 입니다. 오전 11시 8분 50초를 뜻합니다. ^^

예제 31) 시간 상수와 정수 상수를 서로 더할 때
C_TIME (vh_Time;vh_TimeTotal)
C_INTEGER (vi_Number)

vh_Time := time("6:00:00")
vi_Number := 180
vh_TimeTotal:=vh_Time+vi_Number

참고 : 1분은 60초이므로 "vi_Number" 인티저 변수에 들어간 180이란 숫자는 180초로 인식됩니다.

결과 : 시간 변수 "vh_TimeTotal"의 최종 결과는 "06:03:00" 입니다.


마지막으로, 컴파일러 지시어의 종류는 총 12가지입니다.


C_BLOB
C_INTEGER
C_REAL
C_BOOLEAN

C_LONGINT
C_STRING
C_DATE
C_PICTURE

C_TEXT
C_GRAPH
C_POINTER
C_TIME


이것에 대한 보다 자세한 내용은 4D_683_Language_Ref.pdf 문서의 319 페이지에 자세히 나와 있습니다. 비록 영문으로 되어 있지만 꼭 한번 시간을 내어 대충이라도 살펴보시기를 권장합니다.

2. 질문 및 답변

질문 1) 소문자 "a" 알파벳과 대문자 "A" 알파벳 글자는 서로 같은건가요?


답변 1) 다음 시간에 배우게 될 내용을 미리 질문하셨네요. ^^ 기본적으로 스트링 값이 비교될 때의 영문 대소문자는 서로 무시됩니다.
즉, "a" = "A" 이 문법은 서로 같다는 뜻이 되며 그 결과는 True(참) 입니다.
만약에 대소문자를 비교하기 원하신다면 Ascii 명령어를 사용하시면 되겠습니다.
Ascii("a") = Ascii("A") 이와 같이 사용할 수 있으며 이 문법의 결과는 False(거짓) 입니다. 아래의 예제를 한번 더 보시기 바랍니다.

C_INTEGER (vi_AsciiCode1;vi_AsciiCode2;vi_AsciiCode3;vi_AsciiCode4)

vi_AsciiCode1:=Ascii("A")
vi_AsciiCode2:=Ascii("a")
vi_AsciiCode3:=Ascii("ABC")
vi_AsciiCode4:=Ascii("abc")

결과 1 : vi_AsciiCode1 변수의 최종 결과는 숫자 65 입니다.
결과 2 : vi_AsciiCode2 변수의 최종 결과는 숫자 97 입니다.
결과 3 : vi_AsciiCode3 변수의 최종 결과는 숫자 65 입니다. (첫번째 문자의 코드만 돌려줍니다.)
결과 4 : vi_AsciiCode4 변수의 최종 결과는 숫자 97 입니다. (첫번째 문자의 코드만 돌려줍니다.)


질문 2) 와일드 문자 "@" 기호도 사용할 수 있나요?

답변 2) 좋은 것을 질문하셨습니다. 와일드 카드 문자 기호인 "@" 부호는 "무엇 무엇을 포함하는 모든 것~" 이러한 뜻을 가지고 있으며 사용 예는 아래와 같습니다.
"abcde" = "ab@" 이 문법은 서로 같다는 뜻이 되며 그 결과는 True(참) 입니다. 하지만 주의하셔야 할 사항이 한가지 있습니다.
"ab@" = "abcde" 이 문법의 결과는 False(거짓) 입니다. 왜냐하면 와일드 카드 문자 "@" 기호는 비교 표현식에서 "=" 기호를 기준으로 오른쪽에만 사용할 수 있기 때문입니다.
비교 연산자 기호 "=" 왼쪽에 "@" 기호가 사용될 때에는 와일드 카드 문자가 아닌 그냥 특수문자가 포함된 "ab@" 단어로 인식하기 때문입니다. 질문하신 내용을 보아 데이타베이스 프로그램을 다루셨던 분으로 예상되네요. ^^



다음글 - Chapter18. 샘플을 통한 문법 및 명령어 적용하기
현재글 - Chapter16. 4D의 지정 연산자와 컴파일러 지시어
이전글 - Chapter15. 아웃품-폼에 몇가지 기능 버튼