String배열, 다차원배열

황찬호·2021년 5월 4일

JAVA

목록 보기
4/5

2. String배열

2.1 String배열의 선언과 생성

배열의 타입이 String인 경우에도 int배열의 선언과 생성방법은 다르지 않다.

String[] name = new String[3]; // 3개의 문자열을 담을 수 있는 배열을 생성

int배열의 변수의 기본값은 0이지만 String배열의 변수의 기본값을 null이다.
그러므로 각 요소의 값을 null로 초기화 된다.

참고로 변수의 타입에 따른 기본값은 다음과 같다.

	자료형		|	기본값
	boolean		|	false
	char		|	'\u0000'
  byte, short, int	|	0
	long		|	0L
    	float		|	0.0f
        double		|	0.0d 또는 0.0
        참조형 변수	|	null.

2.2 String배열의 초기화

초기화 역시 int배열과 동일한 방법으로 한다. 아래와 같이 배열의 각 요소에 문자열을 지정하면 된다.

String[] name = new String[3]; // 길이가 3인 String배열을 생성
name[0] = "Kim";
name[1] = "Park";
name[2] = "Yi";

또는 괄호{}를 사용해서 다음과 같이 간단히 초기화 할 수도 있다.

String[] name = new String[] { "Kim", "Park", "Yi"};
String[] name = { "Kim", "Park", "Yi"}; // new String[]을 생략할 수 있음

특별히 String클래스만 "Kim"과 같이 큰따옴표만으로 간략히 표현하는 것이 허용되지만, 원래 String은 클래스이므로 new연산자를 통해 객체를 생성해야한다.

String[] name = new String[3];
name[0] = new String("Kim"); // new String()을 생력하고 "Kim"만 작성해도 된다
name[1] = new String("Park");
name[2] = new String("Yi");
예제5-12
public class ArrayEx12 {

	public static void main(String[] args) {
		String[] names = { "Kim", "Park", "Yi"};
		
		for(int i=0; i < names.length; i++) {
			System.out.println("name[" + i +"]:" + names[i]);
		}
		String tmp = names[2]; // 배열 names의 세번째 요소를 tmp에 저장
		System.out.println("tmp: " + tmp);
		
		names[0] = "Yu"; // 배열 names의 첫번째 요소를 "Yu"로 변경
		
		for(String str: names) { // 향상된 for문
			System.out.println(str);
		}
	}
}
예제5-13
public class ArrayEx13 {

	public static void main(String[] args) {
		char[] hex = { 'C', 'A', 'F', 'E'};
		
		String[] binary = {	  "0000", "0001", "0010", "0011"
					, "0100", "0101", "0110", "0111" 
					, "1000", "1001", "1010", "1011" 
					, "1100", "1101", "1110", "1111"};
		
		String result = "";
		
		for(int i=0; i < hex.length; i++) {
			if(hex[i] >= '0' && hex[i] <= '9') {
				result += binary[hex[i]-'0'];		// '8'-'0'의 결과는 8
			} else { 
				result += binary[hex[i]-'A'+10];	// 'C'-'A'의 결과는 2
			}
		}
		System.out.println("hex:" + new String(hex));
		System.out.println("binary:" + result);
	}
}

2.3 char배열과 String클래스

지금까지 여러 문자, 즉 문자열을 저장할 때 String타입의 변수를 사용했다. 사실 문자열이라는 용어는 '문자를 연이어 늘어놓은 것'을 의미하므로 문자배열인 char배열과 같은 뜻이다.
그런데 자바에서는 char배열이 아닌 String클래스를 이용해서 문자열을 처리하는 이유는 String클래스가 char배열에 여러 가지 기능을 추가하여 확장한 것이기 때문이다.
그래서 char배열을 사용하는 것보다 String클래스를 사용하는 것이 문자열을 다루기 더 편리하다.

String클래스는 char배열에 기능을 추가한 것이다.

char배열과 String클래스의 한 가지 중요한 차이가 있는데, String객체(문자열)는 읽을 수만 있을 뿐 내용을 변경할 수 없다.

String str = "Java";
str = str + "8";		// "Java8"이라는 새로운 문자열이 str에 저장된다.
System.out.printlb(str);	// "Java8"

윈의 문장에서 문자열 str의 내용이 변경되는 것 같지만, 문자열을 변경할 수 없으므로 새로운 내용의 문자열이 생성된다.

String클래스의 주요 메서드

