Lua 제어문

프로그램을 만드는 데 필수적인 문법, 제어문에 대해 설명한다.

if else에 의한 조건부 분기

if else 구문(영어로 if는 만약 ~라면, else는 그렇지 않다면이라는 의미)은 조건 분기를 할 때 사용하는 구문입니다.

if else 작성법

if (조건식) then
    조건식이 참일  처리
else
    조건식이 거짓일  처리
end

조건식은 괄호가 없어도 상관없다.

그럼 실제로 if, else 구문을 사용해 보자.

이제 시험 성적을 판정하는 프로그램을 만들어 보자. 만약 점수가 60점 이상이면 합격, 그렇지 않으면 불합격으로 표시하는 프로그램을 만들어 보자.

result = 70
if result >= 60 then
    print("합격")
else
    print("불합격")
end

실행 결과:

합격

result가 60 이상인지 비교할 때는 관계 연산자 >=를 사용한다.

else는 쓰지 않아도 된다.

hoge = 10
if (hoge == 10) then
    print("Hello world")
end

이 프로그램은 hoge가 10일 때만 "Hello world"를 출력한다.

여기서 주의할 점은 hoge가 10과 같다고 판단하려면, hoge = 10이 아니라 hoge == 10이라는 점이다.

또한, 조건을 여러 개 작성하고 싶다면, 다음과 같이 작성한다.

hoge = 8

if (hoge == 10) then
--A 처리
elseif(hoge == 9) then
--B 처리
elseif(hoge == 8) then
--C 처리
else
--D 처리
end

2번째, 3번째 판단을 추가하고 싶다면 elseif를 사용한다. 이 경우 C의 처리가 실행된다. 여기서 만약 hoge가 9라면 B의 처리가 이루어지고, 6이라면 D의 처리가 실행된다.

거짓 조건 판단

그렇다면 다음과 같은 코드를 작성하면 어떤 실행 결과가 나올까요?

hoge = 1
if (hoge) then
   print("first")
end

hoge = 0
if (hoge) then
   print("second")
end

hoge = false
if (hoge) then
   print("third")
end

hoge = nil
if (hoge) then
   print("fourth")
end

실행 결과:

first
second

괄호 안에는 무언가 수식을 써야 하는데, 이 경우 변수명 hoge라고만 적혀 있다. 이것은 무슨 의미일까?

사실 이런 경우 괄호 안의 값이 false, nil인지 false, nil이 아닌지 판단한다. false,nil이 아니면 처리를 하고, 그렇지 않으면 처리를 하지 않는다.

관계 연산자

두 변수를 비교하여 식이 맞는지 틀린지를 구할 때 사용하는 연산자를 관계 연산자라고 한다. 예를 들어 표 4.1과 같은 것이 존재한다.

표 4.1: 관계 연산자

관계 연산자 설명
x < y xy보다 작으면 참 그렇지 않으면 거짓
x > y xy보다 크면 참 그렇지 않으면 거짓
x <= y xy 이하인 경우 참 그렇지 않은 경우 거짓
x >= y xy보다 크면 참 그렇지 않으면 거짓
x == y xy와 같으면 참 그렇지 않으면 거짓
x ~= y xy와 같지 않으면 참 그렇지 않으면 거짓

while으로 반복하기

while 문장의 서식

while (조건문) do
처리
end

조건식에는 괄호가 없어도 상관없다.

반복 처리를 하고 싶다면 while 구문을 사용한다. 조건식이 참이면 반복적으로 처리된다.

예를 들어, Hello world를 10번 표시하는 프로그램을 while을 사용하여 만들어 보자.

i = 1
while i <= 10 do
  print ( i .. "번째: Hello world!" )
  i = i + 1
end

실행 결과:

1번째: Hello world!
2번째: Hello world!
3번째: Hello world!
4번째: Hello world!
5번째: Hello world!
6번째: Hello world!
7번째: Hello world!
8번째: Hello world!
9번째: Hello world!
10번째: Hello world!

조건식은 if와 동일하다. if와 같다는 것은 다음과 같은 코드를 작성하면 어떻게 될까?

while true do
    print("Hello world!")
end

