티스토리 뷰



흐름 제어(Flow Control)라는 용어는 프로그램의 처리 과정에서 그 흐름(Flow)을 순차적으로 진행시키는 것 뿐만아니라 일정 횟수나 조건을 만족할 동안 반복하거나, 조건에 따라 처리 내용을 바꾸거나, 특정 값에 따라 처리할 내용을 지정하는 것등을 포함합니다. 프로그램의 시작부터 종료까지 그리고 특정 이벤트의 발생시점부터 종료까지 큰 흐름 또는 작은 흐름으로 수행하는 제어들이 모여 하나의 프로그램을 구성하므로 VB를 활용하여 프로그램을 작성하고 싶다면 이 부분에 대해서는 꼭 알아두셔야 합니다.






1. If 조건문

If문은 조건에 따라 문장을 처리해야할 때 사용하며 가장 가단한 사용 방법은 아래의 예와 같이 "If 조건 Then 처리문장"의 형식으로 한 줄에 특정 조건을 만족할 때의 처리 문장을 간단하게 기술하는 것입니다.

        Dim Blocks As New List(Of String)
        If Hours <> 0 Then Blocks.Add(Hours & " h")
        If T.Minutes <> 0 Then Blocks.Add(T.Minutes.ToString & " m")


조건이 참일때와 거짓일 때를 구분해서 처리할 경우에는 아래의 예와 같이 Else문 다음 줄에 거짓일 경우에 처리할 문장을 기술하고  End If로 조건문을 닫아주면 됩니다.

        If CommandLine.Silent Then
            ProgramConfig.LogAppEvent(String.Format("Silent: Balloon: [{0}].", Msg))
            Exit Sub
        Else
            ProgramConfig.LogAppEvent(String.Format("Balloon tip shown: [{0}].", Msg))
        End If


Then 또는 Else 다음 줄에 기술하는 문장은 여러 문장을 여러 줄에 기술할 수 있습니다. 그 내부에 또다른 If 조건문이 들어 갈수도 있고(Nested) 그 사용 방법은 동일합니다. 아래의 코드를 보면 Then문 안에 또다른 If문 블럭을 기술하고 있는 것을 확인할 수 있습니다. 비주얼스튜디오가 자동적으로 들여쓰기(Indentation)를 지원해 주지만 코드의 가독성이 훼손되지 않도록 들여쓰기를 잘 해주시는 것이 좋습니다.

        If e.KeyCode = Keys.Enter Then
            If Actions.SelectedIndices(0) = 0 Then
                Actions.LabelEdit = True
                Actions.SelectedItems(0).BeginEdit()
            Else
                Dim Bounds As Drawing.Rectangle = Actions.SelectedItems(0).Bounds
                ActionsMenu.Show(Actions, New Drawing.Point(Bounds.Left, Bounds.Top))
            End If
        ElseIf e.KeyCode = Keys.F2 And Actions.SelectedIndices(0) <> 0 Then
            Actions.LabelEdit = True
            Actions.SelectedItems(0).BeginEdit()
        End If


위의 예제를 보면 ElseIf문을 사용했는데 Else문 다음에 또다른 If문을 작성해서 코드를 복잡하게 만들지 않고 연쇄적인 If문 작성을 가능하게 하고 ElseIf문 다음의 Then문 Else문은 동일하게 올 수 있고 연쇄적으로 ElseIf문이 또다시 올 수도 있습니다. 단, ElseIf문은 앞서 사용한 If문의 연장선상에 있으므로 반드시 End If로 문을 끝내주어야 합니다. 또한 많은 ElseIf를 사용해야 한는 경우는 아래에서 다룰 Select문을 검토하는 것이 코드의 가독성을 높이고 버그를 줄이는 방법입니다. 



2. Select 문

하나의 조건 비교에 여러 처리 방법이 있는 경우에 적절한 구문입니다. 문장 형식은 아래와 같습니다.

Select Case 조건식

    Case 비교식

        처리문장

    Case 비교식

        처리문장

    Case Else

        처리문장

End Select

Case 비교식은 경우수 만큼 기술하고 나머지 경우의 수는 Case Else문에 다음에 기술합니다. 일반적으로 Case 비교식에는 리터럴 값을 기술하지만 "10 To 20", "Is < 10"처럼 값의 범위를 지정할 수 있습니다. 


