날짜: 1996-04-09 | 글쓴이: 도아 | 6721 번 | 프린트 | 메일로보내기

제 9강 - 연관배열


펄에서 제공하는 아주 유용한 변수가 연관배열이다. 사실 개체지향 언어에서 개체의 특성을 저장하는 방법이 연관배열이다. 펄은 이 연관배열을 기본 변수로 제공한다.

연관배열은 일반배열 처럼 숫자에의해 참조하는 것이 아니라 "키"를 이용해서 "값"을 참조하게된다. 요약

%(백분율 기호)
전체 배열을 참조한다.
{ }(중괄호)
"키"를 사용한다.
$
{ }와 함께 사용될 때, 이 것은 "키"로 참조한 배열 요소의 값이다.
설명

일반적인 배열 요소는 숫자에의해 참조할 수 있다. @food라는 배열의 첫번째 요소는 $food[0]이고, 두번째 요소는 $food[1]이다. 그러나 펄은 문자열에의해 배열요소를 참조할 수 있는 배열을 제공한다. 이들을 연관배열이라고 한다.

연관배열을 정의하기위해 통상적인 둥근괄호를 사용하지만, 배열명에 % 기호를 붙인다. 사람과 이들의 나이를 배열로 저장한다고 가정하자. 이 것은 다음과 같은 것이다.

%ages = ("김희선", 22,
         "김희애", 34,
         "천사", 27,
         "꼬마", "강아지 나이로 21",
         "여왕", 108);

일반배열을 할당하는 것과 동일한 방법으로 연관배열을 할당할 수도 있지만 이 경우에는 키와 값의 연관관계가 명확하지 않으므로 쉼표(,)대신에 =>를 사용할 수도 있다.

주의 이 방법은 Perl 5에서만 지원된다.

%ages = ("김희선" => 22,
         "김희애" => 34,
         "천사" => 27,
         "꼬마" => "강아지 나이로 21",
         "여왕" => 108);

이제 사람들의 나이를 찾기위해 다음 표현식을 사용할 수 있다.

print "$ages{'김희선'}\n";	# 22를 리턴
print "$ages{'김희애'}\n";	# 34를 리턴
print "$ages{'천사'}\n";	# 27을 리턴
print "$ages{'꼬마'}\n";	# "강아지 나이로 21"을 리턴
print "$ages{'여왕'}\n";	# 108을 리턴

일반 배열과 마찬가지로 % 기호는 개개의 요소를 참조할 때 $로 변경된다(개개의 요소는 스칼라이므로). 일반배열과는 달리 참조(이 경우에 사람의 이름)는 중괄호를 사용한다. 연관배열이라는 개념은 일반배열보다 낯선개념이지만 아주 유용한 개념다. 연관배열의 추가, 변경

이미 선언되어있는 연관배열에 값을 추가하기위해서는 다음과 같이 해당되는 키에 값을 대입하면 된다.

$ages{'김희선'} = '23';
$ages{'팅팅이'} = '25';
$newhash{'보람이'} = '26';
print "김희선: $ages{'김희선'}\n";
print "팅팅이: $ages{'팅팅이'}\n";
print "보람이: $newhash{'보람이'}\n";

연관배열에 값을 할당하면 펄은 일단 해당되는 키가 있는 가를 조사한다. 만약 해당되는 키가 있으면 값을 변경하고 없으면 새로운 키=>값을 생성하게된다.

또한 펄은 변수를 따로 선언하지 않고 사용하는 시점에서 사용하면 동적으로 생성된다. 따라서 위의 예에서는 %newhash라는 연관배열을 새로 생성하게된다. 연관배열과 일반배열의 변환

연관배열은 연관배열을 일반배열에 할당함으로서 일반배열로 변환할 수 있다. 일반배열은 일반배열을 연관배열에 할당함으로서 연관배열로 변환할 수 있다. 이 경우 일반배열은 짝수의 배열요소를 가지고 있어야 한다.

@info = %ages;		# @info은 일반배열.
			# 이제 10개의 요소를 갖는다.
print "@info\n";
print "$info[5]\n";	# 일반배열 @info로부터 27을 리턴한다.
%moreages = @info;	# %moreages는 연관배열이다.
			# 이것은 %ages와 동일하다.
print "$moreages{'김희선'}\n";
키와 값의 상호교환

연관배열은 키에의해 값을 참조하기 때문에 키를 값으로, 값을 키로 변환하는 경우는 거의 발생하지 않는다. 또한 펄은 이와 같은 연산자를 제공하지 않는다. 그러나 앞서배운 일반배열로의 변환과 reverse함수를 이용하면 키와 값을 상호 교환하는 것이 가능하다.

%reverse = reverse @info;

print $reverse{'22'};	# 김희선을 리턴
연산자

연관배열은 배열요소에 어떠한 순서도 가지고 있지 않다(이들은 해쉬와 같다). 그러나 keys와 values 함수를 사용해서 차례로 모든 요소를 참조할 수 있다.

