본문 바로가기
국비수업

[국비 Java 3일차] 과제 코드리뷰 / printf() 메소드/ 강제 자동 형변환

by 박다비 2022. 10. 20.

 

 

오늘은 아침에 학원가는데 사당에서 강남행 지하철을 2대를 떠나 보냈다....

쟈철은 1분마다오는데 와 이리 사람이 많은교....? 증말 서울의 인구밀도는 미쳤다. 지방이랑 좀 노나 가집시다ㅠㅠ

원래는 1시간 거리 강남이 2시간거리가 되는 기적

 

 

아무튼 오늘 배운 것은

어제 과제 풀이를 한시간정도하고

printf 와 형변환 (변수) 의 강제형변환/자동형변환을 배웠다

 

 

과제풀이에서 내가 고쳐야 할 부분은 

Scanner 객체를 생성하고 문자를 입력을 받아야 하는 상황에서 

System.out.print("성별을 입력하세요(남/여) : ");
		//String gender = sc.nextLine();
		char gender = sc.nextLine().charAt(0);

한글자값을 String 타입으로 받은거~

String 변수로 담아도 틀린 것은 아니지만 한글자면 2byte만 쓰면 되는데 메모리 공간 낭비이다~

그리고 사용자가 남/여 란 글자말고 한글자 이상의 값을  입력할 수도 있는데 출력이 내가 생각하는 것과 다르게 나올 수 있다~ 라는 부분!  그래서 char gender = sc.nextLine().charAt(0); 가 더 올바른 코드이다!

charAt() 메소드는 4번째 문제에서 다시 사용하긴 했지만 여기서는 간과했다!  최대한 효율적인 코드를 짜려고 해보자!

 

 

 

그리고 두번째! 틀린건 아니지만 다른부분 

System.out.println("첫번째 문자 : " + message.charAt(0)); //강사님코드
System.out.println("두번째 문자 : " + message.charAt(1));
System.out.println("세번째 문자 : " + message.charAt(2));

//내코드
	char c1 = str.charAt(0);
	System.out.println("첫번째 문자 : " +c1);
	
	char c2 = str.charAt(1);
	System.out.println("두번째 문자 : " +c2);
	
	char c3 = str.charAt(2);
	System.out.println("세번째 문자 : " +c2);

둘다 같은 코드지만  강사님의 코드가 훨씬 간결하고 코딩속도, 로드 속도도 빠르다!

내 코드는 굳이....? 굳이 저렇게 했어야했나? ㅋㅋㅋ 

어차피 변수에 넣어서 같은 코드가 반복이 된다면 로드속도가 빠를것 같은걸로.... 더 간결한걸로

코드는 짧을수록 좋은 코드이기 때문에 강사님 코드를 잘 기억하도록하자~ 

 

 

 

printf() 메소드

 

printf() 메소드는 우리가 엄청 자주 사용하는 System.out.print("출력할내용")의  print()메서드와 개행도 같이 해주는 println()메서드와 비슷한 종류의 출력 메소드임.

 

어떨때 쓰냐면~

출력할때 많은 문자와 많은 변수가 들어갈때  +연산자 없이 쭉쭉쭉 한번에 같이  좀 더 간편하게 쓸 수 있는 장점이 있다.  

특히 뛰어쓰기 공백이나 변수나 문자가 서로 중간중간 마니 혼합된경우 사용될때 편한것같다

글고 오른쪽 정렬 왼쪽 정렬? 할 때도 쓰고

실수형값을 원하는자리까지만 간단하게 출력하고싶을때

입력한 값을 다 대문자로 바꾸고 싶을때 ( 보안문자나 아이디같은거칠때 소문자로 쳐도 대문자로 나오는거같은거..)

실무에서 그렇게 엄청 많이 사용하진 않는데 가끔은 사용한다

 

 

 

사용방법은~

 

printf() 표현법 

 

System.out.printf(" 출력하고자 하는 형식", 출력하고자 하는값); 

ex) System.out.printf(" 내 나이는 %d 이고, 이름은 %s 입니다 "  , 변수명1 , 변수명2); 

     = >  System.out.printf(" 내 나이는 %d 이고, 이름은 %s 입니다 "  , age , name);

 

- 출력하고자 하는 형식 ->  출력하고자하는 값들을 제시한 형식에 맞춰서 출력을 그대로 해주는 문장

