[Go] bufio Reader와 Scanner

개발개발·2022년 9월 13일
0

코딩테스트를 풀던 중 bufio에 대해서 이해할 일이 생겨서 작성한다. 분명 예전에 다른 문제를 풀다가 읽은적이 있는데 기억에서 사라져서 기록으로 남겨둔다.

결론 : 입력값이 지나치게 큰 경우에는 Scanner대신 Reader를 이용해서 받아야 한다.

아래는 백준 10610문제와 풀이 코드다.

// 오답으로 나온다.
func main() {
	r:= bufio.NewScanner(os.Stdin)
	r.Scan()

	numbers :=make([]int,10)
	sum :=0
	for _, v := range r.Text() {
		numbers[v-'0']+=1
		sum+=(int)(v-'0')
	}
	if sum %3!=0 || numbers[0]==0{
		fmt.Println(-1)
		return
	}
	var b bytes.Buffer
	for i := 9; i >= 0; i-- {
		for j := 0; j < numbers[i]; j++ {
			b.WriteByte((byte)(i+'0'))
		}
	}
	fmt.Println(b.String())

}
// 정답으로 나온다.
func main() {
	r:= bufio.NewReader(os.Stdin)
	var s string
	fmt.Fscan(r,&s)

	numbers :=make([]int,10)
	sum :=0
	for _, v := range s {
		numbers[v-'0']+=1
		sum+=(int)(v-'0')
	}
	if sum %3!=0 || numbers[0]==0{
		fmt.Println(-1)
		return
	}
	var b bytes.Buffer
	for i := 9; i >= 0; i-- {
		for j := 0; j < numbers[i]; j++ {
			b.WriteByte((byte)(i+'0'))
		}
	}
	fmt.Println(b.String())

}

두 풀이의 차이점은 파라미터를 입력받는 방법이다. 오답의 경우 scanner를 사용했고 정답의 경우 reader를 사용했다. 결과만 두고 알 수 있는 점은 어떠 방식으로 받는지에 따라 파라미터를 다르게 받아들인다는 것이다. 자세히 알아보기 위해 golang doc(https://pkg.go.dev/bufio#Scanner)을 살펴보았다.


-> scanner는 buf를 읽는 편리한 인터페이스로 split 함수로 토큰을 쪼개서 받고 기본적인 delemiter는 lines라고 한다. 가장 핵심적인 내용은 두번째 문단에 있다. 입력값이 클때는 조심해서 다뤄야 한다고 알려준다. 중간 중간 scan으로 buf에 있는 내용을 읽거나 reader를 사용하라고 알려주고 있다.

즉 입력값이 너무 큰 경우에는 scanner에서 scan을 사용하면 에러가 발생할 가능성이 있다는 것이다. 얼마만큼을 입력값으로 받을 수 있는지 구글링 도중 찾은 블로그에서는(https://wookiist.dev/121) 64kb라고 알려주고 있다.

문제에서 입력값으로 최대 1,000,000개의 숫자로 구성되어있다고 하니 scanner를 사용했을 경우 오답이 발생한 것이다.

profile
청포도루이보스민트티

0개의 댓글