[JAVA] 기본 프로그래밍(입력 받기, 연산, 조건문)

최지수·2024년 1월 7일
post-thumbnail

📗자바에서 키 입력 받기

System.in

System.in은 키보드 장치를 직접 제어하고 키 입력을 받는 표준 입력 스트림 객체이다. 자바 응용프로그램은 아래 그림과 같이 System.in을 통해 사용자로부터 키를 입력받을 수 있다.

하지만 System.in은 입력된 키를 단순한 바이트 정보로 응용프로그램에게 제공하므로, 응용프로그램은 받은 바이트 정보를 문자나 숫자로 변환해야하는 번거로움이 있다. 그러므로 키보드에서 입력된 키를 문자나 정수, 실수, 문자열 등 사용자가 원하는 타입으로 변환해주는 Scanner 클래스를 사용하는 것이 효과적이다.

Scanner를 이용한 키 입력

Scanner는 응용프로그램이 키 입력을 쉽게 받을 수 있도록 자바 패키지에서 제공하는 클래스이다. 지금부터 Scanner를 이용하여 키 입력 받는 방법을 알아보자.

Scanner 객체 생성

다음과 같이 Scanner 객체를 생성한다.

Scanner scanner = new Scanner(System.in);

이 생성문에 의해 아래 그림과 같은 구조가 이루어지고, scanner 객체는 System.in 객체를 이용하여 키보드로부터 일련의 바이트 정보들을 입력받고, 이 바이트들을 정수, 실수 문자, 문자열 등 자바응용프로그램이 원하는 타입으로 변환하여 리턴한다.

import 문 사용

Scanner를 사용하기 위해서는 프로그램의 맨 앞줄에 다음 import 문이 필요하다.

import java.util.Scanner;

Scanner 클래스는 자바에서 제공되는 java.util 패키지에 있으므로, 이 import 문을 통해 Scanner의 경로명이 java.util.Scanner 임을 나타낸다. 이 import 문이 없으면 자바 컴파일러가 Scanner 클래스의 코드가 어디에 있는지 찾을 수 없다.

Scanner 클래스로 키 입력받기

Scanner 클래스는 사용자가 입력하는 키 값을 공백 문자(' ', '\t', '\n')를 기준으로 분리하여 토큰 단위로 읽는다. 예를 들어, "Kim Seoul 20 65.1 true"를 입력하면, scanner 객체는 빈칸으로 끊어 "Kim", "Seoul", "20", "65.1", "true"의 토큰 단위로 읽는다.

Scanner 클래스를 이용하여 키 입력을 받을 때 아래 그림과 같이 메소드를 사용한다.

nextLine()과 next()

"Seoul Korea"와 같이 공백이 낀 문자열을 입력받기 위해서는 Scanner 클래스의 nextLine()을 이용하면 된다. next()로는 공백이 낀 문자열을 읽을 수 없다. 앞의 경우 next()는 "Seoul"만 문자열로 리턴한다.
또한 nextLine()은 < Enter >키의 입력을 기다리는 용도로 사용할 수 있다. 다른 입력 없이 < Enter >키만 입력될 떄, nextLine()은 빈 문자열("")을 리턴하면서 바로 돌아오지만, next()를 사용하게 되면, < Enter > 키를 계속 입력하여도 문자열이나 숫자 등 다른 키가 입력될 떄까지 기다린다. next()는 결코 빈 문자열을 리턴하지 않는다.

Scanner 객체 닫기

Scanner 객체의 사용을 종료하려면 다음과 같이 닫아 준다.

scanner.close();

scanner 객체가 닫히면, System.in도 함께 닫히므로 더 이상 System.in을 사용하여 키 입력을 받을 수 없다.

scanner.close();
scanner = new Scanner(System.in);

위와 같이 scanner를 닫은 후 다시 scanner로 키 입력 받을 수 없다.