긍까 쌍따움표 안에 들어가는 문장들은 %를 붙인  키워드만 빼고 그대로 출력이 되는거임.

%가 붙은 키워드는 쌍따움표 뒤에 콤마 다음에 오는 변수들이 순서대로 대입이 된다...

 

- 출력하고자 하는 값 -> 값(변수혹은값)을 앞의 포맷형식에 들어갈 순서대로 쓰면 됨

(내가 쓰면서도 몬솔인지 모르겠다...난 이해가 되지만ㅎ)

 

ex)

예를 들자면

내 나이와 이름을 출력을 하고 싶다할때

int age = 20;   // 나이를 뜻하는 age라는 int형타입(정수형 용) 변수에 20을 담음

String name  = "김철수";   // 이름을 뜻하는 name이라는 String타입(문자열 용) 변수에 김철수를담음

 

System.out.prinf("내 나이는 %d  이며, 이름은 %s 입니다" , age, name);

age변수의 값이  %d에 들어가고, %s에는 name변수의 값이 대입? 입력? 들어가는거임.

순.서.대.로 들어간다를 거를 기억하면됨 

출력 -> 내 나이는 20 이고, 이름은 김철수 입니다

뒤에 변수들이 대입되서 그대로 출력되는거임.

아니 %d는 모고 %s는 모냐..왜 저럭케 쓰냐?

 

<printf()에서 쓰는 문자출력 포맷형식 키워드 >

%d : 정수
%c : 문자 (캐릭터)
%s : 문자열,문자 (String)
%f : 실수

 

정수값이 들어갈 위치에는 %d를 써주면되고

문자한개 값이 들어갈 위치에는 %c 를 써주고

문자열이 들어갈 자리에는 %s 를 써주고

소수점실수형값이 들어갈 자리에는 %f를 써주면 되는것임..

 

저 퍼센트 자리에 뒤에 쓴 변수값이 대입이 됨

즉 포맷에 쓴 키워드가 4개이면, 뒤에 오는 값들도 4개여야한다~

 

또한 printf() 는 print() 과 같이 개행,줄바꿈을 해주지 않기 때문에 

printf()를 쓴 다음에

System.out.println();  을 쓰거나

\n (역슬래시쓰고 n) 을 써줘야한다

\n 을 써주는 위치는 printf(" 어쩌구 저쩌구 \n", 어쩌구저쩌구 값 );

쌍따움표안의 출력문 가장 마지막에 써주어야한다

그럼 출력할때 딱 저 위치에서 줄바꿈을 하겠쥬?

System.out.prinf("내 나이는 %d  이며, 이름은 %s 입니다. \n" , age, name);

++ 보너스

/t  -> tap 공간만큼 띄어짐 

 

%를 같이 출력하고 싶을땐?

Systme.out.printf("%d %d%% ", num1, num2);

%%두번 써주면 % 출력됨

 

printf()의 오른쪽 왼쪽 정렬?

prinf()에서는 오른쪽정렬 왼쪽정렬을 하고 출력할 수 잇음 

%10d 

%-10d

%뒤의 숫자가 양수 일때는 오른쪽정렬하고 그 앞에 10개의 공백이 붙음

%뒤의 숫자가 음수 일떄는 값이 왼쪽에 나오고 그 뒤에 10개의 공백이 붙음 

 

%5d\n : 오른쪽 정렬 -> 오른쪽 끝에 붙어서 값이 출력됨(앞에는 5개의 공백이생김) 

System.out.printf("%5d",100);

->[     100]

%-5d\n : 왼쪽 정렬 -> 왼쪽 끝에 값이 붙어서 출력됨(뒤에는숫자만큼의공백)

System.out.printf("%-5d",100);

->[100    ]

먼..먼소린지 잘 모르겠다면 그냥 양수는 오른쪽정렬 음수는 왼쪽정렬이라고 생각하자

그....숫자에서 이하/초과 같은 숫자그래프?를 생각하면 외우기 쉬울 것 같다..

0을 기준으로 왼쪽으로 가면 마이너스 오른쪽으로가면 플러스 이지 않음 ?

 

printf()의 소숫점 표현

가장 큰 장점..소숫점 표현 방식이 넘나 편함

손쉽게 소숫점자릿수 표현을 정할 수 있음 

 

double dNum1 = 1.23456789;
double dNum2 = 4.5345;

값이 있음

