ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 4. 자바 배열과 반복문 (1) 배열
    자바(Java) 강의 2019. 3. 7. 17:43

    이전 포스트에서 조건문 중 하나인 if문을 다뤘다. 이번 포스트에서는 배열과 반복문을 다룰 것이다. 다른 조건문을 다루기 전 배열과 반복문을 다루는 이유는 프로그램을 만들기위한 기본적인 문법(조건문/반복문)을 이해 한 후 다른 조건문을 공부해도 늦지 않다고 생각하기 때문이다. 계속 조건문만 하면 지루하기도 하고, 특별히 프로그램을 만드는 느낌도 아니다. 그러니 프로그램을 작성 할 수 있는 최소의 문법들을 먼저 다루고, 나머지 문법들은 이후에 설명하도록 하겠다.

    예상 독자

    목표

    • 배열이 필요한 이유
    • 배열

    배열이 필요한 이유

    자바 변수와 자료형 char에서 문자 하나를 저장하는 자료형에 대해 알아보았었다. 하지만 우리가 실제로 문자 하나만 쓰는 경우가 자주 있는가? 없다. 우리는 문자를 여러개 나열해 단어를 만들어 쓴다. 그렇다면 이런 단어는 어떻게 표현 해야겠는가? 예를들어 software라는 단어를 생각 해 보자. software를 자바에서 표현하려면 어떻게 하겠는가?

    public class Main {
    public static void main(String[] args) {
    char c0 = 's';
    char c1 = 'o';
    char c2 = 'f';
    char c3 = 't';
    char c4 = 'w';
    char c5 = 'a';
    char c6 = 'r';
    char c7 = 'e';
    System.out.println(c0);
    System.out.println(c1);
    System.out.println(c2);
    System.out.println(c3);
    System.out.println(c4);
    System.out.println(c5);
    System.out.println(c6);
    System.out.println(c7);
    }
    } 실행 결과: s o f t w a r e

    여러분이 지금까지 열심히 따라왔다면 위와 같은 방법을 생각 해 낼 수 있을 것이다. 이 방법의 단점은 무엇인가? 가장 큰 단점은 문장을 표현 하는 것이 매우 어렵다는 점이다. 예를들어서 'I'm a software engineer'를 char형으로 표현하려면 무려 23개의 변수가 필요하다. 그리고 코드를 딱 보면 뭔가 마음이 불편하지 않은가? 반복되는 복사/붙여넣기가 여러분의 마음을 심란하게 하지 않는가? 인간이 이해하기 쉽도록 software라고 왼쪽에서 오른쪽으로 나열 할 수는 없을까? 만약 이 상황이 불편하지 않다면 'I'm a software engineer'를 위와 같은 방법으로 선언 해보라. 그래도 불편하지 않다면 애국가를 1절부터 4절까지 위와 같은 방식으로 선언 해 보고 출력 해 보라. 

    다행히도 대부분의 프로그래밍 언어는 배열이라는 자료구조를 지원한다. 우리는 배열을 이용해 여러개의 데이터를 나열 할 수 있다. 그리고 그 배열의 위치를 이용해 쉽게 접근 할 수 있다. 

    참고! 배열은 자료형이 아님을 유의하라. 아마도 배열은 여러분이 공부하게될 가장 첫번째 자료구조가 될 것이다. 자료형이 아니므로 지금까지 배웠던 자료형 선언 및 초기화 방법과는 조금 다른것이다.

    배열

    배열을 선언하는 방법엔 여러가지가 있다. 

    public class Main {
    public static void main(String[] args) {
    char[] str = new char[8];
    }
    }

    아래 그림을 통해 배열의 선언 방법에 대해 자세히 들여다 보자.

    변수와 자료형에서 변수를 어떻게 선언하는지 배웠다. 그 때 변수는 'type 변수이름 = 값;' 이렇게 선언한다고 했었다. 그 맥락에서 이해 해 보도록 하자. 우리는 배열을 표현 할 변수를 선언하고 싶다. 따라서 왼쪽에 자료형(type)옆에 []를 붙여, '이 변수는 type이라는 자료형을 여러개 담을 배열을 표현 할 변수이다.'라고 명시해준다. 만약 이 배열이 char를 담을 배열이면 char[]이고, 정수형을 담을 배열이면 int[] 일 것이다. 그리고 이 변수 선언에서 했던 것 처럼 변수 이름(variableName)을 써 준다. 이제 값이 들어가는 부분을 보자. new type[n] 무슨 뜻인가? new - 새로 생성하라는 뜻이다. 무엇을? 메모리에 공간을. 어떤 공간을? type형을 n개 저장 할 수 있는 공간을 만들라는 뜻이다. char의 예를 가지고 생각 해 보자.

    위의 예에선 char형이 8개 들어 갈 수 있는 배열을 선언하고 있다. new char[8]을 통해 우리는 컴퓨터에게 '내가 char형 8개를 나열 할 배열이 필요하니 이를 저장할 공간을 마련해라'라고 전달 하는 셈인 것이다. 이러면 컴퓨터는 '아~ char은 하나 당 2바이트니까 2*8 = 16바이트의 공간이 필요하겠구나'하고 이해 한 후 메모리에 16바이트를 덩어리로 할당한다. 만약 int[] integers = new int[8]을 한다면 컴퓨터는 "int는 4바이트니까 4바이트 * 8=32바이트의 공간을 할당해야겠다"하고 이해한다. 여기서 이 '덩어리'가 중요하다. '덩어리'로 할당해야하기 때문에 애초에 얼마만큼의 공간을 할당해야 할 지 알려줘야 하는 것이다. 배열은 메모리에서 진짜 물리적으로 나란히 나열된다. 그래서 배열이다. 나중에 리스트 자료구조와 비교 하며 더 자세히 설명하겠다.

    str변수는 여러분이 방금 만든 배열의 0번째 아이템의 메모리 주소를 가지고 있다. 지금 이해가 안돼도 괜찮다. str과 붉은 화살표의 의미는 나중에 클래스, 오브젝트, 레퍼런스에 대한 개념을 배운 후에 이해해도 된다. 지금은 이렇게 생각하자. str은 배열을 사용 할 수 있도록 도와준다. str을 이용해 배열에 접근 할 수 있다.

    public class Main {
    public static void main(String[] args) {
    char[] str = new char[8]; // 또는 char str[] = new char[8];
    str[0] = 's';
    str[1] = 'o';
    str[2] = 'f';
    str[3] = 't';
    str[4] = 'w';
    str[5] = 'a';
    str[6] = 'r';
    str[7] = 'e';
    System.out.println(str);
    }
    } 실행 결과:

    software

    배열의 접근은 위와 같이 '배열변수의이름[인덱스]'로 가능하다. str[0] 은 0번 인덱스의 자료를, str[1]는 1번 인덱스의 자료를 접근한다. 맨 처음에 c0, c1, ... c7를 하나하나 선언 했던게 기억나는가? 여러분은 배열을 선언함으로써 c0, c1, c2, ... 를 하나하나 할 필요가 없어진 것이다. 하지만 이것도 약간 거추장스럽다. 애초에 software를 한번에 넣을 수는 없을까?

    public class Main {
    public static void main(String[] args) {
    char[] str = new char[]{'s', 'o', 'f', 't', 'w', 'a', 'r', 'e'};
    System.out.println(str);
    }
    } 실행 결과:

    software

    없을리가 없다! 위처럼 []뒤에 { }중괄호를 이용해 원하는 문자를 나열 해 주면된다. 이 경우 왜 크기가 필요 없을까? 왜냐면 뒤에 몇개의 문자를 넣었는지 컴퓨터가 계산 할 수 있기 때문이다. 8개의 문자를 넣었으니, "아 얘는 8개의 문자를 넣어야 하니까 2바이트 *8 = 16바이트의 공간을 만들면 되겠네"하고 이해한다는 것이다. 

    이렇게 선언된 배열의 크기를 알 수 있을까? 

    public class Main {
    public static void main(String[] args) {
    char[] str = new char[]{'s', 'o', 'f', 't', 'w', 'a', 'r', 'e'};
    System.out.println(str.length);
    }
    } 실행 결과:

    8

    자바에서 배열 자료구조는 기본적으로 length라는 변수를 제공한다. 지금 str다음의 마침표가 뭔지 묻지 마라. 나중에 클래스와 오브젝트에 들어가면 이해된다. 지금은 그냥 .length를 이용해 배열의 길이를 접근 할 수 있다는 것만 알면 된다.

    특정 배열의 값을 출력 해 보자. 예를들어 인덱스 3번의 값을 출력 해 보자.

    public class Main {
    public static void main(String[] args) {
    char[] str = new char[]{'s', 'o', 'f', 't', 'w', 'a', 'r', 'e'};
    System.out.println(str[3]);
    }
    } 실행 결과: t

    t가 출력되는 것을 확인 할 수 있다. 유저에게 index를 입력받아 출력 해 보자.

    import java.util.Scanner;

    public class Main {
    public static void main(String[] args) {
    char[] str = new char[]{'s', 'o', 'f', 't', 'w', 'a', 'r', 'e'};

    Scanner scan = new Scanner(System.in);
    System.out.println("인덱스 입력: ");
    int index = scan.nextInt();

    System.out.println(str[index]);
    }
    } 실행 결과: 인덱스 입력: 5 a

    5를 입력 했더닌 인덱스 5에 해당하는 a가 출력되었다. 이번에는 위 코드를 다시 실행시키고 100을 넣어보자. 실행 결과가 어떻게 되는가?

    실행 결과: 인덱스 입력:
    100
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
    at Main.main(Main.java:11)

    축하한다! 여러분은 처음으로 자바의 예외(Exception)를 만나게 되었다. 소프트웨어 엔지니어라면 예외를 아주아주아주아주아주 많이, 적어도 하루에 한번은 보게 될 것이다. 예외에 뭐라고 써있나보자. ArryaIndexOutOfBoundsException - 직역하면 배열인덱스범위밖예외이다. 즉 배열의 인덱스가 해당 배열의 범위 밖에 있어서 예외가 났다는 뜻이다. 우리는 방금 100번째 인덱스에 있는 값을 접근하려고 했다. 근데 이 배열의 크기는 얼마인가? 8이다. 100번은 존재하지 않는다. 따라서 예외가 난 것이다. 배열과 반복문으로 코드를 짜다보면 한번은 꼭 만날 예외이니 잘 보고 넘어가길 바란다.

    이번엔 int[] integers = new int[10];을 선언하고 10, 20 ,30 ,40 ,50, 60, 70, 80, 90, 100을 넣어보자.

    public class Main {
    public static void main(String[] args) {
    int[] integers = new int[]{ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
    System.out.println(integers);
    }
    } 실행 결과:

    [I@5cad8086

    아니..? 이게 무슨 일인가? 여러분의 결과 값은 나의 결과 값([I@5xad8086)와 좀 다를 수 있다. 중요한건 아까처럼 값의 나열이 나타나지 않았다는 것이다. 왜 10 20 30 40 50 60 70 80 90 100이 출력되지 않고 이상한 값이 출력되는가? 이 값이 위에서 말한 '여러분이 방금 만든 배열의 0번째 아이템의 메모리 주소'의 의미이다. System.out.println이라는 녀석은 char의 배열은 문자 배열의 값을 한꺼번에 출력하도록 만들어져 있다. 하지만 아쉽게도 다른 자료형은 그렇게 만들어져 있지 않아 그냥 integers 변수 안에 들어있는 값을 바로 출력하는 것이다. 이 값이 뭔지에 대해서는 클래스, 오브젝트, 레퍼런스에서 다시 설명 할 것이다. 아무튼 이렇게 바로 출력이 불가능 하므로 하나하나 출력 해 보자.

    포스팅이 너무 길어져 여기서 일단 끊었다. 다음 포스트에서 반복문에 대해 얘기해 보도록 하겠다.

    다음 포스트: 4. 자바 배열과 반복문 (2) 반복문

    댓글

f.software engineer @ All Right Reserved