Part 04 입출력과전처리 1
전처리기지시자 전처리기 (preprocessor) 컴파일러가프로그램을번역하기 ' 전 ' 에소스프로그램을 ' 처리 ' 하는프로그램 전처리기지시자 (preprocessor directive) 전처리기에게특정작업을지시하는가짜명령어 ( 의사명령어 ) # 으로시작함 중요한전처리기지시자 #include: 다른파일의내용을현재파일에포함시킴 #define: 특정단어를다른문자열로바꿈 #define 을처리합니다. #include 를처리합니다. 2
#include 파일포함지시자 헤더파일 (header file) 다른파일에포함시킬목적으로작성된파일 인클루드파일 (include file) 이라고도함 헤더파일 a.h 소스파일 Source.c 전처리기 전처리된소스파일 3
헤더파일종류 < 표준헤더파일 > 시스템의특별한위치에존재 " 일반헤더파일 " 소스파일과같은위치에서찾을수있는파일 4
변수값출력프로그램 표준헤더파일 // 전역변수 이부분을별도의헤더파일로만들자 실행결과 : X = 101 5
직접작성한헤더파일 #include 예 일반헤더파일이므로 definex.h 는 include.c 와같은디렉터리에있어야함 실행결과 : X = 101 6
#define 다른문자열로대치될단어 ( 매크로 ; macro) 를정의함 전처리기가매크로 MESSAGE 를 "Have a nice day!" 로바꾸어준다 ( 확장된다. 그래서 macro 라부른다 ). 실행결과 : Have a nice day! 7
#define 8
매크로함수 함수형태의매크로 실제로함수는아니지만함수와같이인수를받는형태로 macro 정의 실행결과 : Hello? Hello? 문자열리터럴을나란히두면컴파일러가알아서접합한다. ( 실행결과와같이 ) DUP("Hello? ") 에서 MESSAGE 는 "Hello? " 이므로 DUP("Hello? ") 는다음과같이바뀐다. "Hello? " "Hello? " 9
매크로정의가길때 백슬래시 (backslash) 는매크로정의가다음줄에계속됨을의미함 실행결과 : La La La La La La La La La La 10
요약 전처리기지시자 #include: 다른파일을포함시킴 #define: macro( 다른문자열로바뀔문구 ) 를정의함 macro 함수 macro 를이용하여함수형태로정의한것. 11
표준라이브러리 라이브러리 (library) 미리작성해둔프로그램 표준라이브러리 (standard library) 컴퓨터시스템이달라도같은기능 (same functionality) 을같은방식 (same interface) 으로사용할수있도록작성해둔라이브러리 표준입출력라이브러리 (standard input/output library) 표준입출력을다루는프로그램 ( 함수 ) 집합 표준입출력 (standard input/output): 거의모든컴퓨터가기본적으로수행하는입출력으로표준입력은통상키보드, 표준출력은통상모니터를나타냄 Computer1,2 의하드웨어 instruction set 들이다르다. 그러나, 표준 library 가있어같은 C 프로그램으로두컴퓨터를제어할수있다. 12
printf: 모니터로출력하는출력함수 % 로시작하는 printf (format string) 은데이터변환을지시함 정수 i 문자열 2 %d "2" 실수 f 문자열 3.14 %f "3.140000" 실행결과 : i = 2 f = 3.140000 c = 5 문자 c '5' %c 문자열 "5" 13
printf 포맷스트링 14
printf 출력폭지정 실행결과 : i = 2 f = 3.141593 c = 5 10 칸 format string 에서 % 다음에양의정수를기입하여출력폭지정 15
printf 정밀도지정 format string 에서 % 와 f 사이에 ( 출력폭이지정된경우, 출력폭다음에 ) ". 양수 " 형태로소수점이하자릿수지정 형식지정자 %6.4d %6.2f 3.1415926535897 12 자리 6 자리중에서 4 자리로출력 의미 반올림 실행결과 : pi = 3.141593 pi = 3.14 pi = 3.141592653590 0 1 2 3 전체폭은 6, 소수점이하자리 2, 우축정렬 1. 2 3 10 칸 16
scanf: 형식에맞는입력함수 주소연산자 & 를사용한점에주의! Scanf 의 format string 은문자열을데이터로변환함 문자열 정수 n 실행결과 : 27 entered n = 27 double of n = 54 triple of n = 81 "27" %d 27 17
scanf 의주소연산자 주소연산자 (address-of operator) &: 변수의주소를계산하는연산자 scanf("%d", &n); 표준입력에서변환한값을저장할장소를알아야하기때문에변수 n 의주소 (&n) 를두번째인수로사용함 & 변수 : 해당변수가할당된메모리주소 주소연산자를누락시키면실행시간오류 ( 변수에값을저장하려면변수의주소가필요 ) 18
프롬프트 (prompt) 프롬프트 (prompt) 입력할내용을설명해주는안내문 프롬프트가없으면 " 프로그램이죽은 " 것으로오해할수있음 앞슬라이드의프로그램은프롬프트가없다! 사실깜빡이는형태의빈 (null) 프롬프트가존재 19
scanf: 프롬프트를사용한버전 바로이것이 prompt! 입력할내용을설명해준다. 실행결과 : 정수 n 을입력해주세요. n = 27 입력한 n = 27 n 의두배 = 54 n 의세배 = 81 20
scanf: 입력할자료의자릿수 함수 scanf( ) 는 printf( ) 와같이입력할숫자의자릿수를지정할수도있다. 1 //****************************************** 2 // 3 // 입력할정수숫자의자릿수를지정하여입력. 4 //****************************************** 5 6 #include <stdio.h> 7 실행결과 : 8 int main() 정수 4자리입력후 Enter> 4253 9 { 입력한정수 : 4253 10 int num; 11 12 printf(" 정수 4자리입력후 Enter>"); 13 scanf("%4d", &num); 14 printf(" 입력한된정수 : %d\n", num); 15 } 21
scanf 포맷스트링 #include <stdio.h> int main() { double n = 0; } scanf("%lf", &n); printf("entered n = %f\n",n); return 0; TIP: double 타입으로입력받아야할경우에는 %f 대신 %lf 를사용한다. 22
getchar, putchar: 문자입출력함수 표준입력 (KB) 대문자로변환하는함수 toupper() a... getchar 문자 'A' 문자 'a' putchar...a 표준출력 (Monitor) 안내문구 (prompt) 실행결과 : 소문자를입력하세요. a a 의대문자는 A 입니다. putchar 가출력한문자들 23
gets, puts: 줄단위입출력함수 실행결과 : 사용자가입력한 \n // 배열 puts 가출력한 \n line 에는여기까지만저장됨 (\n 은제외됨 ) 24
gets, puts: 개행문자처리 개행문자처리 gets 는 \n 을떼고 \0(null 문자 ) 을붙여준다. puts 는 \n 을문자열출력끝에자동으로붙여준다. 이전예에서 gets 처리후 line[256] 상황 ( 배열은 Ch. 9&10 에서설명!) 25
입력버퍼실행결과 : 정수 n 과문자 c 를입력해주세요. 250 a n = 250 c = a 는어디로? printf( 정수 n 과문자 c 를입력해주세요.\n ); (scanf 는읽기표식이나타내는위치부터읽기시작함.) 수정 scanf(" %c", &c); c 에는공백문자가저장됨 26
입력버퍼 x y 도가능함 x y 만가능함 %c 와 %c 사이에공백이있으면, 입력시문자사이에공백이있어도되고없어도됨. 주의 : %c 와 %c 사이에공백이없으면, 입력시문자사이에공백이없어야함. 27
scanf 가공백을건너뛰는습성 포맷스트링 %c 의특이함 포맷스트링 %c 는공백을건너뛰지않음 ( 공백도문자로생각함!) 포맷스트링에공백이하나라도있으면여러공백문자에대응함 scanf("%d%c", ) scanf("%d %c", ) 포맷스트링 %c 를제외하고는모두공백을건너뜀 scanf("%d%d", ) scanf("%d %d", ) %s 로도공백을건너뛰어문자를읽을수있다 %s( 항상공백문자를건너뜀 ) 로입력을받되입력폭을 1로지정 char c; scanf("% 1s", &c); // scanf(" %c", &c); 와같음 %s로공백을건너뛰지않으려면? 불가능함. gets를사용하세요! 28
입력버퍼 printf( 정수 n 과문자 c 를입력해주세요.\n ); 수정수정 scanf("%d %c", &n,&c); scanf(" %c", &c); 또는 scanf("%d%1s", &n,&c); 29
입출력방향재지정 입력재지정 (input redirection) 표준입력대신파일로부터입력받음 program.exe < inputfile.txt 출력재지정 (output redirection) 표준출력대신파일로내용을저장 program.exe > outputfile.txt 합쳐서 program.exe < inputfile.txt > outputfile.txt program.exe > outputfile.txt < inputfile.txt < 를 로, > 를 로생각하면기억하기쉽다. 30
입출력방향재지정 예 : getsput.c를실행하여 getsput.exe 생성. input.txt 파일을아래와같이작성한다. This is a sample input. Win32 console 에서 getsput.exe < input.txt 을실행한다. 실행결과 : 한라인을입력해주세요. 입력하신라인은다음과같습니다. This is a sample input. 31
전처리기지시자복습 매크로정의가길경우에는행끝에 \ 를넣어다음줄에계속정의한다. 32
매크로함수의한계? 실행결과 : x = 250 x = 747 printf("x=%d\n",x); printf("x=%d\n",y); 이 x 를 y 로바꾸고싶지않습니까? 33
매크로인수연산 #x 매크로인수 x 를문자열로바꿈 실행결과 : x = 250 y = 747 # 하나만넣었을뿐인데 PR(y) printf(#y " = %d\n", y) printf("y" " = %d\n", y) printf("y = %d\n", y) 34
매크로인수연산 ## 매크로인수연산자 ## 매크로인수이름을붙여줌 문자열을붙이는것이아니라인수이름자체를붙임 ## 사용예 #define MERGE(x, y) x ## y... MERGE(x, 1) = 25; // x1 = 25; 로확장됨 MERGE(blue, berry) *= MERGE(x, 1); // blueberry *= x1; 으로확장됨... 35
Key Point 1 전처리기지시자 #include: 다른파일을포함시킴 #define: 매크로 ( 다른문자열로바뀔문구 ) 를정의함 표준입출력 키보드 (std. in) 와모니터 (std. out) 를추상화함 문자단위입출력을수행함 표준입출력라이브러리 형식에따른입출력 : printf(), scanf() 문자단위입출력 : getchar(), putchar() 줄단위입출력 : gets(), puts() 36
Key Point 2 버퍼 입출력속도차이를메워주기위한임시저장소 버퍼오버런 : 저장범위를넘어다른영역에침범하는현상 입출력방향재지정 표준입출력대신파일을사용하도록지정함 매크로인수활용 #x: 매크로인수 x 에해당하는문자열 x ## y: 매크로인수이름 x 와 y 를접합함 37
주의사항 Key Point 사용자로부터입력받을때에는안내문구 (prompt) 를사용하는것이좋음 scanf 의인수로는변수의주소를주어야함 int x; scanf("%d", x); scanf("%d", &x); // 잘못됨 // 올바름 scanf 로 double 형데이터를읽으려면 "%lf" 를이용함 scanf 포맷스트링 "%c" 는공백을건너뛰지않음 " %c" 를이용하거나 "%1s" 를이용함 38