응용프로그램 전체에 Scanner 객체를 하나만 생성하고 공유하는 것이 바람직하다. Scanner 객체를 여러 개 생성해도 이들은 모두 하나뿐인 System.in을 공유하므로 한 군데서 Scanner.close()를 호출하여 Scanner 객체를 닫아버리면 System.in도 닫혀버려 응용프로그램 내 다른 Scanner 객체에서 키 입력을 받을 수 없게 된다.


📗연산

식과 연산자

주어진 식을 계산하여 결과를 얻어내는 과정을 연산이라고 한다.

위 그림 식에서 +,>,==을 연산자(operator), 데이터를 피연산자(operand)라고 한다. 자바에서 종류 및 연산자는 아래 그림과 같이 다양하다.

연산자 우선순위

식에 여러 개의 연산자가 있는 경우, 우선순위가 높은 연산자를 먼저 처리한다. 우선순위가 동일하면 왼쪽에서 오른쪽으로 처리하나, 대입 연산자, --, ++, +(양수 부호), -(음수 부호), !, 타입 변환 연산자 등은 오른쪽에서 왼쪽으로 처리한다. 괄호는 항상 최우선적으로 처리한다. 식에 다수의 괄호가 포함된 경우 왼쪽에서 오른쪽으로 처리하며, 괄호가 다시 괄호를 포함한 경우는 안쪽부터 먼저 처리한다.

산술 연산

산술 연산자는 더하기(+), 빼기(-), 곱하기( * ), 나누기 (/), 나머지(%)의 5개가 있다. 정수 연산에서 '/'는 몫을, '%'는 나머지를 구한다.

연산자 +(더하기)
-> 25.5 + 3.6 = 29.1
연산자 -(빼기)
-> 3 - 6 = -3
연산자 (곱하기)
-> 2.5
4.0 = 10.0
연산자 /(나누기)
-> 5 / 2 = 2
연산자 %(나머지)
-> 5 % 2 = 1

증감 연산

증감 연산자는 ++, --의 두 가지이며, 피연산자의 앞 또는 뒤에 붙어 값을 1 증가시키거나 1 감소시킨다.

int a = 1;
a++;  // a 값 1증가. a는 2
++a;  // 다시 a 값 1 증가. a는 3

연산자가 변수의 앞에 붙을 때 전위 연산자라고 부르고, 뒤에 붙을 때 후위 연산자라고 부른다. 이 둘은 모두 1 증가시키는 연산을 실행하지만 연산 결과로 반환하는 값은 서로 다르다. 전위 연산자의 경우, ++a가 계산되어 a는 2가 되고 ++a의 연산 결과로 2를 반환하여, a, b 모두 2가 된다. 하지만 a++의 경우, a++가 계산 되어 a의 값은 2가 되지만, 증가되기 전 a 값을 반환하여 b의 값이 1이 된다.

a++ => a를 1 증가하고 증가 전의 값 반환
++a => a를 1 증가하고 증가된 값 반환
a-- => a를 1 감소하고 감소 전의 값 반환
--a => a를 1 감소하고 감소된 값 반환

대입 연산

대입 연산자는 연산자의 오른쪽 식의 결과를 왼쪽에 있는 변수에 대입한다. 대입 연산 종류는 다음과 같다.

a = b -> b의 값을 a에 대입 a &= b -> a = a & b와 동일
a += b -> a = a + b와 동일 a |= b -> a = a | b와 동일
a -= b -> a = a - b와 동일 a ^= b -> a = a ^ b와 동일
a = b -> a = a b와 동일 a <<= b -> a = a << b와 동일
a /= b -> a = a / b와 동일 a >>= b -> a = a >> b와 동일
a %= b -> a = a % b와 동일 a >>>= b -> a = a >>> b와 동일

비교 연산과 논리 연산

비교 연산자는 두 개의 피연산자를 비교하여 true 또는 false의 논리 값을 내는 연산자이며, 논리 연산자는 논리 값을 대상으로 AN, OR, XOR, NOT의 논리 연산을 하여 논리 값을 내는 연산자이다.