Select Case e.KeyCode
    Case Keys.N
        Actions.LabelEdit = True
        Actions.Items(0).BeginEdit()
    Case Keys.O
        Interaction.StartProcess(ProgramConfig.ConfigRootDir)
    Case Keys.L
        SetView(1)
    Case Keys.Subtract
        SetFont(Actions.Font.Size - 1)
End Select

아래의 코드는 Case IsCase Else를 사용한 또다른 예제입니다. 

        Select Case Size
            Case Is >= (1 << 30)
                Return Math.Round(Size / (1 << 30), Digits).ToString & " GB"
            Case Is >= (1 << 20)
                Return Math.Round(Size / (1 << 20), Digits).ToString & " MB"
            Case Is >= (1 << 10)
                Return Math.Round(Size / (1 << 10), Digits).ToString & " kB"
            Case Else
                Return Math.Round(Size, Digits).ToString & " B"
        End Select

C언어 switch 문에서는 case구문 다음에 break문을 기술하지 않으면 다음 case로 흘러버리지만 VB에서는 해당 Case문만 수행하고 End Select다음으로 나오는 차이점이 있습니다.


조건에 따라 다른 값을 설정해야 하지만 If나 Select를 사용하지 않고 간편하게 문장을 기술하고 싶을 경우에는 Microsoft.VisualBasic.Switch(조건, 값, 조건, 값......) 구문을 사용할 수 있습니다. 조건이 참을 경우 그에 해당하는 값을 리턴해 줍니다.



3. For 루프

많은 프로그래밍 언어에서 사용하는 for 루프는 VB에서는 "For 인덱스 = 시작 To Step 증분"으로 기술하고 루프의끝에는 "Next 인덱스"와 같이 기술합니다. 인덱스 변수 값에 "시작"을 입력하고 인덱스 값이 "시작"과 "끝" 값 사이에 있을 동안 루프를 반복합니다. 루프를 반복할 때 때 인덱스에 "증분"을 더하는데 Step문을 생략하면 증분은 1로 간주합니다. Next문의 인덱스는 생략할 수 있지만 프로그램의 가독성을 위해서 Next 다음에 인덱스 이름을 붙여줍니다. 인덱스는 For문 이전에 먼저 선언해 주지만 선언하지 않은 상태에서 For문에 "For 인덱스 As 데이터타입"의 형식을 사용 시점에 정의해서 사용할 수도 있습니다. 물론 다른 문장처럼 내부에 또다른 For 문을 내장할 수 있습니다. 다음은 그 사용 예제입니다. 인덱스를 For 구문에서 선언했고 증분을 음수로 해서 역순으로 작업하고 있습니다. For 루프 수행 도중 루프에서 빠져나갈 때는 "Exit For"구문을 사용합니다.

For ProfileIndex As Integer = ScheduledProfiles.Count - 1 To 0 Step -1
    If Not Profiles.ContainsKey(ScheduledProfiles(ProfileIndex).Name) Then
        ScheduledProfiles.RemoveAt(ProfileIndex)
    End If
Next ProfileIndex 

4. For Each 루프

배열이나 트리 노드 처럼 특정 데이터 타입의 항목으로 구성된 집합 변수를 "For 인덱스"문을 사용하지 않고 간편하게 처리할 수 있는 방법입니다. 항목의 개수나 배열의 크기를 고민할 필요없이 For Each 구문이 자동적으로 개별 항목 하나 하나를 가져다 주므로 프로그래머는 해당 개별 항목에 대한 처리만 수행하면 됩니다. 문법은 "For Each 항목 In 집합변수"로 시작하고 루프의 끝은 "Next 항목"으로 기술합니다. For문과 같이 항목을 앞에서 선의하지 않은 경우에는 "As 데이터타입"으로 For Each문에서 정의할수 있고 루프를 중간에서 끝내고 싶은 경우에는 "Exit For"구문을 사용합니다. 다음은 그 사용 예제입니다. 이 예제에서는 루프 중간에 Exit For로 루프를 빠지는 경우가 있습니다.

For Each Node As TreeNode In BaseNode.Nodes
    If Node.Text = Path(0) Then
        Node.Expand() : Path.RemoveAt(0)
        CheckAccordingToPath(Node, Path, FullCheck)
        Exit For
    End If
