C 프로그래밍
<문자의 입출력>
1. 개 요
시스템은 문자의 입력과 출력을 다루기 위해 getchar() 및 putchar()를 제공한다. 다음 프로그램에서 getchar()는 입력 스트림으로부터 하나의 문자를 얻고, 이것을 변수 c에 저장한다. putchar()는 화면 위에 하나의 문자를 출력하는데, 이 프로그램의 경우 putchar()가 두 번 사용되었기 때문에 같은 문자가 두 번 출력된다.
main()
{
char c;
while(l) {
c = getchar();
putchar(c);
putchar(c);
}
}
변수 c는 char형으로 선언되었는데, 이는 C 언어의 기본자료형 중 하나이다. 이러한 형의 변수는 문자 값을 가질 수 있다. 1은 0이 아니므로 식은 항상 참이다. 따라서 구조
while(l) {
․․․․․
}
는 무한루프이다. 이 프로그램을 멈추는 길은 인터럽트밖에 없는데, 전형적으로 control-c를 타자하는 것이다.
화면에 나타나는 것은 운영체제가 설정된 상태에 따라서 다르다. 위의 프로그램을 실행시켰을 경우 전형적으로 키보드로 문자를 타자했을 때 문자는 화면 위에 그대로 에코(echo)되어 나타난다. 그러나 운영체제는 입력을 처리하기 전에 문자의 라인이 캐리지 리턴이 되어 끝날 때까지 기다린다. 캐리지 리턴이 타자되었을 때 라인이 모든 문자가 컴퓨터로 즉시 전달된다. 프로그램을 실행시키고
abc <CR>
를 타자한다면 프로그램은 화면에 새로운 라인에
aabbcc
를 프린트한다. 이때 <CR>은 캐리지 리턴을 나타낸다.
캐리지 리턴은 newline 문자를 컴퓨터에 전달하는 작용을 한다. 따라서 두 개의 newline 문자도 프린트된다. 어떤 운영체제는 키보드에서 문자를 타자하자마자 처리된다. UNIX운영체제는 보통 한번에 한 라인을 처리한다. 그러나 다르게 설정할 수도 있다. UNIX명령어
stty cbreak
는 시스템이 각 문자가 타자되자마자 처리하도록 해준다. 이러한 명령어로 프로그램을 다시 한번 실행하였다고 가정해 보자. 만일 문자 p를 타자하였다면
ppp
가 화면에 나타난다. 첫 번째 p는 타자된 문자에 대한 에코이고, 다음 두 개는 프로그램에 의해 프린트된 것이다. 만일 pqr를 타자한다면
pppqqqrrr
가 화면에 나타난다. UNIX 명령어
stty-cbreak
는 운영체제를 리세트시켜서 한 번에 한 라인을 처리하게 된다.
2. 기호상수 EOF의 사용
C 언어에서 헤더파일을 사용하여 프로그램을 좀 더 간결하게 작성할 수 있는데 기호상수 EOF 의 값을 헤더파일에 설정하여 효과적으로 처리할 수 있다.
위의 프로그램을 보다 나은 방법으로 다시 작성하면 다음과 같다.
#include <stdio.h>
main()
{
int c;
while((c = getchar()) != EOF){
putchar(c);
putchar(c);
}
}
프로그램의 첫 번째 라인은 선행처리기에게 헤더파일 <stdio.h>를 포함시키도록 하는 명령어이다. stdio.h를 묶고 있는 꺾쇠 괄호는 시스템에게 파일을 표준 디렉토리 보통 include디렉토리에서 찾도록 해준다. 이 장소는 시스템에 종속적이다 보통
#include "/usr/include/stdio.h"
와 동일한 의미의 명령어이다. 다른 시스템에서는 파일을 다른 장소에 가질 수도 있다. 어떤 경우든 파일 stdio.h는 C 시스템에서 제공하는 표준 헤더파일이다. 이 파일은 전형적으로 어떤 표준입출력 구조를 이용하여 프로그램에 포함된다. 이 헤더파일의 한 라인은
#define EOF (-1)
로 된다.
식별자 EOF는 ‘end-of-file'의 연상자이다. 실제로 어떤 파일종료마크를 사용하는가는 시스템에 종속적이다. int값 -1을 종종 사용하지만 시스템에 따라 다른 값을 가질 수도 있다.
프로그램에서 변수 c는 char형보다 int형으로 선언되는 것에 주의한다. c는 int형이기 때문에 특별한 값인 EOF뿐만 아니라 모든 문자 값을 가질수 있다. char형은 아주 짧은 정수형으로, int는 char형의 모든 값과 혹은 그 이상을 나타낼 수 있는 일반적인 정수형으로 간주하는 것이 타당하다.
식
(c = getchar()) != EOF
는 두 부분으로 구성된다. 첫 번째 식
c = getchar()
는 키보드로부터 값을 얻어 변수 c에 치환시키고, 그 식 자체도 읽어들인 값을 당연히 취한다. 기호 !=는 ‘같지 않음’을 나타내는 연산자이다. 식 c = getchar()의 값이 EOF와 같지 않은 한 while루프의 몸체가 실행된다. 전형적으로 EOF의 값은 키보드에서 캐리지 리턴이 따르는 control-d를 타자함으로써 들어간다. 이것은 시스템에 종속된다. 식 c = getchar()을 묶는 괄호는 꼭 필요하다.
c = getchar() != EOF
를 타자하였다고 가정하자. 연산자의 우선 순위 때문에 이것은
c = (getchar() != EOF)
와 같은 의미로서 의미론적으로는 옳지만 우리가 바라는 바는 아니다.
또한 char의 상수는 ‘a', 'b', 'c' 등으로 쓴다.
she sells sea shells by the seashore
를 프린트하는 프로그램은 다음과 같이 작성할 수 있다.
main()
{
putchar('s');
putchar('h');
putchar('e');
putchar(' ');
. . . . . . . .
putchar('e');
putchar('\n');
}
3. 소문자와 대문자의 관계
문자는 대부분의 C 시스템에서 문자의 7비트 ASCII 표현에 대한 수치 값인 정수 값 표현을 갖는다. 예를 들어 상수 char 'a'는 값 97을 갖는다. 만일 문자를 작은 값의 정수로 간주한다면 문자에 의한 산술계산이 의미가 있다. 문자의 값이 소문자이든 대문자이든 간에 순서대로 나타나기 때문에 식 ‘a'+1은 값 ’b'를, 식 ‘b'+1은 값 ’c'를, 그리고 식 ‘Z' - 'A'는 값 25를 갖는다. 더구나 ’A' - 'a', 'B' - 'b', 'C' -'c'등은 모두 같은 값을 갖게 된다. 이러한 이유로 변수 c가 소문자의 값을 갖는다면 식 c + 'A' - 'a'에 대응되는 값은 대문자의 값을 갖는다. 이러한 개념을 구조화한 다음의 프로그램은 모든 소문자를 대문자로 변환하고 newline 문자를 2개로 하고 있다.
/*** 소문자의 대문자 전환과 이중공백라인 ***/
#include <stdio.h>
main()
{
int c;
while((c = getchar()) != EOF)
if('a' <= c && c <= 'z')
putchar(c + 'A' - 'a');
else if(c == '\n'); {
putchar('\n');
putchar('\n');
}
else
putchar(c);
}
프로그램 capitalize의 분석
while((c = getchar()) ! = EOF)
함수 getchar()는 문자를 받아 변수 c에 치환시킨다. c의 값이 EOF가 아닌 한 while 루프의 몸체는 실행된다.
if('a' <= c && c <= 'z')
putchar(c + 'A' - 'a');
연산자의 우선순위로 인하여 식
‘a' <= c && c <= 'z'과 (’a' <= c) && (c <= 'z')
은 같다. 기호 <= 는 ‘작거나 같음’을 나타내는 연산자이다. 식 ‘a' <= c는 값 ’a'가 c의 값보다 작거나 같은가 비교하며, 식 c <= 'z'는 c의 값이 값 ‘z'와 작거나 같은가 비교한다. 기호 &&는 ’논리 and'를 나타내는 연산자이다. 양쪽의 식이 모두 참일 때 식
‘a' <= c && c <= 'z'
은 참이며, 그렇지 않을 경우 거짓이다. 따라서 c가 소문자인 경우에만 식은 참이며, 식이 참일 때 문장
putchar(c + 'A' - 'a');
이 실행된다. 이것은 대응되는 대문자를 출력한다.
else if(c == '\n') {
putchar('\n');
putchar('\n');
}
기호 ==는 ‘같음’을 나타내는 연산자이다. 만약 c가 소문자가 아니면, 이것이 newline 문자와 같은지 검사한다. 만일 그렇다면 두 개의 newline 문자가 프린트된다.
else
putchar(c);
만약 c의 값이 소문자가 아니고, 이것이 newline 문자도 아니라면 값 c에 대응되는 문자가 프린트된다. else는 항상 if와 결합되어 사용된다.
'컴퓨터 > 언어,프로그래밍' 카테고리의 다른 글
[C언어] C언어 조건문 (0) | 2009.03.17 |
---|---|
[C언어] C언어 반복문' (0) | 2009.03.17 |
[C언어] C언어 함수 (0) | 2009.03.17 |
[C언어] C언어 배열,문자,포인터 (0) | 2009.03.17 |
[C언어] C언어 파일의 활용 (0) | 2009.03.17 |