CHAPTER 03. 입력과출력 프로그램에서입력과출력의필요성을살펴본다. 표준출력함수 printf, putchar, puts 의특징과사용법을익힌다. 표준입력함수 scanf, getchar, gets 의특징과사용법을익힌다. printf 와 scanf 함수에서사용되는변환명세를이해한다.
3.0 개요 p.76 출력 컴퓨터내부의내용을사람이인식할수있는형태로 모니터, 프린터, 스피커등에표시해주는과정 입력 사용자로부터마우스, 터치스크린, 조이스틱등 입력장치를통하여프로그램의변수에자료를전달하는과정 표준입력과표준출력 표준입력장치는키보드, 표준출력장치는모니터 프로그래머가직접표준입 / 출력장치를제어하는것이어려우므로라이브 러리함수를제공 : scanf, printf 함수등 2
3.1.1 변환명세를포함하지않은 printf 함수 p.78 printf 함수 변환명세를사용하여형식에맞춰출력해주는함수 단순히특정문자열을출력하기 예 ) 1 printf("hello! "); 2 printf("my name is 'C'. "); 3 printf("nice to meet you. "); 3
3.1.1 변환명세를포함하지않은 printf 함수 p.79 이스케이프문자 (escape sequence) 원래문자의의미를벗어나 (escape) 특별한의미를가진문자임을표시하기위해 \ ( 백슬래쉬, \ ) 로시작하는문자 p.79 [ 표 3-1] 예 : 출력결과를보기좋게하기위해행을바꾸고싶으면? 행을강제로바꾸는문자 \n 을사용 4
3.1.1 변환명세를포함하지않은 printf 함수 p.79 이스케이프문자를이용한출력예 1 printf("hello! "); 2 printf("my name is 'C'. \n"); 3 4 printf("you said \"Hello!\". \n\n"); 5 책수정 6 printf("yes!!\b "); 7 printf("i said \"Hello!\" \n\n"); 실행결과 Hello! My name is C. You said Hello!. Yes! I said Hello! 5
3.1.2 변환명세를포함한 printf 함수 p.80 변수에저장된값은어떻게출력할까? printf 함수의변환명세 (conversion specification) 를이용형식에맞게출력 6
3.1.2 변환명세를포함한 printf 함수 p.81 변환명세의종류 7
3.1.2 변환명세를포함한 printf 함수 p.82 예 ) 1 int age = 26; 2 double height = 175.7; 3 char grade = 'A'; 4 5 printf(" 나이 %d세\n", age); 6 printf(" 키 %lfcm의표준체중 : %lf\n", height, (height - 100) * 0.9); 7 printf(" 학점 : %c\n", grade); 8 printf(" 국적 : %s\n\n", " 대한민국 "); 9 printf("1억 : %e\n", 1.0e8); 10 11 printf("10진수 %d = 8진수 %o = 16진수 %X\n", age, age, age); 8
3.1.2 변환명세를포함한 printf 함수 p.82 p. 82 주의 자료형에맞지않은변환명세를사용하면이상한결과가출력된다. 9
3.1.3 변환명세의필드폭, 플래그, 정밀도 p.83 자료의크기가가변적일때세로로가지런히맞춰출력하기 필드폭을지정하여해결가능 필드폭을지정하면다음과같이세로로가지런히맞추어출력가능 10
3.1.3 변환명세의필드폭, 플래그, 정밀도 p.84 %d 변환명세에서의필드폭 출력에사용할전체칸 무조건부호출력양수도 + 출력 왼쪽정렬 11
3.1.3 변환명세의필드폭, 플래그, 정밀도 p.84 %d 변환명세사용예 책수정 2 12
3.1.3 변환명세의필드폭, 플래그, 정밀도 p.84 %d 변환명세사용예 : p.83 의예결과와비교 p. 85 주의 출력할자료의자리수가필드폭보다클경우 위의예에서 %3d 대신 %2d 를사용했다면결과는? 13
%lf 사용법 p.85 % 필드폭. 정밀도 lf 필드폭 : 전체출력칸 주의 소수점위의칸만의미하는것이아니라소수점위자리, 소수점, 소수점아래자리수모두를포함 p. 85 예 1 double avg = 83.768; 2 3 printf("avg=%7.3lf\n", avg); 4 printf("avg=%6.2lf\n", avg); 8 3. 7 6 8 정밀도 :. 아래자리칸 8 3. 7 7 ( 정밀도 +1) 번째자리에서반올림 14
%lf 사용법 p.85 %. 정밀도lf. 아래칸만강제지정 정밀도 : 소수점아래출력칸지정 소수점위 : 필요한만큼만칸확보 p. 85 예 1 double avg = 83.768; 2 5 printf("avg=%.2lf\n", avg); a v g = 8 3. 7 7 정밀도 :. 아래자리칸 ( 정밀도 +1) 번째자리에서반올림 15
%lf 사용법 p.85 % 필드폭 lf 필드폭 : 전체출력칸 소수점아래 : 무조건 6 칸, 필드폭나머지왼쪽칸에. 위값과. 을출력 p. 85 예 1 double avg = 83.768; 2 6 printf("avg=%10lf\n", avg); 필드폭 : 전체출력칸 8 3. 7 6 8 0 0 0 무조건 6 자리 16
%lf 사용법 p.85 % 필드폭.lf 필드폭 : 전체출력칸. 아래첫자리에서반올림하여소수점위의값만출력 % 전체폭.0lf 와결과가같음 필드폭 : 전체출력칸 p. 85 예 1 double avg = 83.768; 2 7 printf("avg=%5.lf\n", avg); 8 4. 아래에서반올림한결과 p. 86 주의 100 점만점의평균점수여러개를출력할경우 %5.1lf 가아닌 %3.1lf 로지정하면평균점수들의소수점위치를나란히맞출수없다. 왜? 17
3-1 실수형의출력예 p.86 1 #include <stdio.h> 2 3 int main() 4 { 5 double d = 12.345e-50; 6 7 printf("d = %.5lf\n", d); 8 printf("d = %.50lf\n", d); 9 10 printf("d = %.5e\n", d); 11 printf("d = %.5E\n", d); 12 13 return 0; 14 } 18
3.1.3 변환명세의필드폭, 플래그, 정밀도 p.87 %c 변환명세사용법 예 ) % 필드폭 c %- 필드폭 c 왼쪽정렬 1 char grade = 'A'; 2 3 printf("i've got an %c.\n", grade); 4 printf("i've got an %3c.\n", grade); 5 printf("i've got an %-3c.\n", grade); 19
3.1.3 변환명세의필드폭, 플래그, 정밀도 p.87 %s 변환명세사용법 자세한문자열처리는 7장에서소개함 % 필드폭s %- 필드폭 s 왼쪽정렬 20
3.2 문자와문자열전용출력함수 p.88 printf는변환명세때문에번거로워!!! 보다간결하고처리속도도빠른건없을까? 문자전용출력함수 putchar 문자열전용출력함수 puts putchar 함수 형식 문자 1 개출력 예 ) putchar( 문자 ); putchar( 문자형변수 ); 1 char grade = 'A'; 2 3 putchar(grade); 4 putchar('+'); 5 putchar('\n'); 21
3.2.2 문자형자료와정수형자료간의상호변환관계 p.89 문자의 ASCII 코드 (p.50, p.51 참고 ) 문자마다정해진 2진수의 ASCII 코드가부여됨 2진수코드값은 10진수정수로변환가능문자 정수 : 상호변환가능 char ch = 'A' + 2; A 의 ASCII 코드값 65 + 2 = 67 67은 C 의 ASCII 코드값 ch에는 C 가저장 22
3.2.3 문자열전용출력함수 puts p.90 puts 함수 문자열출력후무조건개행문자 ( \n ) 출력 즉줄이바뀜 형식 예 puts( 문자열 ); puts( 문자열변수 ); 1 puts("hello!"); 2 puts("my name is Hong GilDong."); 3 puts("nice to meet you."); 23
3.3 프로그래밍실습 p.90 문제 주어진자료 : 학번 2013901, 국어 89, 세계사 100, 수학 95 결과 : 세과목의평균 (94.67) 출력형식 : 세점수를세로로나란히맞추기, 평균은. 아래두자리까지출력 학번단순히 int형정수로간주하여 int형변수에저장 각과목의점수최대점수가 100이므로 %3d 또는 %4d와같이필드폭을 3 이상으로지정 평균점수소수점아래두자리까지출력되도록 %6.2lf로지정 ( 전체폭은 6보다크게 ) 과목명문자열한글한자는출력시두칸을차지 가장긴 세계사 를고려해 %-6s 사용 24
3-2 세과목의평균을구해출력하기 (ch3-2.cpp) p.91 3 int main() 4 { 5 // 변수선언 6 int std_no, kor, world, math; 7 double avg; 8 9 // 대입문을사용해변수값저장하기 10 std_no = 2013901; 11 kor = 89; 12 world = 100; 13 math = 95; 14 15 // 세과목의평균구하기 16 avg = (kor + world + math) / 3.0; 17 18 // 결과를형식에맞춰보기좋게출력하기 19 printf("%-6s: %d \n", " 학번 ", std_no); 20 printf("===============\n"); 21 printf("%-6s: %4d( 점 ) \n", " 국어 ", kor); 22 printf("%-6s: %4d( 점 ) \n", " 세계사 ", world); 23 printf("%-6s: %4d( 점 ) \n", " 수학 ", math); 24 printf("===============\n"); 25 printf("%-6s: %7.2lf \n", " 평균 ", avg); 정수 / 정수결과는정수이므로 3 을실수로사용 25
3.4 입력함수 scanf p.92 1 2 한개의자료만입력하기 여러개의자료를한꺼번에입력하기 26
3.4 입력함수 scanf p.92 프로그램에서지정할수없는값은사용자가직접입력하도록한다. 예 ) 사용자의나이, 키, 이름, 학교명등 scanf, getchar, gets 등의함수를사용 scanf 를많이사용 : printf 에서사용된변환명세를사용 27
3.4.1 한개의자료만입력하기 p.93 scanf 함수를사용한입력 변수명 = 키보드입력값 ; 효과 & 변수명 : 입력값을저장할변수의기억장소주소 변환명세 : 입력값종류별로정해져있다. [ 표 3-4] %d: 정수, %lf: 실수, %c: 문자, %s: 문자열 scanf 함수의실행과정 1 2 3 실행창에커서가깜박이며사용자입력을기다림사용자가키보드로자료를입력하고 [ 엔터 ] 키를누름입력된값이변수에저장 28
3.4 입력함수 scanf p.93 29
3.4.1 한개의자료만입력하기 p.94 예 1 int age; 2 3 printf(" 나이는? "); 4 scanf("%d", &age); 5 6 printf(" 입력한나이 : %d세\n", age); 30
3.4.1 한개의자료만입력하기 p.94 p. 94 주의 scanf 함수 변환명세 안에변환명세가아닌다른문자는사용못함 scanf( 나이는? %d, &age); [X] printf( 나이는? ); scanf( %d, &age); [] 변환명세 에서 로닫기전에공백문자 (white character) 나이스케이프문 자를넣지않기 scanf( %d\n, &age), scanf( %d, &age) [X] 뒤의입력문내용에따라키보드입력을한번더해야하는현상이생길수도있다. 자료형에맞는변환지시자 (d, lf, c, s 등 ) 를정확히사용 변환명세에서필드폭은사용하지않는것이더편리 ( 꼭필요할때만사용 ) 31
프로그램 3-3 학생의개인정보를입력받아출력하기 p.95 5 int age; 6 char gender; 7 double height; 8 9 // 자료입력받기 10 printf(" 성별은? ( 남자라면 M 여자라면 F) "); 11 scanf("%c", &gender); 12 printf(" 나이는? "); 13 scanf("%d", &age); 14 printf(" 키는? "); 15 scanf("%lf", &height); 16 17 // 결과출력하기 18 printf("\n============\n"); 19 printf(" 성별 : %c\n", gender); 20 printf(" 나이 : %d 세 \n", age); 21 printf(" 키 : %.1lfcm\n", height); 32
3.4.1 한개의자료만입력하기 p.97 %s 를사용한문자열입력 문자열은배열을이용하여저장 자세한것은 7 장배열에서다룸 33
3.4.2 여러개의자료를한꺼번에입력하기 p.98 scanf 함수에서여러변수의값을입력하기 키보드입력방법 - 자료간구분은공백문자 ( 스페이스바, 탭키, 엔터키입력문자 ) 를사용 - 입력의끝은 [Enter] 키사용 - 예 ) 입력방법 1: 10 20 입력방법 2: 10[Tab] 20 입력방법 3: 10 20 %d %d 도가능 %d%d\n, %d%d 처럼 로닫기전에 \n 이나빈칸을넣지않아야함 %d, %d 입력시반드시, 를눌러야함입력방법 : 10, 20 34
3.4.2 여러개의자료를한꺼번에입력하기 p.99 p.99 주의 확인하기 35
3.5 문자와문자열전용입력함수 1 문자전용입력함수 getchar 2 문자입력과버퍼비우기 fflush(stdin) 3 문자의연산 4 문자열전용입력함수 gets 36
3.5.1 문자전용입력함수 getchar p.100 getchar 문자만입력 변환명세가필요없고인수도사용하지않음 예 ) getchar 함수실행시키보드에서누른문자가 getchar() 의결과값이됨 이결과값 ( 문자 1개 ) 이변수에대입 ( 저장 ) 됨 1 char grade; 2 3 printf("c 언어의학점은? "); 4 grade = getchar(); 5 printf("c 언어의학점은 %c입니다.\n", grade); 37
3.5.2 문자입력과버퍼비우기 fflush(stdin) p.100 숫자를먼저입력받은후문자를입력받았을때발생하는문제 문자자료를입력받을때는공백문자 ( 빈칸, 탭키, 엔터키 ) 도입력문자로 사용되므로문제가발생할수있음 [ 프로그램 3-3] 순서를바꾸면어떤문제가발생할까? [ 프로그램 3-5] 38
[ 프로그램 3-5] 에서의문제점 p.101 실행결과 나이는? 21 키는? 165.7 성별은? ( 남자라면 M 여자라면 F) ============= 성별 : 나이 : 21 세 키 : 165.7cm 15 행이입력문이지만사용자의입력을받지않고곧바로 18 행이실행된다. 19 행에서 gender 가출력될곳에개행문자가출력되어있다. ( 왜?)
3.5.2 문자입력과버퍼비우기 fflush(stdin) p.102 숫자입력후문자입력시발생하는문제는버퍼를이용하는입력때문 입출력버퍼 (buffer) 입출력은컴퓨터의다른장치보다속도가아주느림 이를보완하기위해운영체제는입출력이수행될때입출력자료를임시로 버퍼에모아두었다가한꺼번에전달함 버퍼를이용한입력처리과정 사용자가입력한자료는변수에바로저장되지않고일단버퍼에저장 엔터키가입력되면버퍼에있는내용을꺼내서실제로변수에자료를저장 하며 버퍼의내용을변수에저장할때버퍼에저장된내용이남아있는한 다음입력문실행시키보드에서자료가입력되기를기다리는게아니라버 퍼에있는내용을이용하여곧바로변수에저장함 버퍼에이전에키보드에서입력된자료가있다면새로운입력을기다리지않고버퍼의내용으로입력을완료 40
3.5.2 문자입력과버퍼비우기 fflush(stdin) p.102 12 printf(" 키는? "); 13 scanf("%lf", &height); 14 printf(" 성별은? ( 남자라면 M 여자라면 F) "); 15 gender = getchar(); // scanf("%c", &gender); 16 17 // 결과출력하기 18 printf("\n============\n"); 19 printf(" 성별 : %c\n", gender); 20 printf(" 나이 : %d세\n", age); 21 printf(" 키 : %.1lfcm\n", height); 사용자가 165.7 입력후엔터키를누르면버퍼에저장된내용을꺼내서 height 에저장하여입력을완료한다. 15 행입력문처리시버퍼에남은자료 ( 엔터키 ) 가있으므로입력을기다리지않고이문자를 gender 에저장하여입력을완료한다. 사용자에게서새로 gender 를입력받지않고이전의입력자료를사용함으로써문제가발생 41
3.5.2 문자입력과버퍼비우기 fflush(stdin) p.103 문제해결방안 1 15 행앞에 getchar(); 문장을추가 버퍼에남은엔터키를읽어버퍼가비게되면새로운사용자입력이버퍼에저장될때까지기다리게된다. 13행실행후버퍼에남아있는엔터키를입력받음으로써버퍼가비게된다. 13 scanf("%lf", &height); 14 printf(" 성별은? ( 남자라면 M 여자라면 F) "); getchar(); 15 gender = getchar(); // scanf("%c", &gender); 상황에따라버퍼에엔터키외다른문자가여러개있는경우에는해결할수없으므로근본해결방안이아님 42
3.5.2 문자입력과버퍼비우기 fflush(stdin) p.103 문제해결방안 2 사용자에게서새로운입력을받도록강제로버퍼를비움 버퍼에서읽어올자료가없으므로사용자가새자료를입력할때까지기다리게됨 언제나사용자에게서새로입력을받게된다. 표준입력장치용버퍼의내용을모두제거 이함수호출문다음에나오는입력문은항상키보드에서새로운자료를입력받게됨 43
3.5.2 문자입력과버퍼비우기 fflush(stdin) 해결결과 : [ 프로그램 3-6] p.104 44
3.5.4 문자열전용입력함수 gets p.106 scanf 의문자열입력시문제점 공백, 탭등이포함된문자열을한꺼번에입력받을수없음 Hong GilDong 을입력하면 Hong 만입력됨 행단위입력함수 gets 를사용하여해결 행단위입력함수 gets 사용 45
3.5.4 문자열전용입력함수 gets p.106 행단위입력함수 gets사용 1 char address[30]; 2 3 printf(" 주소는? "); 4 gets(address); 5 printf(" 입력한주소 : %s", address); 46
3.6 프로그래밍실습 p.106 문제 ) 학생의이름, 학년, 평점을입력후평점을 100 점만점의점수로환산하여 출력하기 분석 빈칸을포함한이름입력 : scanf 대신 gets 함수이용 학생의이름 : 문자열 char 형 1 차원배열 한글 1 자는 2 바이트차지 넉넉하게배열의크기를 10 으로사용 학점은 A+ 를 4.5 만점으로환산 평점 4.5 가 100 점이므로입력된평점 GPA 를점수 score 로의환산은 4.5 : 100 점 = GPA : score 로구함 47
3-8 학생의평점을점수로환산하여출력하기 p.107 48