본문 바로가기
Programming/TclTk

TCL 자료 구조

by Hunveloper 2022. 9. 2.
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는 리스트의 특정 범위에 있는 원소들을 새로운 원소들로 변경
  • 새로운 원소를 인자로 주지 않으면 특정 범위의 원소가 삭제
  • linsertlreplace기존의 리스트를 변경하지는 않고 변경된 리스트를 반환만 함
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

'Programming > TclTk' 카테고리의 다른 글

TCL 프로시져와 스코프  (0) 2022.09.05
TCL 순서제어 명령  (0) 2022.09.02
TCL 스트링과 패턴 매칭  (0) 2022.09.02
TCL 기본  (0) 2022.09.01
TCL 설치하기  (0) 2022.09.01

댓글