이렇게 작성하게 되면 조건은 항상 참이 된다는 뜻이다. 즉, 무한 루프에 빠지게 된다.

for에 의한 반복

for 구문에는 Numeric for와 Generic for 두 가지가 있는데, Generic for는 어려운 구문이므로 다음 장에서 다시 설명하기로 한다. 여기서는 Numeric for에 대해서 설명한다.

Numeric for도 while과 마찬가지로 반복적인 처리를 할 때 사용한다. 다만, while과 달리 종료 조건을 숫자로만 지정할 수 있다.

형식

for 초기값, 종료값, 증가값 do
    처리
end

증가값은 생략할 수 있다. 이 경우 자동으로 증가값은 1이 된다.

앞에서 소개한 "Hello world"를 10번 표시하는 프로그램을 for를 사용하여 다시 작성하면 다음과 같다.

for i = 1, 10, 1 do
    print( i .. "번째: Hello world!")
end

i가 1로 시작하여 i가 10이 될 때까지 i를 1씩 증가시킨다. 즉, i가 10 이하일 때까지 반복을 수행한다.

실행 결과:

1번째: Hello world!
2번째: Hello world!
3번째: Hello world!
4번째: Hello world!
5번째: Hello world!
6번째: Hello world!
7번째: Hello world!
8번째: Hello world!
9번째: Hello world!
10번째: Hello world!

증가값은 생략할 수 있다. 이 경우 자동으로 1이 할당된다.

for i = 1, 10 do
    print( i .. "번째: Hello world!")
end

실행 결과는 앞과 동일하다.

증가값을 4로 변경해 보자. 어떤 실행 결과가 나올까?

for i = 1, 10, 4 do
    print( i .. "번째: Hello world!")
end

실행 결과:

1번째: Hello world!
5번째: Hello world!
9번째: Hello world!

for를 사용할 때 주의해야 할 점이 있다. 초기값으로 정의한 변수(루프 변수)는 for문 안에서만 유효하다는 것이다. 즉, for를 벗어나면 루프 변수는 소멸된다.

예를 들어, 다음과 같은 코드를 작성했다고 하자.

for i = 1, 10, 4 do
    print( i .. "번째: Hello world!")
end
if i == nil then
    print ("i은 정의되지 않았다")
end

for 문에서 사용하는 iif 문에서 사용하는 i는 다르다.

실행 결과는 다음과 같다.

실행 결과:

1번째: Hello world!
5번째: Hello world!
9번째: Hello world!
i은 정의되지 않았다

i는 정의되어 있지 않으므로 nil이 된다.

repeat를 이용한 반복

repeat를 사용하여 반복을 할 수도 있다.

repeatwhile과 달리 repeat 내의 처리는 최소 1회 이상은 반드시 수행된다. 처리를 수행한 후, 조건식을 판단하고 조건이 참이면 루프가 종료된다.

형식

repeat
    처리
until (조건식)

조건식이 거짓인 경우 반복적으로 처리한다. 참인 경우는 아니므로 주의해야 한다.

i = 1
repeat
  print (i .. "번째: Hello world!")
  i = i + 1
until ( i >= 5 )

실행 결과:

1번째: Hello world!
2번째: Hello world!
3번째: Hello world!
4번째: Hello world!

break를 이용한 루프 탈출

반복 처리 중에 break 문을 사용하면 언제든지 루프에서 탈출할 수 있다.

예를 들어, 다음과 같은 프로그램을 작성했다고 하자.

for i = 0, 10 do
  print( "i의 값: " .. i )
  if (i == 5) then
      break
  end
end
print("escape")

실행 결과:

i의 값: 0
i의 값: 1
i의 값: 2
i의 값: 3
i의 값: 4
i의 값: 5
escape

break는 반드시 블록의 마지막에만 사용할 수 있다. 블록의 끝은 구체적으로 다음과 같이 위치한다.

  • end의 앞부분
  • repeat - untiluntil 앞부분 등

위의 위치 이외에는 break를 정의할 수 없다. 하지만 디버깅을 하다 보면, 예를 들어, 처리 중간에 break를 하고 싶은 경우가 있을 수 있다. 다음과 같은 코드가 있다고 하자.

