프로그래밍언어/Go

fmt 패키지를 이용한 텍스트 입출력 / Tucker님의 Go 언어 프로그래밍 #5

구구절절2 2021. 5. 8. 22:18
반응형

본글은 『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패키지 에서 표준입력 함수를 제공한다.

📌
Scan() : 값을 입력받음 Scanf() : 서식형태로 입력받음 Scanln(): 한줄 읽어서 값을 입력받는다. 이것을 주로 사용

만약 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은 입력받은 개수이다. 



}

반응형