Programming/TclTk
TCL 자료 구조
Hunveloper
2022. 9. 2. 11:51
728x90
TCL 자료 구조
TCL의 자료 구조
- TCL의 기본적인 자료 구조는 String
- TCL에는 리스트와 배열의 두 가지 자료 구조가 더 존재
- 리스트는 스트링으로 구현되며 구조는 스트링 문법에 의해 정의
- 문법은 일반 명령의 경우와 같으며, 명령도 리스트의 일종
- 배열은 index를 가지는 변수
- index또한 스트링 값이기에 배열은 하나의 스트링(index)로부터 다른 스트링(배열 원소의 값)의 대응이라고 생각할 수 있음
- 작은 자료의 경우 리스트가 적당, 큰 자료의 경우 배열이 적당
변수의 사용
puts [set var {the value of var}]
#var = "the value of var"
puts [set name var]
#name = var
puts [set name]
#name = var
puts [set $name]
#name = "the value of var"
- set 명령에서 값을 주지 않으며 변수의 값만을 출력
- 변수 이름 앞에 $를 붙이는 경우와 붙이지 않는 경우를 구분해야 함
- unset 명령을 사용해 변수를 제거
unset varName varName2 ...
- info exist 명령을 통해 변수가 존재하는지 확인 가능
if ![info exists foobar] {
set foobar 0
} else {
incr foobar
}
#0
set foobar 2
if ![info exists foobar] {
set foobar 0
} else {
incr foobar
}
#3
리스트
- TCL에서의 리스트는 스트링이 whitespace로 구분된 형태
- { }나 “ “가 grouping을 위해 사용될 수 있음
- 자주 사용되는 긴 길이의 리스트는 배열로 바꾸는 것이 바람직
- 리스트와 관련된 명령어
- list arg1 arg2 ... : 리스트 생성
- lindex list i : i번째 원소 반환
- llength list : list의 길이 반환
- lrange list i j : 리스트의 i번째부터 j번째 원소들을 반환
- lappend listVar arg arg ... : listVar에 원소 추가
- linsert list index arg arg ... : list의 index번째 원소 앞에 새로운 원소를 추가
- lreplace list i j arg arg ... : list의 i부터 j까지의 원소를 새로운 원소들로 바꾼다.
- lsearch mode list value : list에서 value와 일치하는 원소를 찾아 위치를 반환. mode는 -exact, -glob, -regexp 중의 하나이며 -glob가 기본값
- lsort switches list : list를 정렬. switches에는 sort 방법을 주게 되는데, -ascii, -integer, -real, -increasing, -decreasing, -command 중의 하나
- concat arg arg arg : 리스트 병합
- join list joinString : list의 원소를 joinString으로 구분해 병합
- split string splitChars : splitChars을 원소 간의 경계로 생각해 string을 리스트 원소로 분할
리스트 만들기 : list, lappend, concat
- list 명령은 인자들을 원소로 가지는 새로운 리스트를 생성
puts [set x {1 2}]
puts [set x]
puts [list $x \$ foo]
#1 2
#1 2
#{1 2} {$} foo
- lappend 명령은 리스트의 마지막에 원소를 추가하기 위해 사용
puts [lappend new 1 2]
puts [lappend new 3 "4 5"]
puts [set new]
#1 2
#1 2 3 {4 5}
#1 2 3 {4 5}
- concat 명령은 리스트를 합치는데 사용
puts [set x {4 5 6}]
puts [set y {2 3}]
puts [set z 1]
puts [concat $z $y $x]
#4 5 6
#2 3
#1
#1 2 3 4 5 6
- list 명령과 concat 명령을 구분할 필요가 있음
- list나 lappend 명령은 리스트 구조를 유지하지만 concat 명령은 list 구조를 없앤 후 합침
리스트의 원소 얻기 : llength, lindex, lrange
- llength 명령은 리스트의 원소 개수를 반환
puts [llength {a b {c d} "e f g" h}]
#5 // a, b, {c d}, "e f g", h 5개
- lindex 명령은 리스트의 특정 원소를 반환
- 첫 번째 인자로 index를 받으며 index는 0부터 시작
- index 대신에 end키워드를 사용하여 리스트의 마지막 원소를 정할 수 있음
- end 키워드는 lindex, linsert, lrange, lreplace 명령에 유효
puts [lindex {11 22 33} 1]
#22
puts [lindex {11 22 33} end]
#33
- lrange 명령은 리스트의 특정 범위 원소를 반환
puts [lrange {1 2 3 {4 5}} 2 end]
#3 {4 5}
리스트의 수정 : linsert, lreplace
- linsert 명령은 리스트의 특정 위치에 원소를 삽입
- index가 0 이하이면 리스트의 맨 처음에 삽입
- index가 리스트 크기보다 크면 리스트의 마지막에 추가
- index가 0보다 크고 리스트의 크기보다 작으면 index번째 원소의 앞에 삽입
- lreplace는 리스트의 특정 범위에 있는 원소들을 새로운 원소들로 변경
- 새로운 원소를 인자로 주지 않으면 특정 범위의 원소가 삭제
- linsert나 lreplace는 기존의 리스트를 변경하지는 않고 변경된 리스트를 반환만 함
puts [linsert {1 2} 0 new stuff]
#new stuff 1 2
puts [set x [list a {b c} e d]]
puts [linsert $x 0 zzzz]
puts $x
#a {b c} e d
#zzzz a {b c} e d
#a {b c} e d
puts [set x [list a {b c} e d]]
puts [lreplace $x 1 2 B C]
puts [lreplace $x 0 0]
#a {b c} e d
#a B C d
#{b c} e d
리스트에서 원소 찾기
- lsearch는 리스트에서 특정 원소의 list index를 반환
- 존재하지 않는 경우는 -1을 리턴
- glob 모드의 패턴 매칭이 기본 값
- 패턴 매칭 방법을 바꾸기 위해서는 -exact나 -regexp 등의 옵션을 사용
lsearch {here is a list} l*
#3
- lreplace 명령은 새로 넣고 싶은 원소가 이미 리스트에 포함되어 있는지를 확인하기 위해 보통 lsearch 명령과 함께 사용
proc ldelete { list value } {
set ix [lsearch -exact $list $value]
if {$ix >= 0} {
return [lreplace $list $ix $ix]
} else {
return $list
}
}
set x {A1 A2 A3 A4}
puts $x
#A1 A2 A3 A4
puts [ldelete $x A1]
#A2 A3 A4
리스트의 sort
- lsort 명령을 사용하면 다양한 방법으로 리스트를 정렬할 수 있음
- 세 가지 기본적인 소팅 방법은 -ascii, -integer, -real
- -increasing이나 -decreasing은 오름차순 정렬, 내림차순 정렬
- 기본 옵션은 -ascii -increasing임
- 사용자 정의 sorting 함수도 생성 가능함
proc mycompare {a b} {
set alast [lindex $a end]
set blast [lindex $b end]
set res [string compare $alast $blast]
if {$res != 0} {
return $res
}
else{
return [string compare $a $b]
}
}
puts [set rist [list {Eung Do Kim} {Hyo Jun Im} {Woo Joo Lee}]]
puts [lsort -command mycompare $rist]
#{Eung Do Kim} {Hyo Jun Im} {Woo Joo Lee}
#{Hyo Jun Im} {Eung Do Kim} {Woo Joo Lee}
split과 join 명령
- split 명령은 스트링을 입력받아 특정 문자를 구분자로 생각하여 리스트를 만들어냄
split string seperator
- split 명령은 사용자 입력을 TCL이 처리하기 쉬운 형태로 바꾸는 데 사용할 수 있음
set line {welch:*:3116:100:Brent Welch:/usr/welch:/bin/csh}
puts [split $line :]
#welch * 3116 100 {Brent Welch} /usr/welch /bin/csh
set line {this is \"not a tcl list}
puts [lindex $line 2]
#"not
puts [split $line]
#this is {\"not} a tcl list
- split 명령의 기본 구분자는 공백 문자
- 구분 문자가 두 개 이상 연달아 오면 그 사이는 빈 리스트로 표시
puts [set line "\tHello, world."]
# Hello, world.
puts [split $line \ ,.\t]
#{} Hello {} world {}
- join 명령은 split 명령의 반대이며 리스트를 스트링으로 변환
puts [join {1 {2 3} {4 5 6} } :]
#1:2 3:4 5 6
배열
- index는 string이며 괄호로 구분됨
- 내부적으로 해쉬 테이블을 사용해 구현되었기에 탐색 시간이 짧음
- 인덱스는 명령어 대치를 포함해 어떤 string 값도 가질 수 있음
- 배열의 원소값도 역시 변수 치환을 통해 얻어낼 수 있음
set arr(0) 1
for {set i 1} {$i <= 10} {incr i} {
set arr($i) [expr $i * $arr([expr $i-1])]
}
puts $arr(5)
#120
- 배열 변수는 일반 변수와 똑같이 사용가능
- 인덱스가 복잡한 경우 인덱스의 다른 부분을 구분하기 위해 ‘,’를 사용
- 괄호는 grouping 기능을 제공하지 않기에 배열의 인덱스에 공백이 생기면 안됨
- 인덱스 부분에 공백을 넣기 위해서는 역슬래쉬 치환이나 grouping을 사용해야 함
set index {I'm asking for trouble}
set arr($index) {I told you so.}
- 배열의 이름만 다른 변수에 저장하고 사용 가능
set name TheArray
set ${name}(xyz) {some value}
puts ${name}(xyz)
puts [set x $TheArray(xyz)]
#TheArray(xyz)
#some value
array 명령
- array 명령은 배열 변수에 대한 정보를 돌려줌
- 배열의 원소들을 모두 검색하기 위해 array 명령을 사용
- array names 명령을 foreach 루프와 함께 배열의 모든 원소에 대해 특정 작업을 하게 할 수 있음
foreach index [array names arr] {command body}
- array names 명령에 의해 리턴되는 원소의 순서는 랜덤
- array get과 array set 명령은 배열과 리스트간의 변환을 위해 사용
- array get 명령에 의해 리턴되는 리스트는 짝수 개의 원소를 가지고
먼저 인덱스 부분이 나오고 뒤에 그 값이 나오며 모든 원소에 대해 반복 - array set 명령에게 주는 인자도 array get에 의해 리턴되는 배열의 구조와 같아야 함
set fruit(best) kiwi
set fruit(worst) peach
set fruit(ok) banana
puts [array get fruit]
#ok banana best kiwi worst peach
728x90
728x90