String클래스는 상당히 많은 문자열 관련 메서드들을 제공하지만 지금은 가장 기본적인 몇 가지만 살펴보고 나머지는 9장에서 자세히 다룰 것이다. 자세히 이해하려 하지 말고 원하는 결과를 얻으려면 어떻게 코드를 작성해야하는지 정도만 이해하자.

		메서드			|			설명
   char charAt(int index)		|	문자열에서 해당 위치(index)에 있는 문자를 반환한다.
   int length()				|	문자열의 길이를 반환한다.
   String substring(int from, int to)	|	문자열에서 해당 범위(from~to)에 있는 문자열을 반환한다.(to는 범위에 포함되지 않음)
   boolean equals(String str)		|	문자열의 내용이 같은지 확인한다. 결과는 true 또는 false 출력
   char[] toCharArray()			|	문자열을 문자배열로 변환(char[])해서 반환한다.    

charAt

String str = "ABCDE"
char ch = str.charAt(3); // 문자열 str의 4번째 문자 'D' 를 ch에 저장

substring()
substring()은 문자열의 일부를 뽑아낼 수 있다. 주의할 것은 범위의 끝은 포함되지 않다는다.
예를 들어, inedx의 범위가 1~4라면 4는 범위에 포함되지 않는다.

String str = "012345";
String tmp = str.substring(1,4); // str에서 index의 범위 1~4문자들을 반환
System.out.println(tmp); // "123"이 출력

equlas
기본 변수의 값을 비교하는 경우 "=="연산자를 사용하지만, 문자열의 내용을 비교할 때는 equals()를 사용해야 한다. 그리고 이 메서드는 대소문자를 구분한다. 대소문자를 구분하지 않고 비교하려면 equlas()대신 equalsIgnoreCase()를 사용하자.

String str = "abc";
if(str.eqials("abc")) { // str와 "abc"가 내용이 같은지 확인한다.
	... // 변수str과 "abc"의 내용이 같다면 출력될 내용
	}

char배열과 String클래스의 변환

가끔char배열을 String클래스로 변환하거나, 또는 그 반대로 변환해야하는 경우가 있다. 그럴 때 다음의 코드를 사용하자.

char[] chArr = { 'A', 'B', 'C'};
String str = new String(chArr);	// char배열 -> String
char[] tmp = str.toCharArray();	// String -> char배열
예제5-14
public class ArrayEx14 {

	public static void main(String[] args) {
		String src = "ABCDE";
		
		for(int i=0; i < src.length(); i++) {
			char ch = src.charAt(i); // src의 i번째 문자를 ch에 저장
			System.out.println("src.charAt(" + i + "):" + ch);
		}
		char[] chArr = src.toCharArray(); // String을 char[]로 변환
		
		System.out.println(chArr); // char배열(char[])을 출력
	}
}

2.4 커맨드 라인을 통해 입력받기

Scanner클래스의 nextLine()외에도 화면을 통해 사용자로부터 값을 입력받을 수 있는 간단한 방법이 있다. 바로 커맨드라인을 이용한 방법인데, 프로그램을 실행할 때 클래스이름 뒤에 공백문자로 구분하여 여러 개의 문자열을 프로그램에 전달할 수 있다.
만일 실행할 프로그램의 main메서드가 담긴 클래스의 이름이 MainTest라고 가정하면 다음과 같이 실행할 수 있을 것이다.

	c:\jdk1.8\work]ch5\java MainTest abc 123

커맨드라인을 통해 입력된 두 문자열은 String배열에 담겨서 MainTest클래스의 main메서드의 매개변수(args)에 전달된다. 그리고는 main메서드 내에서 args[0], args[1]과 같은 방식으로 커맨드라인으로 부터 전달받은 문자열에 접근할 수 있다. 여기서 args[0]은 "abc"이고 args[1]은 "123"이 된다.

예제5-16
public class ArrayEx16 {

	public static void main(String[] args) {
		System.out.println("매개변수의 개수:" + args.length);
		
		for(int i=0; i < args.length; i++) {
			System.out.println("args[" + i + "] = \"" + args[i] + "\"");
		}
	}
}

