1. 데이터 출력 : printf()
C에서는 입출력과 같은 하드웨어에 의존하는 표준 라이브러리 함수를 각 컴파일러 제작자가 제공하도록 되어있다. 따라서 그 모양은 각 제작자마다 다소 다르게 되어 있다. 그러나, 기본적인 입출력 함수에 관해서는 거의 공통이다. 본 내용은 입출력을 행하는 scanf 및 printf 함수와 한 개 문자의 입출력을 행하는 getchar 및 putchar 함수에 관해서 공부하기로 한다. 라이브러리 함수 중에서 printf를 사용하면 문자열이나 수치 데이터를 표준 출력 장치, 즉 컴퓨터 화면으로 출력할 수 있다
(1) printf( )을 사용해서 화면으로 데이터를 출력
[hello]라는 문자열을 화면으로 출력하려면,
printf("hello");
라 한다. [hello]라 표시한 후 행을 바꾸려면,
printf("hello\n");
라 한다. 여기서 \n은 행을 바꾸는 확장 문자이다. 변수 a에 들어있는 수치를 출력하려면
printf("%d", a)
라 한다. 여기서 "%d"를 형식 제어 문자열이라 하고 변수 a의 값을 10진수로 출력하라는 의미이다(d는 decimal의 약자이다). 여기서 문자열과 수치를 혼합해서 출력하려면 다음과 같이 하면 된다.
printf("adding = %d", a);
일반적으로 이중 인용부호(" ")로 싸여진 문자열을 형식 제어문 문자열이라 하고 그 뒤에 콤마 (,)로 구별해서 정돈한 것을 인수(parameter, argument)라 한다. 형식 제어 문자열의 문자는 그대로 화면에 출력되지만 %뒤에 이어지는 문자는 그것에 대응하는 인수의 내용을 표시할 때 형식 제어문에 사용되고(즉, 출력 형식을 지정한다) 그 자체는 화면에 표시되지 않는다. 예를 들면 위의 식에서 a의 값이 100이라고 하면 출력 결과는 다음과 같다.
adding = 100
예제 1. 정수 데이터 a와 b를 더하고 결과를 출력하라. 아래의 설명문이 이해가 되지 않으면 각 부분을 의도적으로 생략한 후 실행시켜 보기 바란다.
●프로그램
#include <stdio.h>
main()
{
int a, b, c; /* 변수 a, b, c를 정수형으로 선언, 반드시 선언해야 한다. */
a = 50;
b = 20;
c = a + b; /* 변수 a에 50, b에 20을 대입하고 a+b의 결과를 c에 대입 */
printf("Addition = % d\n", c); /*변수 c의 값을 10진수로 출력하고 행 바꿈*/
}
●결과
Addition = 70
예제 2. C라는 문자를 출력하라.
●프로그램
#include <stdio.h>
main()
{
printf(" CCCCCC\n");
printf(" CCCCCCCCCC\n");
printf(" CCC CC\n");
printf(" CCC CC\n");
printf("CCC\n");
printf("CCC\n");
printf("CCC\n");
printf("CCC\n");
printf(" CCC CC\n");
printf(" CCC CC\n");
printf(" CCCCCCCCCC\n");
printf(" CCCCCC\n");
printf("\n\n");
printf("C와 함께 유익하고 즐거운 Computer의 세계로...\n");
}
●결과
CCCCCC
CCCCCCCCCC
CCC CC;
CCC CC
CCC
CCC
CCC
CCC
CCC CC
CCC CC
CCCCCCCCCC
CCCCCC
C와 함께 유익하고 즐거운 Computer의 세계로...
(2) 출력 위치의 지정
printf() 로 데이터를 출력할 때, 데이터의 출력 형태(자리수)를 지정할 수 있다. 예를 들어
printf("%4d", a);
라 하면, 변수 a의 내용이 4자리의 10진수로 출력된다. 만약 그 값이 4자리보다 작으면 오른쪽에서부터 시작해서 빈자리는 공백으로 보충된다. 반대로 그 값이 4자리보다 많으면 4자리 지정은 무시되고 그 크기에 해당되는 폭만큼만 출력된다. %와 d사이에 출력 위치를 나타내는 숫자가 표시된다.
응용문제 1: 정수 데이터 a와 b의 가, 감, 승, 제의 결과를 8자리의 폭으로 출력하는 프로그램을 작성하라.
(3) 실수 데이터의 출력
10진 정수 데이터의 출력에서 형식 제어 문자 d(decimal)를 사용하였지만, 실수 데이터의 출력에서는 형식 제어 문자 f(double, float)를 사용한다. 예를 들어
printf("%f", a);
라고 하면, 변수 a의 값이 소수점을 가진 실수형으로 출력된다. 이것으로 출력 형태(자리수)를 지정하려면,
printf("5.2f", a);
라 한다. 이것은 전체 5자리(소수점을 포함해서), 소수점 이하 2자리의 폭으로 출력하게 된다. printf() 의 인수에 float 형 데이터가 있어도 그것은 double형으로 변환되기 때문에 printf()의 실수형의 형식 제어 문자는 float이나 double에 관계없이 「f」의 한 종류만 사용된다.
응용문제 2: 실수 데이터 a, b 의 가, 감, 승, 제의 결과를 전체는 8자리, 소수 이하 2자리의 폭으로 지정해서 출력하는 프로그램을 작성하라.
(4) 정수값의 16진수 표시와 문자 표시
정수값을 16진수 및 그의 ASCII 코드에 대응하는 문자로 출력하는 방법을 생각해 보자. 10진수인 정수값 104는 16진수 0x68로 표시할 수 있고(숫자 0 다음에 영문자 x를 붙여쓰고 그다음에 16진수 68을 표시한다), 이것을 ASCII 코드 문자 "h"로 대응시킬 수 있다 (ASCII 코드를 다시 말하면, 우리 눈에 보이는 영문자 h는 미국 표준화 단체에서 표준으로 정의한 바에 따라 컴퓨터 내부에 10진수 104(정확하게는 2진수로 저장)로 저장되는 방식으로 각 문자에 해당하는 코드를 ASCII 코드라고 한다). 예를 들어
printf("%x %c", 104, 104);
라 하면 화면에는
68 h
라고 표시된다. 형식 제어 문자 x는 정수값을 16진수로 표시하고 형식 제어문자 c는 정수값을 그에 대응하는 ASCII코드 문자로 표시한다. 그 의미를 다시 말하면, 10진수 104를 16진수로 출력하고, ASCII 코드 104에 해당하는 문자를 출력하라는 것이다. 물론 x는 d와 같이 %4x의 형식으로 출력폭을 지정한다.
(5) printf()의 형식
printf() 의 형식의 일반형은 다음과 같다.
printf(format[, arg1. arg2…])
위의 형식에서 [ ]으로 싸인 항목은 생략할 수도 있다.
형식 제어 문자열의 일반적인 형식은 다음과 같다. [ ]의 항목은 생략 가능하다는 것을 표시한다.
그 밖의 다양한 형식을 아래에 정리하였다.
%[-][[0]w][.n][1]변환 문자
%…형식 제어 문자열의 시작
-…폭의 왼쪽에서부터 출력 printf("%-7d", 123);
[0]w…w는 field의 폭을 나타내는 정수값 printf("10d", 123)
w 앞에 0을 위치시키면 공백을 전달하는 대신에 0을 전달한다.
.n…실수의 소수점 이하의 자릿수 printf("%10.5f", 3.14);
또는 문자열의 폭 printf("%10.3s", "ABCDE");
l… long int 형의 지정. d, u, o, x 변환 문자의 지정자로 사용 printf("%ld", 123);
변환문자
d…부호가 있는 10진수
u…부호가 없는 10진수
o…부호가 없는 8진수
x…부호가 없는 16진수 (a∼f의 문자를 소문자로 출력)
X…부호가 없는 16진수 (A∼F의 문자를 대문자로 출력)
c…1문자 출력
s…문자열
e…지수 형식 (e의 문자를 소문자로 출력) 예) 1.23000e+00
E…지수 형식 (E의 문자를 대문자로 출력)
f…부동 소수점 숫자
예를 보기로 하자. printf 문 다음은 출력 형태이다.
b=97
printf("%d %c %4x %04x\n",b, b, b, b);
97 a 61 0061
d=1234.5
printf("%8.2f %10.2e\n", d, d) ;
1234.50 1.23e+003
name = " candy "
year = 20 ;
printf ("% -10s% -5d\n", name, year); printf("%1x\n ", -1L);
candy 20 ffffffff
예제 프로그램 3: printf 함수를 사용한 program
#include <stdio.h>
#define PI 3.14159
main() /* Example of printf 함수 */
{
char aChar = 'A';
short i = 0x41;
float pi = 3.14;
printf("aChar = %c, %d, %x\n", aChar, aChar, aChar);
printf("i = %d, %u, %o, %x, %c\n", i, i, i, i, i);
printf("pi = %f, %e\n", pi, pi);
printf("The value of PI is %f or %e\n", PI, PI);
}
●결과
aChar = A, 65, 41
i = 65, 65, 101, 41, A
pi = 3.140000, 3.14000e+00
The value of PI is 3.141590 or 3.14159e+00
아래의 확인문제를 반드시 실행시켜 앞의 설명을 이해하기 바란다.
확인문제 1
/* 정수형 데이타의 출력 형식을 지정한 출력의 예 */
#include <stdio.h>
#define INT_DATA_1 1234
#define INT_DATA_2 -1234
main()
{
int a = 10;
printf("(123456789012345)\n");
printf("(%d)\n", INT_DATA_1);
printf("(%2d)\n", INT_DATA_1);
printf("(%10d)\n", INT_DATA_1);
printf("(%-10d)\n", INT_DATA_1);
printf("(% 10d)\n", INT_DATA_1);
printf("(% 10d)\n", INT_DATA_2);
printf("(% +10d)\n",INT_DATA_1);
printf("(%+10d)\n", INT_DATA_2);
printf("(%10o)\n", INT_DATA_1);
printf("(%#10o)\n", INT_DATA_1);
printf("(%10X)\n", INT_DATA_1);
printf("(%#10x)\n", INT_DATA_1);
printf("(%010d)\n", INT_DATA_1);
printf("(%-010d)\n", INT_DATA_1);
printf("(%10.7d)\n", INT_DATA_1);
printf("(%-010.7d)\n", INT_DATA_1);
printf("(%*.*d)\n", a, 7, INT_DATA_1);
printf("(%10.*d)\n", 2, INT_DATA_1);
}
확인문제 2
/* 실수형 데이타의 출력 형식을 지정한 출력의 예 */
#include <stdio.h>
#define FLOAT_DATA 1234.5678
main()
{
printf("(12345678901234567)\n");
printf("(%f)\n", FLOAT_DATA);
printf("(%.f)\n", FLOAT_DATA);
printf("(%.4f)\n", FLOAT_DATA);
printf("(%2.2f)\n", FLOAT_DATA);
printf("(%e)\n", FLOAT_DATA);
printf("(%5.3e)\n", FLOAT_DATA);
printf("(%15.9E)\n", FLOAT_DATA);
printf("(%15.4E)\n", FLOAT_DATA);
printf("(%4.2f)\n", FLOAT_DATA);
printf("(%3.1f)\n", 123.123);
printf("(%10.3f)\n", FLOAT_DATA);
printf("(%10.3e)\n", FLOAT_DATA);
printf("(%+4.2f)\n", FLOAT_DATA);
printf("(%010.2f)\n", FLOAT_DATA);
printf("(%G)\n", 0.00012);
printf("(%g)\n", 0.0000000012);
printf("(%g)\n", 100.0000);
printf("(%#10.2f)\n", 100.);
printf("(%+#-10.2f)\n", 100.);
printf("(%*.*f)\n", 10, 3, 12.345);
printf("(%10.*e)\n", 3, FLOAT_DATA);
printf("(%+*.2f)\n", 10, FLOAT_DATA);
}
참고:
#의 의미: 수치를 8진수(%o) 또는 16진수(%x 또는 %X) 형식으로 출력할 때 8진수는 접두사 0을, 16진수는 접두사 0x 또는 0X를 수치 앞에 자동으로 붙여줍니다. 또 모든 부동형에 #를 사용하면 소수점 이하의 값이 없을 지라도 소수점을 사용하여 출력하고, %g 또는 %G 출력에서 소수점 이하가 0 (예: 4.0)이면 정수로 출력하게 되는데, #를 사용하면 이러한 정수 출력을 소수점이 있도록 출력합니다.
맨 뒷부분에 있는 printf 3문장
printf("(%*.*f)\n", 10, 3, 12.345); // ( 12.345)
printf("(%10.*e)\n", 3, FLOAT_DATA); // ( 1.235e+03)
printf("(%+*.2f)\n", 10, FLOAT_DATA); // ( +1234.57)
*은 전달 인수를 사용하여 필드폭을 지정하는 방식입니다. 이때 전달 인수는 양의 정수를 사용하며 (*)에 1:1로 대응하여 필드폭을 지정합니다. 실제로는 널리 쓰이지 않지만, 용례를 보이기 위해 예를 든 것입니다. 위의 첫번째 출력문에서는 필드폭과 정밀도를 전달 인수 (10,3)로부터 받는 것입니다. 두번째는 정밀도(3)를 전달 인수로 받습니다. 세번째는 필드폭을 전달 인수(10)로부터 받습니다.
확인문제 3
/* 문자열 데이타의 출력 형식을 지정한 출력의 예 */
#include <stdio.h>
#define STRING_DATA "SOONCHEON TEC. COLL.!"
main()
{
printf("(%s)\n", STRING_DATA);
printf("(%5s)\n", STRING_DATA);
printf("(%25s)\n", STRING_DATA);
printf("(%-25s)\n", STRING_DATA);
printf("(%25.5s)\n", STRING_DATA);
printf("(%-25.5s)\n", STRING_DATA);
printf("(%.8s)\n", STRING_DATA);
printf("(%10.s)\n", STRING_DATA);
printf("(% #+025s)\n", STRING_DATA);
}
참고: 문자열에는 #, +, 0, 공백 등의 플래그가 적용되지 않습니다.
2. 데이터 입력 : scanf()
라이브러리 함수 scanf( )를 사용하면, 표준 입력 장치 (키보드)를 이용하여 문자열이나 숫자 데이터를 입력할 수 있다.
(1) 정수값의 입력
키보드에서 정수형 변수 a에 정수값 데이터를 입력하려면
scanf("%d", &a):
라 한다 "%d"는 printf( )에서와 같은 의미의 형식 제어 문자열이다. 단지 printf( )와 다른 것은 인수 a의 앞에 &가 있다는 것이다. &을 붙이는 이유는 뒤에서 설명하기로 하고 여기서는 배열, 포인터 변수 이외의 일반적인 변수에는 &를 붙인다는 것을 반드시 기억하자.
두 개의 변수 a, b에 정수 데이터를 입력하려면
scanf("%d %d", &a, &b);
라 한다. 키보드로 입력되는 데이터 간의 구분은 공백으로 하고 데이터 입력의 종결은 엔터(Enter) 키를 누르면 된다.
scanf("%d %d", &a, &b);
35 8
이것은 변수 a에 35, 변수 b에 8이 입력된다. 키보드로 입력되는 데이터 사이를 콤마(,)로 구분하려면 다음과 같이 지정한다.
scanf("%d,%d",&a, &b);
35,8
예제 4. 키보드를 이용하여 정수형 데이터를 입력하여 가, 감, 승, 제를 구하여라.
● 프로그램
#include <stdio.h>
main( )
{
int a, b ;
printf("data ? ");
scanf("%d %d",&a, &b);
printf("\nAdd = %d\n", a + b);
printf("Sub = %d\n", a - b);
printf("Mul = %d\n", a * b);
printf("Div = %d\n", a/b);
}
● 결과
data ? 55 10 (화면에 data? 라고 표시되면 scanf 함수가 임의의 정수값을 키보드를 통해 입력하기를 기다리므로 가, 감, 승, 제 연산을 하기 원하는 정수값을 입력한다. 이 결과는 55와 10이라는 두 값을 입력한 예이다.)
Add = 65
Sub = 45
Mul = 550
Div = 5
(2) 실수값의 입력
C 언어에서 실수는 float(4바이트)와 double(8바이트)로 표시하지만 함수 등의 인수로서 전달될 때는 float가 double로 변환되는데, 여기서는 double형의 변수에 대해서 취급한다. double 형의 변수 a 에 실수 데이터를 입력하려면,
scanf("%lf", &a);
라고 한다. printf( )에서는 float와 double도 형식 제어 문자로서 f를 사용하지만 scanf( )에서는 double 형의 제어 문자로서 lf(long float=double)를 사용한다.
예제 5. 키보드를 이용하여 실수형 데이터를 입력하여 가, 감, 승, 제를 구하여라.
● 프로그램
#include <stdio.h>
main( )
{
double a, b;
printf("data ? ");
scanf("%lf %lf",&a, &b);
printf("\nAdd = %f\n", a + b);
printf("Sub = %f\n", a - b);
printf("Mu l= %f\n", a * b);
printf("Div = %f\n", a/b) ;
}
● 결과
data ? 100 56 (화면에 data? 라고 표시되면 scanf 함수가 임의의 실수값을 키보드를 통해 입력하기를 기다리므로 가, 감, 승, 제 연산을 하기 원하는 실수값을 입력한다. 비록 정수값을 입력해도 scanf에서 지정된 대로 실수값으로 저장된다. 이 결과는 100과 55라는 두 값을 입력한 예이다.)
Add = 156.000000
Sub = 44.000000
Mul = 5600.000000
Div = 1.785714
(3) 문자열의 입력
문자열을 입력하려면, 일반적으로 변수로는 안 되고 배열을 사용해야 한다. 배열에 대해서는 5주차 강의에서 설명하겠지만, 일반적으로 다음과 같이 선언한다.
char str[20];
이것은 문자형 배열 str을 선언하게 되고, str에 20 문자의 영역이 확보된다. 이렇게 선언한 뒤에,
scanf("%s", str);
라 한다. 키보드를 통해 hello라고 입력하면 배열 str에 「hello」가 저장된다. 또
printf("%s\n", str);
라 하면, 배열 str의 내용 「hello」가 이 화면에 표시된다.
예제 6. 이름과 생년월일을 입력하여 생일 축하 메시지를 작성하여라.
● 프로그램
#include <stdio.h>
main( )
{
char name[20];
int y, m, d;
printf("name ? "); scanf("%s", name);
printf("date ? "); scanf("%d %d %d", &y, &m, &d);
printf("\n////////////////////////////////////\n");
printf(" Happy birthday to %s\n", name);
printf(" %d. %d. %d\n", y, m, d);
printf("////////////////////////////////////\n");
}
● 결과
name ? Seyoung (화면에 name? 이라고 표시된 후 이름에 해당하는 임의의 문자열을 입력하면 scanf 함수에 의해 name이라는 문자 배열에 저장된다)
date ? 1991 12 2 (화면에 date? 라고 표시된 후 생년웧일에 해당하는 임의의 문자열을 입력하면 scanf 함수에 의해 년 월 일 값이 각각 y, m, d에 저장된다)
////////////////////////////////////
Happy birthday to Seyoung
1991. 12. 2
////////////////////////////////////
(4) scanf( )의 형식
scanf( )의 일반 형식은 다음과 같다.
scanf(format, arg1, arg2…)
형식 제어 문자열의 일반적인 형식은 다음과 같다. [ ]내에 있는 항목들은 생략이 가능하다.
%[*][w][l] 변환문자
%…형식 제어 문자열의 시작
* …대입 불가능. *이 있는 형식 제어 문자열에 대응하는 필드는 건너 뛰고 데이터는 입력되지 않는다.
w …w는 폭을 지정하며 폭을 분류하여 입력한다.
l …long형 데이터 지정. 변환 문자 d, o, x, f를 지정한다.
변환문자
d…부호가 있는 10진법 정수
o…부호가 없는 8진법 정수
x…부호가 없는 16진법 정수
u…부호가 없는 정수
c…1문자 입력
s…문자열
f…부동 소수점 숫자
e…부동 소수점 숫자
다음과 같은 예를 생각해 보면,
int year; char name[16];
scanf("%s %d", name, & year);
candy 20 이라고 입력하면, name과 year에 각각 candy와 20이 저장됨
int a; long b; double c;
scanf("%x %ld %lf", &a, &b, &c);
laft 100000 3.1415927을 입력하면, a b c에 각각 차례대로 기억됨
int year; char name[16];
scanf("%5s%2d", name, %year);
candy20을 입력하면 각각 name과 year에 지정되고, 이 경우 필드 폭을 지정하고 있으므로 입력하는 데이터(candy와 20)사이에 구분 기호는 두지 않는다.
더욱이 scanf( )의 리턴값은 정상적으로 입력되는 항목의 수이다. (참고로 ^Z (CTRL+Z)가 입력되면 -1이 리턴된다. 예를 들면,
scanf("%d%d", &a, &b);
에 대하여 정상적으로 데이터 입력이 이루어지면 2가 리턴된다. 이것을 이용한 확인 문제를 앞으로 만나게 될 것이다. 기억하기 바란다.
참고: 변환 문자 *
입력 지정 금지 문자(*)는 키보드로부터 입력되어 입력 버퍼에 저장된 데이터의 입력을 금지하여 입력 자체를 취소합니다. 따라서 버퍼에 저장된 데이터는 일단 읽혀져서 버리게 되고, 버퍼의 입력 위치는 다음 데이터로 이동합니다. 예를 들
면,
printf("Input data: ");
scanf("%*d %d %*c %f %c", &i, &f, &c);
printf("Results of print data : %d %f %c", i, f, c):
위의 간단한 실행문에서, scanf() 함수는 출력 서식 문자열("%*d %d %*c %f %c, &i, &j, &c)에서 모두 5 개의 데이터 입력을 요구합니다. 이때 다음과 같이 키보드로부터 데이터 입력을 했다고 합시다.
Input data: 123 456 a 123.456 b [Enter 키]
위와 같이 입력하면 입력 버퍼에는 다음과 같이 저장될 것입니다.
---------------------------
123 456 a 123.456 b
---------------------------
입력 버퍼에서 데이터와 데이터 사이의 구분은 공백 문자로 이루어지므로, 먼저 123을 읽어 %*d 지정자에 의해서 읽은 데이터를 버리고, %d 지정자에 의해서 데이터 456을 읽어 정수로 변환한 다음 변환된 정수 456을 변수 i의 주소 부분에 저장합니다. 다음으로 %*c 지정자에 의해서 문자 'a'를 읽어서 버리고, 나머지 데이터인 123.456과 문자 'b'를 읽어 변수 f와 c의 주소에 각각 저장합니다. 따라서 출
력 결과는 다음과 같습니다.
Results of print data : 456 123.456 b
일반적으로 scanf( ) 실행시 입력 데이터 구분은 필드 폭 w로 구분되지만 그 폭의 끝에 도달하기 전에 공백, 줄바꿈 문자(\n), 탭(\t) 등이 나타나면 그 곳에서 데이터의 구분이 됩니다. 단, %c로 지정하고 스트링 입력시에 첫 문자만 입력되는 것에 주의할 것! 또 scanf ( )에 대한 입력 종료의 표시는 엔터 키에 의해서 이루어집니다.
확인문제 4
/* 필드 폭을 지정한 입력 서식 프로그램 */
#include <stdio.h>
main( )
{
int i, j, k;
float f, g;
char string[20];
printf("Input data: ");
scanf("%3d %4f %d %5f %4s %3d", &i, &f, &j, &g, string, &k);
printf("Results of print data : %d %f %d %f %s %d",
i, f, j, g, string, k);
}
예제 7: scanf 함수를 사용한 program
#include <stdio.h>
main() /* Example of scanf 함수 */
{
char name[30];
char class;
short number;
printf("Input name, class, number = ");
scanf("%s %c %d", name, &class, &number); /* ktkwon A 123을 입력*/
/* "%s %c %d"를 "%s%c%d"로 고치면 어떻게 될까? 각자 확인*/
printf("%s, %c, %d\n", name, class, number);
}
● 결과
Input name, class, number = ktkwon A 123 (화면에 Input name, class, number = 라고 표시된 후 이름, 클래스, 숫자에 해당하는 각각의 값을 입력하면 scanf 함수에 의해 각각 name, class, number에 저장된다)
ktkwon, A, 123
"%s %c %d"를 "%s%c%d"로 고친 결과
Input name, class, number = ktkwon A 123
ktkwon, ,27197
<요약> scanf 함수
scanf(제어문자열, 인자-1, 인자-2, ..., 인자-n);
① 변환문자는 printf 함수와 유사하며 다른 점은 아래와 같다.
1. %g는 허용하지 않음
2. %f와 %e는 동일하다.
3. %h --- short int를 입력
② 단순변수(정수, 실수, 문자)에 대한 입력은 변수 명칭 앞에 &를 붙인다.
③ 문자열(문자형 배열)에 대한 입력은 &를 사용하지 않는다.
※ scanf 함수 사용시 주의할 점
1. 정수나 실수를 입력할 때 주로 사용.
2. 문자를 입력할 때는 getchar, 문자열(string)을 입력할 때는 gets를 사용
3. scanf와 다른 함수(getchar, gets 등)를 같이 사용할 때 주의해야 한다.
※ C 언어에서 출력 함수는 printf가 주로 사용되지만, 입력 함수는 scanf가 가장 많이 사용되는 것은 아니다.
확인문제 5
/* scanf(), printf() 함수와 gets(), puts() 함수를 이용한 문자열 입출력 */
#include <stdio.h>
main( )
{
char name[20];
printf("1. What is your name?: ");
scanf("%s", name); /* 문자 배열에 하나의 단어만 입력됨 */
printf(" My name is %s ", name);
puts("2. What is your name?: ");
gets(name); /* 입력 버퍼로부터 나머지 문자열을 입력 받음 */
puts(name); /* 나머지 문자열 출력, 줄 바꿈 */
puts("good!");
}
참고:
실행 결과는 다음과 같습니다.
1. What is your name?: Lee Hyo Lee
My name is Lee 2. What is your name?:
Hyo Lee
good!
예상했던 대로 scanf() 함수는 하나의 단어인 "Lee" 문자열만 입력받고 나머지는 입력 버퍼에 남게 됩니다. 문자 배열 name에 입력된 내용을 printf() 함수에서 %s 출력 지정자로 출력하기 때문에 "My name is Lee"라는 문자열을 출력하지만 printf() 함수에서는 문자 배열에서 문자열 끝을 표시하는 '\0'가 '\n'으로 변경되지 않으므로 줄바꿈을 하지 않아 puts() 함수에서 출력한 문자열이 같은 줄에 출력됩니다. 그리고 나서 gets() 함수는 입력 버퍼로부터 나머지 문자열을 모두 읽어 문자 배열 name에 배정하고 이를 다시 출력하므로 문자열 "Hyo Lee"를 출력하고 문자열 끝 표시인 '\0'을 '\n'으로 변경하여 줄바꿈을 한 다음 문자열 "good"을 출력합니다.
※ scanf("%c %d %d", &c, &i, &j); 에 대한 입력 데이터
"A 10 20B 30 40"는 허용되나 "A 10 20<Enter>B 30 40" or "A 10 20 B 30 40" 등
20과 B사이에 space가 삽입되면 안됨.
참고: scanf() 함수가 반복적으로 적용될 때, 위의 입력 데이터의 경우 20과 B사이에 space가 삽입되면 그 space를 지정자 %c에 의해 정상적인 데이터로 간주한다는 것입니다.
확인문제 6
/* float, double, long double 형에 대한 입/출력 프로그램 */
#include <stdio.h>
main( )
{
float float_x;
double double_y;
long double long_double_z;
printf("Input data1 in float, double, long double: ");
scanf("%f %lf %Lf", &float_x, &double_y, &long_double_z);
printf("%6f %11.lf %.13Lf \n", float_x, double_y, long_double_z);
printf("%e %le %Le \n", float_x, double_y, long_double_z);
printf("%E %lE %LE \n", float_x, double_y, long_double_z);
printf("%g %lg %Lg \n", float_x, double_y, long_double_z);
printf("%G %lG %LG \n", float_x, double_y, long_double_z);
printf("Input data2 in float, double, long double: ");
scanf("%g %le %.Le", &float_x, &double_y, &long_double_z);
printf("%.4f %.7lf %.9Lf \n", float_x, double_y, long_double_z);
printf("%e %le %Le \n", float_x, double_y, long_double_z);
printf("%E %lE %LE \n", float_x, double_y, long_double_z);
printf("%g %lg %Lg \n", float_x, double_y, long_double_z);
printf("%G %lG %LG \n", float_x, double_y, long_double_z);
}
3. 한 문자 단위의 입출력
printf( )나 scanf( )는 형식이 있는 입출력 함수였지만 한 문자 단위의 입출력 함수로는 getchar와 putchar가 있다. 이것들은 정확히 말하면 함수가 아니고 매크로(macro)이며, stdio.h 내에서 다음과 같이 정의된다.
#define getchar getc(stdin)
#define putchar putc((c), stdout)
매크로와 함수의 다른 점은 12주차 강의에서 설명된다.
사용자가 getchar/putchar를 사용하려면 표준 입출력 헤더 파일 stdio.h을 포함하도록 프로그램 선두에 다음과 같이 사용해야 한다.
#include <stdio.h>
(1) putchar( ) : 한 문자 출력
putchar(c);
위의 함수는 c에 저장된 문자를 화면에 출력한다. c는 char형(문자형) 또는 int형(정수형)의 데이터로서 h나 h+1, 0x61과 같은 상수나 식, \t, \n 등의 확장 문자를 사용할 수 있다.
예제 8. 화면에 하나의 문자를 출력하여라.
● 프로그램
#include <stdio.h>
main( )
{
putchar('a');
putchar('\n');
putchar('a'+1); /* 'a'+1은 'a'의 ASCII 코드 0x61에 1을 더한 'b'를 표시*/
putchar('\t');
putchar(0x71); /*ASCII 코드 0x71은 'q'를 표시 */
}
● 결과
a
b q
(2) getchar( ) : 한 문자 입력
c=getchar( );
위의 함수 표시는 변수 c에 키보드에서 입력된 하나의 문자가 저장된다. 키보드에서 데이터의 끝을 표시하는 데는 ^Z (CTRL+Z, 즉 Crtl키와 Z키를 동시에 누름) 를 입력하는 경우가 있다. ^Z가 입력되어지면 getchar( )은 -1을 리턴하여 c에 -1이 기억된다. 따라서 변수 c에는 char 또는 int 형을 사용해야 한다. 즉, 프로그램 상단에 변수 c를 문자형이나 정수형으로 선언해야 한다. 만약에 unsigned형(부호 없는 정수형)을 사용하면 -1을 인식하지 못한다.
예제 9. 키보드에서 한 문자를 읽어 화면에 표시
● 프로그램
#include <stdio.h>
main()
{
char ch;
ch = getchar();
putchar(ch);
}
예제 10. 키보드에서 입력한 문자를 그대로 화면에 출력하여라. 이 과정을 ^Z가 입력될 때까지 반복하여라.
● 프로그램
#include <stdio.h>
main( )
{
int c;
while ((c=getchar( )) !=EOF)
putchar (c);
}
● 결과
Hello Turbo C
Hello Turbo C
Candy
Candy
^Z
(3) 버퍼(buffer)
scanf()나 getchar()는 <Enter> 키를 누른 다음에야 데이터가 입력된다. <Enter> 키 이전까지의 데이터가 입력 버퍼라고 하는 임시기억장소에 저장되었다가 <Enter> 키를 누르면 프로그램으로 데이터가 전송된다. 따라서 여러 문자를 입력하더라도 <Enter> 키를 입력해야만 getchar()가 실행된다. scanf(), printf(), getchar(), putchar()는 buffered I/O 함수이고, getch(), getche(), putch()는 unbuffered I/O 함수이다.
확인문제 7
/* getchar( ), getch( ), getche( ), putchar( ), putch( ) 함수의 예제 */
#include <conio.h> /* getch( ), getche( ), putch( )를 정의하고 있음 */
#include <stdio.h>
main( )
{
char ch, ch2;
/* first while statement */
printf("Input first string: ");
while((ch = getchar( )) != '\n')
putchar(ch);
putch(ch);
putchar('\n');
/* second while statement */
printf("Input second string: ");
while((ch = getche( )) != '\r')
putch(ch);
printf("\n ***");
putchar(ch);
/* third while statement */
printf("Input third string: ");
while((ch = getch( )) != '\r')
printf(" ===> %c\n", ch);
putch(ch);
}
4. 심화 학습
예제 11. 키보드로 입력되는 문자를 읽어 '*'가 입력될 때까지 출력하는 프로그램이다. 아직 공부하지 않은 while 문이 나오므로 부담을 가지지 말고 읽어 보기 바란다. 두 가지 가능한 형태를 나란히 제시하였다.
#include <stdio.h>
main() /* 문자 '*'가 입력될 때까지 문자들을 입력하는 프로그램 */
{
char ch;
ch = getchar(); | while ((ch = getchar()) != '*')
while (ch != '*') { | putchar(ch);
putchar(ch); |
ch = getchar(); |
}
}
위 프로그램이 이해가 되는 사람들은 다음에 제시하는 대로 수정해 보기 바란다.
1) 읽어들인 문자의 수를 count하여 출력하는 프로그램으로 고쳐 쓰시오.
2) STOP 문자를 '\n'으로 바꾸면 한 line을 읽어 들인다. --- <Enter> 키가 입력될 때까지
3) STOP 문자를 EOF로 바꾸면 end-of-file 문자(ctrl-Z)가 입력될 때까지 문자를 읽어들인다.
댓글