이걸  printf()로 원하는 자릿수로 조절해서 출력하고싶다!

dNum1의 값을 소숫점 둘째자리까지만 표현하고싶고

dNum2의 값은 소숫점 셋쩨짜리까미난 보여주게하고싶다면

일단 실수형태의 값을 표현하는 키워드는 %f 임(위에 적혀있쥬?)

소숫점자릿수표현조절에는 .n (n은보여주고싶은 자릿수) 인데 퍼센트뒤에 끼워넣어주면됨

쩜~~!쩜 찍고 뒤에 원하는소숫점자릿수 숫자를 쓰는걸 잘 기억하자~!

System.out.printf(%.2 /n %.3f, dNum1, dNum2 );

출력 -> 1.23

             4.534

중간에 /n은 모다? 줄바꿈 ,개행을 해주는 키워드다~ 

 

대소문자로 출력해보기

-> 포맷형식을 대문자로 쓰면 대문자로 출력됨

그렇다고 소문자로 쓴다고 대문자값이 소문자로 출력되진않음

즉, 대문자만 변환이 가능하다~ 

String str = "Hello"

char ch = 'a'

System.out.printf("%C, %S", ch, str);

출력 ->  A, HELLO

 

 

 

 

정리

printf() 메소드는 문자와변수를 한번에 쫙 쓸수 있어서 편함. 

음수는 왼쪽정렬 양수는 오른쪽정렬

소숫점 표현 방식은 퍼센트뒤에 점찍고 숫자~ 

문자를 다 대문자로 쓰고 싶으면 포맷키워드를 대문자로 쓰기 

 

 

 

 

 

형변환 (Casting)

 

 

 

 

형변환이란?

값의 자료형을 바꿔(변환)준다는 의미

형변환에는 자동형변환/ 강제형변환이 있음

 

값 처리에는 규칙이 있잖음

1.  대입연산자를 기준으로 왼쪽과 오른쪽은 같은 자료형이여야한다...(당연함)

2. 같은 자료형 끼리만 연산이 가능하다.

값 + 값  을 하면 계산 결과도 당연히 같은 자료형임

 

즉~ 다른 자료형, 데이터 타입의 값을  다른 데이터타입 변수에 담고자 할때 형변환이 필수적이다!!!

 

ex) 

double d1 = 10.5

int i2 = 10

int sum = d1 + i2;   -> 에러난다는 소리임 

실수형타입 변수 d1 과 정수형 타입 (int)  i2를 서로 연산하려고 하니 에러남

또는 실수형타입(double) 변수를 정수형타입변수(int)에 대입하려고해도 에러남

 

 

즉~

형변환을 다른 타입의 데이터값을 다른 타입에 변수에 대입을하거나,

연산을 하면 에러가나서 형변환을 해주는것임

 

그럼 형변환을 어떻게 ~ 해야하냐

형변환에는 강제형변환 자동형변환이있음

 

자동형변환에대해서 먼저 설명함

 

각 데이터 타입에는 크기가 있음

int 4바이트

float 4바이트 

double 8바이트

long 8바이트 

 

자동형변환은 내가 안해줘도 컴퓨터,컴파일러가 알아서 자동으로 해주는건데

자동형변환이 되는 기준은 

 

값의 범위가 작은 자료형과 큰 자료형간의 연산시 자동으로 범위가작은자료형을 큰자료형에 변환시켜줌

그니까 컴퓨터가 작은데이터자료형을 것보다 큰데이터타입에 넣는다면 그건 알아서 해준다는거임

왜냐? 큰 사이즈에다가 작은걸 넣는건 쉬우니까

	int i1 = 12;
		double d1 = /*(double)*/i1; 
        //d1에다가 i1을 넣는데 원래는 안되는건데..(자료형과값은 일치해야함)
		//컴터가 자동으로 강제형변환해줌 /* */주석사이처럼

긍까 왼쪽항이랑 오른쪽항이랑 타입이 다른데 오류가 안난다?

자동형변환된거임. 즉 큰거에 작은거넣은거니까 ㄱㅊ다는소리

원래 안되는거라서 (double)을 쓰고 형변환을 해줘야하는데 안해줘도 오류가 안난다~이말 

 

 근데 특이 케이스도 잇음 

 long형 (8byte) -> float(4byte) 실수형  큰거에서 작은거로 바뀌는데도 오류가안남