for i = 0, 10 do
    print("뭔가 처리")
    -- 사실은 여기서 break 하고 싶다.
    print("다른 처리")
end
print("탈출")

뭐, 이런 코드를 작성하는 경우는 흔치 않겠지만 말이다.

어쨌든 중간에 break를 하고 싶다면 for의 중간에 블록을 만들면 된다. 블록을 만들려면 do - end를 사용하면 된다.

형식

do
    처리
end

따라서 다음과 같이 다시 작성하면 처리 도중에 break를 할 수 있다.

for i = 0, 10 do
  print("뭔가 처리")
  do
      break;
  end
  print("다른 처리")
end
print("탈출")

실행 결과:

뭔가 처리
탈출

Lua에 존재하지 않는 제어문

많은 프로그래밍 언어에는 존재하지만 Lua에는 존재하지 않는 제어문이 있다.

예를 들어, switch 구문은 Lua에 존재하지 않는다. switch는 테이블을 사용하여 표현할 수 있지만, 여기서는 그 방법은 생략한다.

또한, 반복 처리 중에 사용하는 continue 문도 존재하지 않는다.

예제

99단을 작성하는 프로그램

99단 표시하는 프로그램을 작성하시오. 99단은 다음과 같이 표시된다.

  1  2  3  4  5  6  7  8  9
  2  4  6  8 10 12 14 16 18
  3  6  9 12 15 18 21 24 27
  4  8 12 16 20 24 28 32 36
  5 10 15 20 25 30 35 40 45
  6 12 18 24 30 36 42 48 54
  7 14 21 28 35 42 49 56 63
  8 16 24 32 40 48 56 64 72
  9 18 27 36 45 54 63 72 81
for i = 1, 9 do
  for j = 1, 9 do
      io.write( string.format("%3d", i*j) )
  end
  io.write("\n")
end

io.write 함수는 print 함수와 동일한 기능을 수행한다. 단, 문장 끝에 줄바꿈이 자동으로 추가되지 않는다. string.format 안에 %3d라는 것을 사용하였는데, 이는 3자 분량의 공백을 확보하여 표시한다는 의미이다. 이렇게 하면 깔끔하게 표시할 수 있다. 5자의 공간을 확보하려면 %5d로 지정하면 된다.

문자 코드 표를 표시하는 프로그램

0~255까지의 문자 코드를 표시하는 프로그램을 작성하시오. 10진수 값, 16진수 값, 문자를 표시하도록 한다.

00 11

(생략)

65 41 A
66 42 B

(생략)
for hoge = 0, 255 do
    print( string.format("%3d %3x %3c", hoge, hoge, hoge) )
end

덧셈, 뺄셈을 하는 프로그램

사용자의 선택에 따라 덧셈, 뺄셈을 할 수 있는 프로그램을 작성하시오.

print("1 : 덧셈")
print("2 : 빼셈")
io.write("숫자를 입력하시오 :")
select = io.read()

io.write("1번째 숫자 :")
hoge = io.read()
io.write("2번째 숫자 :")
piyo = io.read()

if (select == "1") then
    print( hoge .. " + " .. piyo .. " = " .. hoge + piyo )
elseif (select == "2") then
    print( hoge .. " - " .. piyo .. " = " .. hoge - piyo )
end

주의할 점이 하나 있다. io.read 함수로 읽을 수 있는 것은 문자열이다. 따라서 select는 String 타입으로 되어 있다.

따라서 아래와 같이는 할수 없다.

if (select == 1) then

실행 결과:

% lua HelloWorld.lua
1 : 덧셈
2 : 빼셈
숫자를 입력하시오 :1
1번째 숫자 :24
2번째 숫자 :17
24 + 17 = 41
% lua HelloWorld.lua
1 : 덧셈
2 : 빼셈
숫자를 입력하시오 :2
1번째 숫자 :33
2번째 숫자 :23
33 - 23 = 10

연습문제

문제1

키보드에서 숫자를 입력받아 그 절대값을 표시하는 프로그램을 작성하시오. 절대값은 숫자 0으로부터의 거리를 의미한다.
예를 들어, -7이라면 0으로부터의 거리는 7이므로 절대값은 7이다.




최종 수정 : 2024-04-22