커맨드라인에 입력된 매개변수는 공백문자로 구분하기 때문에 입력될 값에 공백이 있는 경우 큰따옴표(")로 감싸주어야 한다. 그리고 커맨드라인에서 숫자를 입력해도 숫자가 아닌 문자열로 처리된다. 문자열 "123"을 숫자 123으로 바꾸려면 다음과 같이 한다.

int num = Integer.parseInt("123"); // 변수 num에 숫자 123이 저장
예제5-17

화면으로부터 사칙연산을 수행하는 수식을 입력받아서 계산하여 그 결과를 보여주는 예제이다. 커맨드라인으로부터 입력받은 데이터는 모두 문자열이므로 숫자와 문자로 변환이 필요하며, Integer.parseInt()를 사용했다.

//import javax.swing.JOptionPane;

public class ArrayEx17 {

	public static void main(String[] args) {
		if(args.length != 3) {
			System.out.println("usage: java ArrayEx17 NUM1 OP NUM2");
			System.exit(0);
		}
		int num1 = Integer.parseInt(args[0]);
		char op = args[1].charAt(0);
		int num2 = Integer.parseInt(args[2]); 
		
//		자바스윙을 이용한 인풋다이얼로그 호출
/*		String ipNum1 = JOptionPane.showInputDialog("Enter a num1");
		String ipOp = JOptionPane.showInputDialog("Enter a op");
		String ipNum2 = JOptionPane.showInputDialog("Enter a num2");
		
		int num1 = Integer.parseInt(ipNum1);
		char op = ipOp.charAt(0);
		int num2 = Integer.parseInt(ipNum2); */
		
		int result = 0;
		
		switch(op) {
		case '+':
			result = num1 + num2;
			break;
		case '-':
			result = num1 - num2;
			break;
		case 'x':
			result = num1 * num2;
			break;
		case '/':
			result = num1 / num2;
			break;
		default :
			System.out.println("지원되지 않는 연산입니다.");
		}
		System.out.println("결과:" + result);
	}
}

3. 다차원 배열

지금까지 우리가 배운 배열은 1차원 배열인데, 2차원 이상의 배열, 즉 다차원 배열도 선언해서 사용할 수 있다. 메모리 용량이 허용하는 한, 차원의 제한은 없지만, 주로 1,2차원 배열이 사용되고 3차원 이상의 배열은 잘 사용되지 않는다. 2차원 배열만 잘 이해하고 나면 3차원 이상의 배열도 어렵지 않게 다룰 수 있으므로, 앞으로 2차원 배열에 대해서 중점적으로 배울 것이다.

3.1 2차원 배열의 선언과 인덱스

2차원 배열을 선언하는 방법은 1차원 배열과 같다. 다만 괄호[]가 하나 더 들어갈 뿐이다.

	    선언 방법 		|	    선언 예
	타입[][] 변수이름;	|	int[][] score;
	타입 변수이름[][];	|	int score[][];
	타입[] 변수이름[];	|	int[] score[];
  • 3차원 이상의 고차원 배열의 선언은 대괄호[]의 개수를 차원의 수만큼 추가해 주기만 하면 된다.

2차원 배열은 주로 테이블 형태의 데이터를 담는데 사용되며, 만일 4행 3열의 데이터를 담기 위한 배열을 생성하려면 다음과 같이한다.

int[][] score = new int[4][3]; // 4행 3열의 2차원 배열을 생성

3.2 2차원 배열의 초기화

2차원 배열도 괄호{}를 사용해서 생성과 초기화를 동시에 할 수 있다.다만, 차원 배열보다 괄호{}를 한번 더 써서 행별로 구분해 준다.

int[][] arr = new int[][] { { 1, 2, 3} , { 4, 5, 6} };
int[][] arr = { {1, 2, 3}, { 4, 5, 6} }; // new int[][]가 생력됨

크기가 작은 배열은 위와 같이 간단히 한 줄로 써주는 것도 좋지만, 가능하면 다음과 같이 행별로 줄 바꿈을 해주는 것이 보기도 좋고 이해하기도 쉽다.

int[][] arr = {
		{ 1, 2, 3},
        	{ 4, 5, 6}
  	      };
int[][] score = {
		{ 100, 100, 100},
        	{ 20, 20, 20},
            	{ 30, 30, 30},
                { 40, 40, 40},
                { 50, 50, 50}
               }

여기서 score.length의 값을 얼마일까? 정답은 5이다. 그리고 score[0].length은 score[0]이 참조하고 있는 배열의 길이이므로 3이다.

만일 for문을 이용해서 2차원 배열을 초기화한다면 다음과 같을 것이다.

// score의 모든 요소를 10으로 초기화
for (int i=0; i < score.length; i++) {
	for (int j=0; j < score[i].length; j++) {
    	score[i][j] = 10;
        }
}
예제 5-18

2차원 배열 score의 모든 요소의 합을 구하고, 출력하는 예제이다. 하나의 이중 for문으로 처리가 가능한 작업이지만, 향상된 for문으로 2차원 배열의 모든 요소를 읽어오는 방법을 보여주기 위해 출력과 합계를 따로 처리하였다.

public class ArrayEx18 {

	public static void main(String[] args) {
		int[][] score = {
							{ 100, 100, 100},
							{ 20, 20, 20},
							{ 30, 30, 30},
							{ 40, 40, 40}
						};
		int sum = 0;
		
		for (int i=0; i<score.length; i++) {
			for (int j=0; j<score[i].length; j++) {
				System.out.printf("score[%d][%d]=%d\n", i, j, score[i][j]);
			}
		}
		for (int[] tmp: score) {	// score의 각 요소(1차원 배열 주소)를 tmp에 저장
			for (int i: tmp) {		// tmp는 1차원 배열을 가리키는 참조변수
				sum += i;
			}
		}
		System.out.println("sum=" + sum);
	}
}
예제5-19
public class ArrayEx19 {

	public static void main(String[] args) {
		int[][] score = {
						  { 100, 100, 100}
						, { 20, 20, 20}
						, { 30, 30, 30}
						, { 40, 40, 40}
						, { 50, 50, 50}
						};
		// 과목별 총점
		int korTotal = 0;
		int engTotal = 0;
		int mathTotal = 0;
		
		System.out.println("번호  국어  영어  수학  총점  평균");
		System.out.println("===========================");
		
		for (int i=0; i<score.length; i++) {
			int sum = 0;		// 개인별 총점
			float avg = 0.0f;	// 개인별 평균
			
			korTotal += score[i][0];
			engTotal += score[i][1];
			mathTotal += score[i][2];
			System.out.printf("%3d", i+1);
			
			for (int j=0; j<score[i].length; j++) {
				sum += score[i][j];
				System.out.printf("%5d", score[i][j]);
			}
			avg = sum/(float)score[i].length; // 평균계산
			System.out.printf("%5d %5.1f\n", sum, avg);
		}
		System.out.println("============================");
		System.out.printf("총점:%3d %4d %4d\n", korTotal, engTotal, mathTotal);
	}
}

3.3 가변 배열

자바에서는 2차원 이상의 배열을 '배열의 배열'의 형태로 처리한다는 사실을 이용하면 보다 자유로운 형태의 배열을 구성할 수 있다.
2차원 이상의 다차원 배열을 생성할 때 전체 배열 차수 중 마지막 차수의 길이를 지정하지 않고, 추후에 각이 다른 길이의 배열을 생성함으로써 고정된 형태가 아닌 보다 유동적인 가변 배열을 구할 수 있다.

int[][] score = new int[5][];
score[0] = new int[4];
score[1] = new int[3];
score[2] = new int[2];
score[3] = new int[2];
score[4] = new int[3];

score.length의 값을 5지만 score[0].length, score[1].length의 값은 서로 다르다.
중괄호{}를 이용해서 생성과 초기화를 동시에 할 수 있다.

int[][] score = {
		, { 100, 100, 100, 100}
        	, { 20, 20, 20}
            	, { 30, 30}
                , { 40, 40}
                , {50, 50, 50}

3.4 다차원 배열의 활용

예제5-20

입력한 2차원 좌표의 위치에 x표를 표시

import java.util.Scanner;

public class MultiArrEx1 {

	public static void main(String[] args) {
		final int SIZE = 10;
		int x = 0, y = 0;
		
		char[][] board = new char[SIZE][SIZE];
		byte[][] shipBoard = {
		// 1  2  3  4  5  6  7  8  9
		 { 0, 0, 0, 0, 0, 0, 1, 0, 0}, // 1
		 { 1, 1, 1, 1, 0, 0, 1, 0, 0}, // 2
		 { 0, 0, 0, 0, 0, 0, 1, 0, 0}, // 3
		 { 0, 0, 0, 0, 0, 0, 1, 0, 0}, // 4
		 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 5
		 { 1, 1, 0, 1, 0, 0, 0, 0, 0}, // 6
		 { 0, 0, 0, 1, 0, 0, 0, 0, 0}, // 7
		 { 0, 0, 0, 1, 0, 0, 0, 0, 0}, // 8
		 { 0, 0, 0, 0, 0, 1, 1, 1, 0} // 9
		};
		// 1행에 행 번호를, 1열에 열 번호를 저장한다.
		for(int i=1; i<SIZE; i++) {
			board[0][i] = board[i][0] = (char)(i+'0');
		}
		Scanner sc = new Scanner(System.in);
		
		while(true) {
			System.out.println("좌표를 입력하세요.(종료는 00):");
			String inp = sc.nextLine();
			
			if(inp.length() == 2) {
				x = inp.charAt(0) - '0';
				y = inp.charAt(1) - '0';
			
				if(x==0 && y==0) // x,y모두 0일때 종료
					break;
			}
			if(inp.length() != 2) {
				System.out.println("잘못된 입력입니다. 다시 입력해주세요.");
				continue;
			}
			
			// shipboard[x-1][y-1]의 값이 1이면, '0'을 board[x][y]에 저장한다.
			board[x][y] = shipBoard[x-1][y-1] == 1 ? 'O' : 'X';
			
			//배열 board의 내용을 화면에 출력한다.
			for(int i=0; i<SIZE; i++) {
				System.out.println(board[i]); // board[i]는 1차원 배열
			}
			System.out.println();
		}
	}
}
예제5-21

빙고판을 만들고 입력받은 숫자를 빙고판에서 지운다.

예제5-22

두 행렬을 곱한 결과를 출력

예제5-23

영어 단어를 보여주고, 뜻을 맞추는 게임

profile
천천히 그리고 꾸준히

0개의 댓글