C언어의 입출력
1. 출력함수
우리가 자주 사용하는 출력함수는 printf()이다. 이것의 장점은 크게 두 가지로 볼 수 있는데, 첫째는 인자 리스트를 구성할 때 길이에 제약이 없다는 것이고, 둘째는 출력의 제어가 간단한 변환형식(format)에 의해 이루어진다는 것이다. 즉, 사용자가 직접 필요한 변환을 하지 않아도 된다는 것이다. printf() 함수는 표준출력 파일 stdout에 문자 스트림을 전달한다. printf()의 매개변수 리스트는 제어문자열과 인자 리스트의 두 부분으로 이루어진다. 다음의 함수 호출
변환문자 |
의미 |
예 |
d |
십진 정수 |
45 |
o |
8진 정수 |
55 |
x |
16진 정수 |
2d |
u |
무부호 십진 정수 |
45 |
e |
지수부가 있는 부동 소숫점 |
-7.001100e+03 |
f |
지수부가 없는 부동 소숫점 |
-7001.100000 |
g |
e 혹은 f 중 짧은 것이 선택됨 |
-7001.1 |
c |
단일 문자 |
k |
s |
문자열 |
Pacific |
선언문과 치환문 | |||
char a; int i,j,k; c='w'; i=1; j=29; k=230551777; | |||
형식 |
식 |
인쇄 |
비고 |
/* 따옴표는 영역의 경계를 나타내기 */ /* 위한 것일 뿐 실제로 인쇄되지는 않음 */ | |||
%c |
c |
"w" |
생랷l의 영역폭은 1 |
$2c |
c |
" " |
우정렬 |
%-3c |
c |
"w " |
좌정렬 |
%d |
c |
"119" |
생략시의 영역폭 |
%5d |
c |
" 119" |
우정렬 |
%-5d |
c |
"119 " |
좌정렬 |
%d |
i |
"1" |
생략시의 영역폭 |
%d |
-j |
"-29" |
생략시의 영역폭 |
%10d |
i |
" 1" |
우정렬 |
%010d |
i |
"0000000001" |
0으로 채워짐 |
%010d |
-i |
"-0000000001" |
0으로 채워짐 |
%-12d |
j |
"29 " |
좌정렬 |
%12o |
j |
" 35" |
우정렬 |
%-12x |
j |
"1d " |
좌정렬 |
%d |
k |
“230551777” |
생략시의 영역폭 |
%5d |
k |
“230551777” |
9칸이 필요 |
%17d |
-k |
“ -230551777” |
우정렬 |
앞의 설명에서 정확도는 소숫점의 오른쪽에 인쇄될 자릿수를 의미하거나 문자열로부터 인쇄될 무자의 수를 의미한다. 보통 정확도는 컴퓨터 안에 부동소숫점수를 저장할 때의 정확도를 말한다. float 형의 변수는 유효 숫자로 대략 6자리만 저장한다. double 형 변수인 경우에는 유효숫자가 약 16자리이다. 다음의 표는 부동 소숫점 변환형식의 사용법을 예시하고 있다. 이 표는 32비트 기계를 기준으로 한 것이다.
선언문과 치환문 | |||
float x; double y,z; x=y=333.12345678901234567890; z=-555.11111111111111111111e-9; | |||
혁식 |
식 |
인쇄 |
비고 |
/* 따옴표는 실제로는 인쇄되지 않음 */ | |||
%f |
x |
"333.123444" |
생략시의 정확도 |
%.1f |
x |
"333.1" |
정확도 1 |
%.9f |
x |
"333.123443603" |
정확도 9 |
%20.3f |
x |
" 333.123" |
우정렬 |
%-20.3f |
x |
"333.123 " |
좌정렬 |
%.9f |
y |
"333.123456789" |
정확도 9 |
%.20f |
y |
"333.12345678901234000000" |
정확도 20 |
%20.3e |
y |
" 3.331e+02" |
우정렬 |
%-20.3e |
y |
"3.331e+02 " |
좌정렬 |
%f |
z |
"-0.000001" |
생략시의 정확도 |
%e |
z |
"-5.551111e-07" |
생략시의 정확도 |
%.1e |
z |
"-5.6e-07" |
정확도 1 |
%.3e |
z |
"-5.551e-07" |
정확도 3 |
%20.9e |
z |
" -5.5511111111e-07" |
우정렬 |
%-20.9e |
z |
"-5.5511111111e-07 " |
좌정렬 |
%2e |
z |
"-5.551111e-07" |
더 많은 공간 소요 |
다음의 표는 문자열 반환형식의 사용 예이다.
선언문과 초기값 | |||
char c='w''; static char s1[]="she sells sea shells"; static char s2[]="by the sea shore"; | |||
형식 |
식 |
인쇄 |
비고 |
/* 따옴표는 실제로는 인쇄되지 않음 */ | |||
%s |
c |
/* error */ |
char는 문자열이 아님 |
%s |
s1 |
"she sells sea shells" |
생략시의 영역폭 |
%7s |
s1 |
"she sells sea shells" |
더 많은 공간소요 |
%20s |
s2 |
" by the sea shore" |
우정렬 |
%-20s |
s2 |
"by the sea shore " |
좌정렬 |
%.5s |
s2 |
"by th" |
정확도 5 |
%.12s |
s2 |
"by the sea s" |
정확도 12 |
%15.12s |
s2 |
" by the sea s" |
정확도 12, 우정렬 |
%-15.12s |
s2 |
"by the sea s " |
정확도 12, 좌정렬 |
%3.12s |
s2 |
"by the sea s" |
더 많은 공간소요 |
% 문자의 인쇄에는 %% 변환형식을 사용한다. 물론 변환형식 %c에 대응하는 인자로 ‘%’를 주어도 마찬가지이다.
2. 입력함수 scanf()
scanf() 함수는 다음의 두 특성을 보유하고 있어 융통성이 매우 높다. 첫째는 인자의 길이에 제한이 없다는 것이고, 둘째는 변환에 필요한 세부사항을 사용자가 몰라도 간단한 변환형식에 의해 입력이 제어된다는 것이다. scanf()의 매개변수 리스트는 제어문자열과 인자 리스트의 두 부분으로 구성된다.
3. 관련함수 : fprintf(), sprint(), fscanf(), sscanf()
함수 printf()는 stdout 파일에 출력한다. 함수 fprintf()는 파일 포인터를 첫 인자로 가져야 한다. 나머지 인수들은 printf()의 것들과 같다. 특히 다음의 두 문은 동등하다.
fprintf(stdout, …);
printf(…);
stdout는 기정의된 파일 포인터형의 식별자로서 다음 절에서 다시 설명한다. 이와 비슷하게 sprintf(s, …)는 파일 stdout 대신에 문자열 s에 출력한다. 이 문자열은 출력을 저장하기에 충분한 크기이어야 한다.
함수 fscanf()는 scanf()에 대응하는 것으로서 입력화일에 대한 포인터를 첫 인자로 갖는다. sscanf()는 scanf()의 문자열 형태이다.
4. 파일
파일은 구조체에 대한 포인터에 의해 접근된다. 이 구조체는 표준 헤더파일 stdio.h에서 FILE로 정의되었다. 추상적으로는 파일을 순차적으로 처리되는 문자들의 스티림으로 생각할 수 있다. 시스템에서 제공하는 표준 하일로는 다음의 셋을 들 수 있다.
stdin 표준 입력 파일 : 키보드에 연결됨
stdout 표준 출력 파일 : 스크린에 연결
stderr 표준 오류 파일 : 스크린에 연결
라이브러리 함수 fopen()은 파일을 열기 위해서 사용된다. 이것은 FILE에 대한 포인터를 반환한다. 다음은 my_file이라는 이름의 파일을 여는 예이다.
#include <stdio.h>
main()
{
int c;
FILE *fp, *fopen();
fp=fopen("my_file","r");
파일이 개방된 후 파일에 대한 모든 참조에 파일 포인터가 사용된다. 표준 라이브러리에 마련되어 있는 중요한 함수를 살펴보면 다음과 같다. 이 외에 다른 함수도 있으며 시스템마다 다소 차이가 있을 수 있다. 상세한 사항은 사용시스템으 지침서를 참조하기 바란다.
1) fopen(파일명, 파일모드)
버퍼가 있는 파일을 열기 위해 필요한 작업을 수행하고 FILE에 대한 포인터를 반환한다. “파일명”을 접근할 수 없으면 NULL값이 반환된다. “파일명”과 파일모드“모두 문자열이다. ”파일모드“는 ”r“, ”w", “a" 가 있는데, 각각 일기(read), 쓰기(write), 추가(append)에 해당한다. 파일 모드가 ”r"이나, “w" 이면 파일 포인터는 파일의 처음에 위치하고, ”a“ 모드인 경우에는 파일의 끝에 위치한다. 파일 모드가 "w" 나 "a" 인 경우에 파일이 존재하지 않으면 파일이 새로 생성된다.
2) fclose(파일 포인터)
“파일 포인터”는 FILE에 대한 포인터이다. 함수 fclose는 버퍼를 비우는 데 필요한 일을 수행하고 지정된 파일에 대한 연결을 모두 제거한다. “파일 포인터”가 파일과 관계가 없는 경우에는 EOF값이 반환된다. 개방되는 파일의 수는 제한적이다. 필요한 파일만을 열어 놓는 것이 시스템의 효율을 높이는 데 도움이 된다.
3) getc(파일 포인터)
“파일 포인터”가 지시하는 파일에서 다음 문자를 추출한다. 문자의 값은 정수로 반환된다. 하일의 끝을 만나거나 오류가 있는 경우에는 EOF값을 반환한다.
4) getchar()
이것은 getc(stdin)과 동일하다
5) fgetc(파일 포인터)
getc()와 유사하게 동작한다.
6) ungetc(c, 파일포인터)
c를 “파일 포인터”가 지시하는 파일에 푸쉬한다. 푸쉬한 다음 번 읽기에는 바로 이 값이 반환된다. ungetc의 반환치는 c이다. 오류인 경우에는 EOF가 반환된다.
7) putc(c, 파일 포인터)
c의 값을 파일 포인터가 지시하는 출력파일에 출력한다. 출력한 문자의 int 값을 반환한다.
8) putchar(c)
putc(c,stdout)와 동일하다
9) fput(c,파일 포인터)
putc(c,파일 포인터)와 유사하다
10) gets(s)
s는 문자열 변수이다. gets(s) stdin으로부터 s로 문자열을 읽어들인다. 개행(newline)문자가 나올 때까지 입력문자들을 s에 저장한다. 개행문자는 널(null)문자로 바꿔어 s에 저장된다. 문자형 포인터인 s의 값이 반환된다.
11) fgets(s, n, 파일 포인터)
파일 포인터가 지시하는 파일로부터 n-1개 문자가 읽혀질 때까지 혹은 첫 번째 개행문자가 읽혀질 때까지 문자를 읽어 문자열 s에 저장한다. gets(s)와는 달리 개행문자 자체도 s에 저장되며 이것 다음에 널이 추가된다. 문자형 포인터인 s의 값이 반환된다.
12) puts(s)
문자열 s와 개행문자가 stdout에 출력된다.
13) fputs(s, 파일 포인터)
문자열 s를 파일 포인터가 지시하는 파일에 출력한다. puts()와는 달리 개행문자가 추가로 출력되지 않는다.
14) fseek(파일 포인터, offset, place)
다음 입력 또는 출력의 시작 위치르 지정한다. offset은 long형의 변수이고 place는 int형 변수이다. place는 0, 1, 2, 중 하나의 값을 가진다. 0은 파일의 시작, 1은 현재 위치, 2는 파일의 끝에 해당한다. 파일 포인터는 place로부터 offset 바이트만큼 이동된다. ungetc()의 효과가 fseek()에 의해 소멸된다.
15) rewind(파일 포인터)
fseek(파일 포인터, 0L, 0)와 동일하다.
16) ftell(파일 포인터)
파일 포인터가 지시하는 파일의 처음으로부터 현재 위치까지의 차감거리를 long으로 반환한다. 유닉스에서 차감거리는 바이트 단위로 측정된다.
17) exit(status)
프로그램 실행을 종료시킨다. 모든 버퍼는 바워지고 파일은 닫힌다. status의 값을 호출 프로세스에 반환한다. status는 int형의 식이다. 보통 프로그램이 적절하게 수행되었으면 0이, 그렇지 않으면 0이 아닌 값이 된다.
18) system(command)
command는 유닉스의 명령어에 해당한는 문자열이다. 예를 들면
system("cal 1990");
은 쉘(shell)이 유닉스 명령어 “cal 1990"을 수행하도록 한다. 이 결고 1990년의 달력이 파일 stdout에 인쇄된다.
이러한 표준 라이브러리 함수들을 사용하는 예들을 살펴보자, 첫째 프로그램은 파일에 존재하는 문자들을 대문자로 바꾸어 stdout에 출력하는 것이다.
/*** 파일의 모든 문자를 대문자로 바꾸기 ***/
#include <stdio.h>
main(argc, argv)
int argc;
char *argv[];
{
int c;
FILE *fp, fopen();
fp=fopen(argv[1], "r");
while((c=getc(fp) !=EOF)
if('a' <= c && c <= 'z')
putchar(c+'A'-'a');
else
putchar(c);
}
다음의 문장
fp=fopen("argv[1], "r");
은 사용자가 입력한 코맨드의 첫 인수로 지정된 파일을 읽기용으로 한다. 이제 포인터 변수 fp가 이 파일을 지시하는 것으로 생각하면 된다. 다음 줄
while((c=getc(fp)) != EOF )
로부터 시작되는 while 루프는 파일의 끝까지 문자를 c로 읽어 이를 대문자로 변환하여 출력한다. UNIX의 경우 이 프로그램이 컴파일된 후 프로그램의 수행은 다음과 같은 코맨드에 의한다.
a.out 파일
여기서 “파일”은 입력자료가 저장되어 있는 파일의 이름이다. 출력은 stdout에 기록된다.
다음의 프로그램은 입력파일을 한 행씩 더 뛰워 stdout과 출력파일에 기록한다. 즉, 입력파일에 개행문자마다 이를 하나 더 추가한다.
/*** 파일의 행을 이중으로 뛰우기 ***/
#include <stdio.h>
main(argc, argv)
int argc;
char *argv[];
{
int c;
FILE *myfile_in, *myfile_out,*fopen();
if(argc != 3) {
fprintf(stderr, "\nusage: %s infile outfile\n", *argv);
exit(1);
}
if((myfile_in = fopen(*++argv, "r")) == NULL) {
fprintf(stderr, "\nmain:cannot open %s\n", *argv);
exit(1)
}
if(myfile_out = fopen(*++argv, "w")) == NULL) {
fprintf(stderr, "\nmain:cannot open %s\n", *argv);
exit(1);
}
while((c = getc(myfile_in) != EOF) {
putc(c,myfile_out);
putc(c,stdout); /* echo to stdout also */
if(c == '\n') { /* double space */
putc(c, myfile_out);
putc(c, stdout);
}
}
fclose(myfile_in);
fclose(myfile_out);
}
이 프로그램의 목적 코드가 double_space라는 파일에 저장되어 있다고 하자. 다음의 코맨드
double_space 파일1
이 입력되면 argc는 2의 값이 되어 오류 메시지를 stderr로 보내고 시스템 함수 exit(1)를 호출하여 탈출하게 된다. exit()의 인자가 0이 아니므로 비정상적인 탈출이다. 다음의 코맨드
double_space 파일1, 파일2
가 입력되면 argc가 3이 되므로 제어는 밑의 if 문으로 이동된다. 다음의 식
(myfile_in = fopen(*++argv, "r")) == NULL
은 코맨드의 첫째 인자가 제시하는 파일을 열기 위해 사용되었다. *++argv 대신에 argv[1] 을 써도 된다. =가 ==보다 우선순위가 낮으므로 괄호는 반드시 있어야 한다. 만을 fopen()이 파일을 열지 못하면 NULL값이 반환되는데, 이 경우 stderr에 적절한 메시지를 출력한후 프로그램을 빠져 나간다
'* 컴퓨터 언어 (Computer Language) > C, C++' 카테고리의 다른 글
Microsoft Visual C++ 6.0 (165) | 2012.04.10 |
---|---|
C언어 (0) | 2012.03.22 |
수식과 연산자 (0) | 2011.12.22 |
02.C언어의 기초 (7) | 2011.11.19 |