foreach $person (keys %ages)
{
    print "필자는 $person의 나이를 알고 있다.\n";
}

foreach $age (values %ages)
{
    print "$age살이다.\n";
}

keys를 호출하면 연관배열의 키 목록을 리턴한다. values를 호출하면 연관배열의 값의 목록을 리턴한다. 이들 함수는 동일한 순서로 이들 목록를 리턴하지만 이들의 순서는 이들 요소가 입력될 때(또는 할당될 때)의 순서와 전혀 무관하다.

keys와 values가 스칼라환경에서 호출되며 연관배열내의 키/값의 쌍의 수를 리턴한다. 또한 키와 값의 두 요소를 리턴하는 each도 존재한다. each가 호출될 때마다 다른 키/값의 쌍이 리턴된다.

while (($person, $age) = each(%ages))
{
    print "$person is $age\n";
}
관례

연관배열은 아주 유용한 개념이지만 일반배열과의 참조상의 차이 때문에 많은 혼란을 야기한다.

따라서 이러한 혼란을 최소화하기위해서는 가급적 연관배열의 배열명은 대문자를 사용하는 하는 것이 좋다. 환경변수

UNIX에서 펄 프로그램을 실행하거나 임의의 스크립트를 실행할 때 특정한 환경변수를 설정한다. 이들은 사용자의 이름을 포함하는 USER일 수도 있으며, 그래픽 화면을 전송할 화면을 지정하는 DISPLAY일 수도 있다. WWW에서 펄 CGI 스크립트를 실행할 때에도 다른 유용한 정보를 포함하는 환경변수가 존재한다. 이러한 모든 환경변수와 값은 %ENV라는 연관배열에 저장되며, 이때 키는 환경변수의 이름이다. 펄 프로그램에서 다음과 같은 것을 실행해보기 바란다.

print "$ENV{'USER'}이며 ";
print "$ENV{'DISPLAY'}를 출력으로 사용하고 있다.\n";
연관배열 관련 함수 keys(%ARRAY)

%ARRAY내의 모든 "키"의 목록을 리턴한다. 이 목록은 랜덤하며, 순서는 내부적으로 사용된 해쉬함수에 의존한다.

foreach $key (keys %ENV) {
	print "$key = $ENV{$key}\n";
}
values(%ARRAY)

%ARRAY내의 모든 "값"의 목록을 리턴한다.

@key = keys %ENV;
@value = values %ENV;
while($#key >= 0) {
	print pop(@key), ' = ', pop(@value), "\n";
}
each(%ARRAY)

%ARRAY로 이 함수가 호출될 때마다 연관배열 내의 다음 "키/값" 쌍으로 구성된 두개의 요소를 갖는 목록을 리턴한다.

while(($key, $value) = each %ENV) {
	print "$key = $value\n";
}
delete($ARRAY{KEY})

ARRAY로부터 KEY와 연관된 "키/값"의 쌍을 제거한다.

delete($ENV{USER});
foreach $key (keys %ENV) {
	print "$key = $ENV{$key}\n";
}
연습

현재 시스템에 설정되어 있는 모든 환경변수를 출력하는 CGI 프로그램을 작성하라. 연습 - 방명록

for 문과 연관배열을 이용해서 사용자의 입력데이타를 디코딩 하도록 guest.cgi를 변경한다.

디코딩하는 부분은 다음과 비슷할 것이다.

@query = split(/&/, $query);
for(0..$#query) {
	# +를 공백으로 변환
	$query[$_] =~ s/\+/ /g;
	($key, $value) = split(/=/, $query[$_]);

	# %HH 형식을 윈래의 특수 문자로 변환
	# 자세한 설명은 문자열 일치, 대치와 변환, CGI 입력 디코딩을 참조한다.
	$key =~ s/%(..)/pack("c", hex())/ge;
	$value =~ s/%(..)/pack("c", hex())/ge;
	$FORM{$key} = $value;
}

위의 루틴을 수행하면 사용자의 입력데이타는 %FORM이라는 연관배열에 저장된다. 따라서 $FORM{name1}과 같은 형식으로 <FORM> 데이터를 참조할 수 있게된다.



다음글: 제 10강 - 다차원 배열 (4619)1996-04-10
이전글: 제 8강 - Split (5897)1996-04-08

세상사는 이야기

  • 찾아라! 아이폰 순정용 >
  • 만원대 피젯 스피너를 >
  • 망하는 길을 택한 쿠팡 >
  • 물놀이에 적당한 가성 >
  • 컴퓨터를 IPTV로 2, po >
  • 컴퓨터를 IPTV로 만들 >
  • Warning.or.kr도 우회 >
  • 한국의 100대 부자, 어 >
  • 세상을 바꾼 크롬: 크 >
  • 장난(?)으로 시작한 여 >


  • RSS 구독 (익명 | 회원 | 강좌 | 포럼)
    (C) 1996 ~ 2017 QAOS.com All rights reserved.