//4. long 형 (8byte) -> float(4byte) 실수형  큰거에서 작은거로 바뀌는데도 안오류?
		//float형이 실수형이기 때문에 long형 보다 표현 가능한 수의 범위가 더 커서
		// 자동 형 변환이 된다.
		
		long l5 = 10000000L; // long형 데이터에는 L 붙음
		float f5 =/*(float)*/ l5; //자동으로 형변환해주어서 에러가 나지 않음

그리고 중요한거

char(2byte) <=> int(4byte) 둘이 왔다갔다 가능함. 지들끼리 왓다갓다 가능

왜? 영어 문자 한개에는 아스키코드라고 숫자값이 있음. 구글에 아스키코드 검색해보셈 

//5. char(2byte) <=> int(4byte) 둘이 와리가리가 됨. 지들끼리 왓다갓다 가능
	
	int num = 'A'; //정수형에 왜 문자가? 근데 왜 에러가안남? -> 자동형변환이됨
	System.out.println("num = " +num); // 65 나옴
		
	char ch = 55153;
	System.out.println("ch = " +ch);
    //각 문자들 마다 고유한 숫자가 지정되어 있기 때문에 쌍 방향으로 형변환이 가능하다
    //대문자 A -> 65 /소문자 a -> 97  이걸 아스키코드라고함

 

그럼 반대는? 작은거에다 큰 타입 넣으려고하면?

반대는 자동 형변환 안해줌. 에러가난다는거임

 

 

그럼 어케함?

강제 형변환을 해주는거임

강제형변환이랑 내가 내손으로 직접써야지 형변환이 되는거임

왜? 형변환을 해야지 못쓰는 데이터를 쓸 수 있으니까 

 

강제형변환을 하는 기준은? 

큰 크기의 자료형을 작은 크기의 자료형으로 바꾸는거임

컴파일러가 자동으로 못해주니까 내가 해야함

 

즉 강제형변환이란 뭐다?

큰 크기의 자료형타입의 값을 작은 크기의 자료형으로바꾸는거다~

 

어케할수있느냐?

자료형 변수명 = (바꿀 자료형) 값;

 

but, 데이터 손실이 일어날수있다는걸 기억해야함

실수값(dNum)을 정수형으로 강제 형 변환시 소숫점 아래 부분 버려짐
즉 -> 데이터 손실 발생할 수 있음 
int형으로 바뀌면서 뒤에 소수점을 잘라버림

(그래서 실수형의 소숫점을 떼버리고싶다? int형으로 형변환하면됨) 

 

 

ex)

double d1 = 4.6;

float f1 = d1;  -> 이러케 쓰면 에러남. 왜? 큰자료형(8바이트짜리)을 작은자료형(4바이트짜리) 에 넣으려고하니까.

float f1 = (float)d1; 로 쓰면 에러안남  (풀이 =>double형 d1값을 강제형변환해서 float형 f1변수에 넣음. 이제 d1의 타입은 float형이다) 

 

아니근데..애초에 float형으로 쓰면되지 왜 저렇게함? 안와닿을수있음. 그냥 예를 든거임.

다른 예시

<int형 값과 double형 값을 연산하고싶음>

int iNum = 10;
double dNum = 5.89; 


// int sum = iNum + dNum;     //iNum과 dNum을 더해서 int형 sum변수에 넣고싶음

->에러                                    //근데 이대로하면 에러남. 해결방법은 3가지가 있음

 

1. int sum = (int)(iNum + dNum);     //둘다 묶어서 강제 형변환

2. int sum = iNum + (int)dNum ;   //문제인놈만 강제형변환하기

여기서 기억해야할것!

실수형을 정수형으로 강제 형변환한거라서 값의 손실이 발생한다

10+5.89=15.89 원래는 이렇게 나와야하지만 값의 손실이 발생해 

정수형으로 15 값만 나온다~ 기억하삼  

3.double sum = iNum + dNum; //(연산결과는 double) (double형이 int형보다 크기가 크니까 자동형변환됨)

sum = 15.89 값 제대로 나옴. 왜?  int형이 double형으로  형변환된거니까~ 

int형이 double형으로 형변환되면 값이 어떠케 변함? 10 -> 10.0 되는거임 

 

긍까 값을 잃지않기 위해서는 어케해야하는지 머리를 잘 굴리도록... 잃어도 상관없다~하면 걍 강제형변환하고