문제 제목 : 문자와 문자열
문제
단어 S
와 정수 i
가 주어졌을 때,
S
의 i
번째 글자를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 영어 소문자와 대문자로만 이루어진 단어 S
가 주어진다.
단어의 길이는 최대 1,000 이다.
둘째 줄에 정수 i
가 주어진다.
( 1 <= i
<= |S|
)
출력
S
의 i
번째 글자를 출력한다.
예제 입력 1
Sprout
3
예제 출력 1
r
예제 입력 2
shiftpsh
6
예제 출력 2
p
예제 입력 3
Baekjoon
4
예제 출력 3
k
문자와 문자열의 처리 과정에 대해서 알아야 하는 이유가 뭘까?
회사의 알고리즘 문제에 나와서? 과제로 주어졌기 때문이었을까?
아니면 백준의 알고리즘 풀이에 입력과 출력은 절대적이기 때문일까?
위의 의견이 틀리지 않다. 하지만, 큰 그림을 보았을 때 이것을 왜 해야 하는가
생각하는 것이 중요하다고 판단했다.
사실, 나는 문자와 문자열 단계는 백준의 문제를 풀며,
입력과 출력을 함에 있어 절대적으로 필요한 단계라고 생각한다.
이 단계를 거치며, 자신이 어떠한 입출력 클래스와 메서드를 사용할 것인지 고착화 될 것이기 때문이다.
하지만, 여기서 시야를 더 넓혀보자. 우리는 문자와 문자열을 왜 알아야 할까?
혹시 regex
라는 단어를 본 적 있는가?
Regular Expression 의 약자로, 정규표현식을 의미한다.
수많은 글자 데이터 속에서 우리가 원하는 데이터를 찾기 위해 위의 정규표현식을 사용한다.
예를 들면, *.md
정규표현식을 선언하면, 해당 데이터 집합의 모든 .md
마크다운 확장자 파일을 의미한다.
말하고자 하는 것은, 우리는 복잡한 문자열이 주어졌을 때,
본인의 고도화 된 프로그래밍 언어로 데이터를 추출 할 수 있도록 정규표현식 기능을 구현할 수 있어야 한다.
물론, 우리가 백준에서 파헤치게 될 문자와 문자열 파트는, 정규표현식을 배운 것은 아니다.
하지만, 우리가 해당 언어로 디버깅을 하게 되면서 콘솔 을 이용하게 되는데,
이 콘솔의 입출력 방식을 조금은 고도화 시켜야 한다는 것이다.
그리고 또한, 프로그램의 자료형으로 표현하지 못할 거대한 숫자를 문자열 형태로 저장할 수도 있다.
결국 숫자, 특수문자, 문자는 전부 문자열 로 치환이 가능하다.
따라서, 해당 프로그램의 문자열을 다룰 수 있는 클래스와 메서드들을 배우게 되는 것이다.
이번 파트를 시작하게 되면서 생각이 얽키고 섥혀 선두가 길어지게 되었다.
이번 문제의 중심은 입력, 그리고 출력 에만 집중되어 있다.
이 글을 보는 분이 초보라면, 방법 을 선택해야 하는 시간이 온 것이다.
Java 입력 출력
Java
언어의 입출력 방법은 생각보다 다양하다.
애초에 복잡하고 어려운 C++
, 간단한 Javascript
와 같은 언어와는 달리,
프로그램에 할당되어 있는 입력 및 출력 리소스를 할당할 수 있는 객체들이 많다.
1. Scanner
사실, 자바를 처음 공부하며 디버깅을 하게 되면서 배우게 될 가장 기초적인 클래스가 아닐까 싶다.
앞으로 어려운 알고리즘 문제를 푸는 데 있어서 Scanner
해당 객체의 메서드로도 충분히 해결이 가능하다.
단어, 해당 줄, 정수, 소수 등, 다양한 언어로 즉시 Parsing 이 가능하며, 메서드가 간단 한 편이다.
다른 객체에 비해 편의성을 위한 기능이 탑재되어 있어 메모리 차지와 속도에 있어 약간 뒤쳐지는 편이다.
하지만, 에러 처리를 코드 사용자가 작성 할 필요가 없다.
2. System.in
이는 클래스가 아니라, System
즉, 시스템 리소스를 관리하는 절대적 객체의 입력 리소스를 의미한다.
System.in.read()
와 같은 메서드로 곧바로 사용하기에는 너무 제한적인 면이 많으며,
오히려 입력 객체를 생성하여 System.in
의 메서드를 불러와서 만든다.
이 리소스를 언급 한 이유는, 모든 편의성 입력 도움 객체들은 이 리소스로 초기화 되기 때문이다.
Example :
new Scanner(System.in);
new BufferedReader(new InputStreamReader(System.in));
3. BufferedReader
프로그램 입력 리소스를 처리하는데 있어 Scanner
의 대용품으로 사용되며,
Scanner
보다 더 빠르고 메모리를 덜 처리한다.
하지만, 편의성 메서드가 그만큼 적기 때문에, 사용자가 생각하고 처리해야 할 것이 더 생긴다.
그러나, Scanner
로도 해결되지 않는 입력이 존재하기 때문에,
결국 StringTokenizer
와 같은 토큰 분리기를 사용하는 것이 더 편하게 된다.
Scanner
로 입력 리소스를 관리해도 괜찮으며, BufferedReader
로 관리해도 괜찮다.
단점으로는, 선언 시 굉장히 긴 코드를 작성해야 한다는 귀찮음이 존재한다.
System.in
입력 리소스 할당은 InputStreamReader
이라는 편의성 객체로 들어가고,
InputStreamReader
객체에서 메서드를 더 구현한 BufferedReader
클래스로 할당된다.
*할당 시 * : BufferedReader = new BufferedReader(new InputStreamReader(System.in))
그러나, 코드 작성자는 에러 처리를 위한 코드를 작성해야 한다.
4. System.out
시스템 프로그램의 출력 을 담당하며, 그나마 편하게 작성 할 수 있다.
System.out.print(출력할것)
or System.out.println(출력할 것)
한 줄에 이어서 작성 or 한 줄을 통째로 작성 , 이렇게 가능하다.
출력 리소스를 관리할 수 있는 BufferedWriter
객체가 존재하지만,
나도 처음에 썼다가 더 작성할 이유를 찾지 못하여 System.out.println
을 사용 중이다.
5. StringBuilder();
이 객체는 출력할 답을 모두 모아서 System.out.println(StringBuilder 객체)
로 출력한다.
기존에도 수많은 메서드와 편의 기능을 지원하던 String
객체의 진화 버전이며,
String
객체는 말 그대로 문자열 을 의미하지만,
StringBuilder
객체는 기록 을 하는 것과 비슷하다.
하지만, 결국 StringBuilder
객체도 String
의 구현 버전이라는 것을 잊지 말자.
Answer 1 - Scanner 사용
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
int index = scanner.nextInt();
System.out.println(str.charAt(index - 1));
}
}
Scanner
입력 객체에는, hasNext()
라는 메서드가 존재한다.
이는 하나의 줄에서 Delim(분리할 문자) 로 분리되는 하나의 단어를 Token(토큰) 이라고 부르는데,
하나의 줄에서 그 다음 토큰 이 존재하는지 boolean
타입으로 알려준다.
만약 false
가 답변으로 나온다면, 해당 줄의 다음 문자나 문자열은 존재하지 않는다는 뜻이다.
Answer 2 - BufferedReader 사용
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
int index = Integer.parseInt(br.readLine());
System.out.println(str.charAt(index - 1));
}
}
'백준-단계별로 풀어보기 > 5-문자열' 카테고리의 다른 글
백준 5622 Java - 다이얼 (0) | 2024.09.11 |
---|---|
백준 10809 Java - 알파벳 찾기 (0) | 2024.09.10 |
백준 11720 Java - 숫자의 합 (0) | 2024.09.09 |
백준 11654 Java - 아스키 코드 (1) | 2024.09.09 |