비교 연산자
a < b -> a가 b보다 작으면 true
a > b -> a가 b보다 크면 true
a <= b -> a가 b보다 작거나 같으면 true
a >= b -> a기 b보보다 크거나 같으면 true
a == b -> a가 b와 같으면 true
a != b -> a가 b와 같지 않으면 true

논리 연산자
!a -> a가 true이면 false, false이면 true
a || b -> a와 b의 OR 연산, a와 b 모두 false인 경우에만 false
a && b -> a와 b의 AND 연산, a와 b 모두 true인 경우에만 true

비교 연산자와 논리 연산자를 복합하여 사용할 수 있다. age,c,x,y가 모두 변수일 때 복합하여 사용하는 예는 다음과 같다.

(age >= 20) && (age < 30)  // 나이(int age)가 20대인 경우
(c >= 'A') && (c <= 'Z')   // 문자(char c)가 대문자인 경우
(x >= 0) && (y >= 0) && (x <= 50) && (y <= 50)
// (x,y)가 (0,0)과 (50,50)의 사각형 내에 있음

위의 첫 번째 코드를 다음과 같이 작성하면 오류이다.

(age >= 20) && (age < 30)
-> 20 <= age < 30 // 오류

조건 연산

조건 연산자는 3개의 피연산자로 구서되어 삼항(ternary)연산자라고도 하며 형식은 다음과 같다.

condition ? opr2 : opr3

앞의 식에서 조건문(condition)이 true이면 위 식의 결과 값은 opr2의 값이 되고, false이면 opr3의 값이 된다. opr2나 opr3은 식이 될 수도 있고 값이 될 수도 있다.

int x = 5;
int y = 3;
int s = (x>y)? 1 : -1;

위의 식은 x>y의 값이 true이면 s는 1이 되고 false이면 s는 -1이 된다. 값을 대입해보면 x는 5이고 y는 3에서 x가 y보다 크다는 식은 true가 되므로 s의 값은 1이 된다.

비트 연산

비트 연산은 비트끼리 AND, OR, XOR, NOT 연산을 하는 비트 논리 연산과, 비트를 오른쪽이나 왼쪽으로 이동시키는 비트 시프트 연산이 있다.

비트란 컴퓨터의 모든 정보는 0과 1값만 가지는 2진수로 다루어지고 저장되는데 2진수의 한 자리를 비트(bit)라 부르며, 8개의 비트를 바이트(byte)라고 한다.

a & b -> AND 연산 -> 두 비트 모두 1이면 1, 그렇지 않으면 0
a | b -> OR 연산 -> 두 비트 모두 0이면 0, 그렇지 않으면 1
a ^ b -> XOR 연산 -> 두 비트가 다르면 1, 같으면 0
~ a -> NOT 연산 -> 1을 0으로, 0을 1로 변환

비트 시프트 연산

비트 시프트 연산(shift operator)는 3개의 연산자를 이용하여 새로운 비트를 오른쪽이나 왼쪽 끝에 삽입하면서 비트의 자리를 이동시키는 연산이다. 저장 공간의 크기가 정해져 있으므로 시프트되는 방향에 따라 끝에 있는 비트는 사라지게 된다.

a >> b
-> a의 각 비트를 오른쪽으로 b번 시프트한다. 최상위 비트의 빈자리는 시프트 전의 최상위 비트로 다시 채운다. 산술적 오른쪽 시프르라고 한다.
a >>> b
-> a의 각 비트를 오른쪽으로 b번 시프트한다. 최상위 비트의 빈자리는 항상 0으로 채운다. 논리적 오른쪽 시프트라고 한다.
a << b
-> a의 각 비트를 왼쪽으로 b번 시프트한다. 최하위 비트의 빈자리는 항상 0으로 채운다. 산술적 왼쪽 시프트라고 한다.