Next Node
반대로 루프 수행중 루프의 나머지 문장을 수행하지 않고 다음 루프로 건너뛰고 싶을 때는 "Continue For"문을 사용할 수 있습니다.
For Each Folder As String In WriteNeededFolders
    If Not IO.Directory.Exists(Folder) Then Continue For

    Dim TestPath As String = Folder
    IO.File.Create(TestPath).Close()
    ToDelete.Add(TestPath)

    If Folder = Application.StartupPath Then Continue For
    For Each File As String In IO.Directory.GetFiles(Folder)
        If (IO.File.GetAttributes(File) Then Throw New IO.IOException(File)
    Next
Next


5. While 루프

"While 조건식"으로 반복할 루프를 시작하고 "End While"로 루프를 마감합니다. 지정한 조건식이 참일 동안 루프를 반복합니다. for문 처럼 "Exit While", "Continue While" 문을 사용할 수 있습니다.

While Not LogReader.EndOfStream
    Dim Line As String = LogReader.ReadLine()
    If TitleLine.IsMatch(Line) Then
        Archives.Add(New Text.StringBuilder())
        If Archives.Count > MaxArchivesCount Then Archives.RemoveAt(0)
    End If
    If Archives.Count > 0 Then Archives(Archives.Count - 1).AppendLine(Line)
End While


6. Do While/Until 루프

Do 루프는 End 대신 Loop문으로 루프를 마감합니다. Do 루프가 다른 루프와 다른 차이점은 조건식을 Do 옆에 두어 루프 진입 시점에 먼저 비교할 수도 있고 Loop 옆에 두어 루프를 실행한 다음 비교 할 수도 있다는 점입니다. 조건 비교를 나중에 하는 방식은 일단 루프를 한번은 수행해야 하는 상황에 적절합니다. 조건은 While과 Until 두가지 방식으로 지정할 수 있으며 While조건식이 참일 동안 루프를 수행하고 Until은 조건식이 거짓일 동안 루프를 반복하고 참이면 루프를 빠집니다. 다른 루프와 같이 루프를 빠질 때는 "Exit Do"문을 사용합니다.


Do
    TempDest = DestFile & "-" & IO.Path.GetRandomFileName()
    DestBack = DestFile & "-" & IO.Path.GetRandomFileName()
Loop While IO.File.Exists(TempDest)


7. With 문

With문은 프로그램의 흐름 제어라기 보다는 프로그램 작성을 편리하게 할 수 있도록 돕는 구문입니다. 특히 .Net 프레임워크의 여러가지 기능과 자원을 활용하다 보면 다양한 오브젝트를 참조해야 하는데 오브젝트 참조 표현의 반복되는 부분을 With 구문으로 묶어서 짧고 간편하게 표현할 수 있도록 한 것입니다. 아래의 예제 코드를 보면 noise라는 오브젝트에 있는 Filters를 참조하는 여러 문장을 With ~ End With로 묶고 그 내부에서는 With 옆에 기술한 오브젝트를 생략한 것을 확인 할 수 있습니다.

Dim noise As New AviSynthCategory("Noise")

With noise.Filters
    .Add(New AviSynthFilter(noise.Name, "FluxSmooth Low", "FluxSmoothT(2)", True))
    .Add(New AviSynthFilter(noise.Name, "FluxSmooth Medium", "FluxSmoothT(4)", True))
    .Add(New AviSynthFilter(noise.Name, "FluxSmooth Heavy", "FluxSmoothT(8)", True))
    .Add(New AviSynthFilter(noise.Name, "Deen", "Deen()", True))
    .Add(New AviSynthFilter(noise.Name, "UnDot", "UnDot()", True))
End With


8. Using 문

With와 같이 흐름 제어라기 보다는 시스템 자원을 편리하게 사용할 수 있도록 돕는 구분입니다. 파일, 데이터베이스, 시스템 오브젝트 등과 같이 자원 가져오기-사용-해제의 과정이 필요한 것들에 대해서 "Using 자원변수 As New 자원 타입"의 형태로 시작하고 "End Using"으로 닫으면 사용했던 자원을 자동으로 해제합니다. 다음은 그 사용 예입니다.

 Using DataStream As New IO.StreamReader(Path), _
          CryptObject As New System.Security.Cryptography.MD5CryptoServiceProvider()
    Return Convert.ToBase64String(CryptObject.ComputeHash(DataStream.BaseStream))
End Using



9. End 문

흐름 제어의 중요한 부분으로 프로그램을 종료시키는 구문입니다. 프로그램의 종료까지 자연스럽게 흐르거나 주요 Form을 닫는 이벤트 처리가 있으면 필요 없는 구문이지만 실행 중간에 임의로 프로그램을 종료시킬때 사용합니다.


※ 코드 참조 : http://synchronicity.sourceforge.net


댓글
댓글쓰기 폼