본글은 『Tucker의 Go 언어 프로그래밍』 스터디 요약 노트입니다.
표준입출력
프로그램과 사용자는 입력과 출력을 통해 상호작용한다.
보통 입력은 키보도와 마우스로한다고 생각할 수 있지만
네트워크를 통해 입력할 수 있고 파일을 통해서도 입력할 수 있다.
이런 입출력을 모두 구현해야한다면 프로그램은 복잡해질 것이다.
따라서 이때에는 운영체제가 제공하는 표준 입출력 스트림을 사용한다.
fmt패키지
표준출력함수는 fmt라는 패키지로 제공이 된다.
각각을 살펴보자.
print()
: 입력값들을 출력함
println()
: 입력값들을 출력하고 개행한다.(다음줄로 넘어간다는 뜻, enter누른다는 뜻)
printf()
: 서식(format)에 맞추어서 출력함
예를 들면
package main
import "fmt"
func main() {
var a int = 10
var b int = 20
var f float64 = 32799438743.8297
fmt.Print("a:",a, "b" , b) //개행하지 않고 다음 줄도 바로 옆에 써진다.
fmt.Println("a:",a,"b:",b, "f:" , f) //개행한다.
fmt.Printf("a: %d b: %b f: %f\n" , a , b, f)
//출력값
// a:10b20a: 10 b: 20 f: 3.27994387438297e+10
// a: 10 b: 10100 f: 32799438743.829700
}
\n은 개행을 뜻한다.
서식문자
printf() 함수는 다음과 같은 형식으로 사용된다.
printf(서식 문자열,인수1,인수2..)
대표적 서식지정자의 특징
- %d : 정수타입 integer ,decimal
- %f : float type 값을 출력하는데 실수형태로 출력(지수형태 아님)
- %g : 6자리이하면 실수형태로 그보다 크면 지수형태로 출력
- %v : 데이터 타입에 맞춰서 기본형태로 출력
- %T: 데이터의 타입을 출력
- %q : 특수 문자 기능을 동작하지 않고 문자열 그대로 출력
- %p : 메모리 주솟값을 출력
최소 출력 너비 지정
printf()로 서식을 정할 때 최소로 출력해야하는 너비를 지정할 수 있다.
예제로 살펴보자.
서식지정자 %와 타입을 나타내는 문자 사이에 숫자를 넣어 최소 너비를 지정할 수 있다.
그리고 너비 앞에 0을 붙이면 빈자리를 0으로 채운다.
마이너스 -를 붙이면 왼쪽을 기준삼아 출력한다.
%5d이라면 123이라면 두칸 띄우고 빈빈123이다
(빈 = 빈칸)
최소출력 너비는 말그대로 최소인점을 유의하면서 예제를 보자
package main
import "fmt"
func main() {
a:= 10
b:= 456
c:= 123456789
fmt. Printf("%5d, %5d\n",a,b) //1
fmt. Printf("%05d, %05d\n",a,b) //2
fmt. Printf("%-5d, %-05d\n",a,b)//3
fmt. Printf("%5d\n",c) //4
fmt. Printf("%05d\n",c) //5
//출력값
// 10, 456 (너비 최소 5칸 부족한칸은 빈칸으로 대체 )
// 00010, 00456 (너비 최소 5칸 부족한 칸은 0으로 채운다.)
// 10 , 456 (왼쪽으로 밀려서 출력 부족한칸은 빈칸으로 대체)
// 123456789 (최소넓이가 5일뿐 그것보다 길면 모두 출력 )
// 123456789 (최소넓이가 5일뿐 그것보다 길면 모두 출력 )
}
실수 소수점 이하 자릿수
실숫값에서는 최소 출력 너비뿐 아니라 소수점 이하 자릿수도 지정할 수 있다.
실수를 나타낼 수 있는 서식지정자는 2개가 있다. 각각은 다르게 최소출력너비를 지정한다.
%f : %5.2f라고 한다면 최소너비 5칸에 소수점 이하 값 2개를 출력함
%g : 실수를 정수부와 소수점 이하 숫자를 포함해 출력 숫자 자체를 제한한다.
그리고 제한된 숫자로 정수부를 표현하지 못하면 지수형으로 표현된다.
예제를 보면서 자세히 살펴보자.
package main
import "fmt"
func main() {
a:= 324.123455
c:= 3.14
fmt.Printf("%08.2f\n", a)
fmt.Printf("%08.2g\n", a)
fmt.Printf("%8.5g\n", a)
fmt.Printf("%f\n", c)
//출력값
// 00324.12 : 08.2f 는 최소너비 8에 소수점 숫자는 2개만 표시하는 것을 뜻한다.
// 03.2e+02 : 08.2g 는 숫자자체를 2개만 표시하고 최소너비8칸을 말한다.
// 정수부 324를 숫자 2개로 표현하지 못하므로 지수형으로 표현한다.
// 324.12 : 8.5g는 최소너비 8개에 숫자5개로 표현해야한다. 정수부 324표현 가능하므로 실수형표현가능
// 3.140000 : f 출력의 기본은 소수점 이하 숫자 6개 표현이다.
}
표준입력
사용자가 입력장치(예를 들면 키보드)로 입력하면 그 데이터는 컴퓨터 내부에 표준 입력 스트림이라는 메모리 공간에 임시 저장된다. 표준입력 함수들은 그 표준 입력 스트림에서 값을 읽어서 입력값을 처리한다.
fmt패키지 에서 표준입력 함수를 제공한다.
만약 int 타입 입력을 받고자 할 때 사용자가 Hello 4
를 입력했다고 가정하자.
그렇다면 표준입력스트림에서는 다음과 같이 데이터가 저장된다.
(Scanln()으로 입력받았다고 가정한다.)
\n4 olleH
왜 그럴까?
가장 먼저 입력한 데이터부터 읽기 때문에 데이터는 거꾸로 저장된다.
Scan() 함수는 먼저 표준 입력 스트림에서 한 글자씩 읽어온다.
이때 한번 읽은 데이터는 다시 읽어올 수 없다.
처음 읽은 값은 'H'인데 이것은 int타입이 아니고 문자타입이다.
따라서 error를 반환한다.
남아있는 "ello4\n" 의 데이터도 하나하나씩 읽는다.
그런데 이미 에러인데 다음 입력을 가져올 필요는 없다.
따라서 Scanln() 표준 입력 스트림을 비워주는데 그 소스 코드는 다음과 같다.
package main
import (
"bufio" // 입력스트림으로부터 한 줄을 읽는 reader 객체를 제공한다.
"fmt"
"os" //표준 입출력을 가지고 있는 패키지이다.
)
func main(){
stdin := bufio.NewReader(os.Stdin) // := 는 선언 대입문이다. var 과 똑같은 것이다. 변수의 선언과 대입이 한꺼번에 된다.
// stdin은 스탠다드 인풋의 약어 표준입력을 나타낸다.
var a int
var b int
n,err := fmt.Scanln(&a,&b) //n과 err 은 scanln의 출력값이다. 굳이 n과 err로 설정하지 않아도된다.
//Scanln은 메모리주소값을 인자로 받는다.
//입력값을 가지고 메모리주소값으로 가서 그 데이터를 변경해주는 것이다.
if err != nil {
// go언어에서 nil은 포인터,인터페이스,맵,슬라이스,채널,함수 타입의 zero value이다.
// 쉽게 말한다면 그 값이 비어있는 상태인 것이다.(존재하지만 비어있다. 마치 strint s = ''과 같다.)
// 따라서 err != nil 은 에러가 비어있지않다면 == 있다면
fmt.Println(err)
stdin.ReadString('\n') //stdin에서 어떤 문자열이 있을 때까지 읽어라 여기선 \n이 나올 때까지 때까지 읽어라 라는뜻
// \n이 등장할 때까지 읽어버려서 남아있는 오류 데이터까지 읽을 필요 없음
} else {
fmt.Println(n,a,b)
}
//다시 반복
n,err = fmt.Scanln(&a,&b)
if err != nil {
fmt.Println(err)
stdin.ReadString('\n')
} else {
fmt.Println(a,b)
}
//hello 4를 입력하면 expected integer가 뜬다. 이말은 뭐냐면 integer를 원했는데 integer가 아닌것이다.
//n은 입력받은 개수이다.
}
Uploaded by Notion2Tistory v1.1.0