시프트 연산의 피연산자는 byte, short, int, long, char 타입만 가능하고, float, double, boolean은 사용할 수 없다.
<< 연산자는 왼쪽 시프트 연산자로서 각 비트를 왼쪼그로 이동시키며, 오른쪽 끝에는 하상 비트 0이 삽입된다. 다음 코드는 a의 각 비트를 왼쪽으로 2번 이동시킨 결과를 변수 b에 저장하며, 그 결과 b의 값은 20이 된다.

byte a = 5;
byte b = (byte) (a << 2);  // a 값을 왼쪽으로 2비트 이동. b 값은 20

>>> 연산자는 비트를 오른쪽으로 이동시키며, 왼쪽 끝에는 항상 비트 0이 삽입된다. 다음 코드는 변수 a의 각 비트들을 2번 오른쪽으로 이동시킨 결과를 변수 b에 저장한다. 그 결과 b 값은 5가 된다.

byte a = 20;
byte b = (byte) (a >>> 2);  // a 값을 오른쪽으로 2비트 이동. b 값은 5

>> 연산자는 오른쪽 시프트 연산자이지만 >>>와 달리, 왼쪽 끝의 최상위 비트에는 시프트 이전의 최상위 비트가 그대로 삽입된다. 다음은 >> 연산의 사례이다.

byte a = 20;
byte b = (byte) (a >> 2);  // 변수 a 값을 오른쪽으로 2비트 이동. b 값은 5
byte c = (byte) 0xf8;      // 0xf8는 -8을 16진수로 표현한 값
byte d = (byte) (c >> 2);  // 변수 c를 오른쪽으로 2비트 이동. d 값은 0xfe가 된다. 
                           //0xfe는 십진수로 -2


📗조건문

단순 if문

if 문의 조건식은 비교 연산이나 논리 연산이 혼합된 식으로 구성되며, 조건식의 결과는 boolean 값이다. 조건식이 참(true)이면 if 내부의 '실행 문장'이 실행되며, 거짓(false)이면 if 문을 벗어난다. 조건식은 boolean 타입의 변수 하나만으로도 가능하다. 다음은 if 문을 사용하여 정수 n이 짝수인지 판별하는 코드이다. n을 나눈 나머지가 0이면 n은 짝수이다.

if (n % 2 == 0) {
    System.out.println(n + "은(는) 짝수입니다.);
}

if-esle 문

if-else 문은 if의 조건식이 참인 경우와 거짓인 경우에 각각 실행할 문장을 지시할 수 있다. 조건식이 true이면 실행 문장1을 실행한 후 if-else 문을 벗어나고, false이면 실행 문장2를 실행한 후 if-else 무늘 벗어난다. if 문만 활용해 짝수 판별하는 것을 if-else로 코드를 작성하면 다음과 같다.

if (n % 2 == 0) {
    System.out.println(n + "은(는) 짝수입니다.");
{
else {
    System.out.println(n + "은(는) 홀수입니다.");
}

if와 else의 실행문이 하나의 문장이면 역시 중괄호를 생략할 수 있다.

switch 문

값에 따라 여러 방향으로 분기하는 경우, if 문보다 switch 문을 사용하면 가독성이 높은 좋은 코드를 작성할 수 있다. swith 문은 다음과 같이 구성된다.

switch (식) {
    case 값1:       // 세미 콜론이 아닌 콜론
        실행 문장 1; // 세미 콜론
        break;
    case 값2:
        실행 문장 2;
        break;
    ...
    case 값m:
        실행 문장 m;
        break;
   default:
       실행 문장 n;
}

switch 문은 먼저 식을 계산하고 그 결과 값과 일치하는 case 문으로 분기한다. case문의 실행 문장을 실행한 후 break를 만나면 switch 문을 벗어난다. 만일 어떤 case 문으로도 분기하지 못하는 경우 default 문으로 분기하여, 실행 문장 n을 실행한다. default 문은 생략 가능하며, 실행 문장은 중괄호로 둘러싸지 않는다.

참고
명품 JAVA Programming 귀로 배우는 자바가 아니라 눈으로 몸으로 배우는 자바강좌

profile
오늘보다 내일 더 성장하는 개발자🌱

0개의 댓글