1. 키보드로부터의 입력
모니터로 출력할 때는 printf 함수를 사용했듯이,
키보드로부터 입력을 받을 때에도 어떤 함수를 사용해야 한다.
이 때 사용되는 함수가 scanf 함수다.
사용법은 printf 함수와 매우 유사하다.
scanf("%d", &num);
정수를 키보드로부터 입력받아 변수 num 에 저장한다는 의미다.
여기서 주목할 점은 변수 앞에 붙은 & 연산자다.
왜 그런지는 조금 뒤에 설명하겠다. 우선은 &를 변수 앞에 붙여줘야 한다는 것만 기억하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <stdio.h>
int main()
{
int num1, num2;
int result;
printf("첫 번째 정수 입력: ");
scanf("%d", &num1);
printf("두 번째 정수 입력: ");
scanf("%d", &num2);
result = num1 + num2;
printf("%d + %d = %d\n", num1, num2, result);
return 0;
}
|
cs |
scanf 함수는 개행 뿐만 아니라 공백으로도 입력값을 구분한다.
그러니까 만약에 3 5 라고 입력하면
3 을 입력한 다음 5 를 입력한 것으로 간주한다는 이야기다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <stdio.h>
int main()
{
int num1, num2;
printf("num1 num2 입력: ");
scanf("%d", &num1);
scanf("%d", &num2);
printf("num1: %d, num2: %d\n", num1, num2);
return 0;
}
|
cs |
2. printf 함수
이미 알고 있겠지만 printf 함수는 출력하는 함수다.
그런데 단순히 출력하는 함수라면 이름을 print 로 해도 될텐데, 왜 printf 일까?
printf 에서 f 는 formatted(서식화된) 을 의미한다. scanf 의 f 도 마찬가지다.
다시 말해, 정해진 서식에 따라 입력받고, 정해진 서식에 따라 출력한다는 이야기다.
이 때 서식은 서식 문자(conversion specifier)을 통해 나타낸다.
서식 문자는 어떤 형식으로 출력할 것인지를 지정하는 문자다.
예를 들어 10진수 정수를 %d 로 나타내고, 실수는 %f 로 나타낸다.
서식 문자 |
출력 자료형 |
출력 형식 |
%d |
char, short, int |
부호 있는 10진수 정수 |
%ld |
long |
부호 있는 10진수 정수 |
%lld |
long long |
부호 있는 10진수 정수 |
%u |
unsigned int |
부호 없는 10진수 정수 |
%o |
unsigned int |
부호 없는 8진수 정수 |
%x, %X |
unsigned int |
부호 없는 16진수 정수 |
%f |
float, double |
부동소수점 방식의 10진수 소수 |
%Lf |
long double |
부동소수점 방식의 10진수 소수 |
%e, %E |
float, double |
*e 표기법으로 나타낸 부동소수점 소수 |
%g, %G |
float, double |
값에 따라 부동소수점 %e/E와 %f 선택 |
%c |
char, short, int |
값에 대응하는 문자(ASCII) |
%s |
char* |
문자열 |
%p |
void* |
주소값 |
*e 표기법: 큰 수를 3.0414e+64와 같은 형식으로 나타내는 것.
3.0414e+64는 3.0414×10^64를 의미한다.
정수, 실수, 문자열, 주소값으로 나누어서 보겠다.
① 정수: %d, %ld, %lld, %u, %o, %x · %X
주의할 것은 부호의 유무다.
음의 정수를 나타내려면 %d, %ld, %lld를 사용해야 한다.
또한 long long형 값을 %d나 %ld로 나타내면 4바이트만큼 버려져 정확한 값이 출력되지 않을 수 있으니 주의해야 한다.
%x와 %X 두 가지를 사용하는 것은 16진수의 알파벳(A~F)의 대소문자를 구별하기 위함이다.
참고로 8진수를 8진수 형식으로, 16진수를 16진수 형식으로 나타내려면
%#o, %#x로 출력하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <stdio.h>
int main()
{
int num1 = 178; //0262, 0xB2
long long num2 = 8223372036554775807;
printf("10진수로 출력\n");
printf("178을 %%d로 출력: %d\n", 178);
printf("\n178을 %%o로 출력: %o\n", 178);
printf("178을 %%#o로 출력: %#o\n", 178);
printf("\n178을 %%x로 출력: %x\n", 178);
printf("178을 %%#x로 출력: %#x\n", 178);
printf("178을 %%X로 출력: %X\n", 178);
printf("178을 %%#x로 출력: %#x\n", 178);
printf("\n8223372036554775807을 %%d로 출력: %d\n", 8223372036554775807);
printf("8223372036554775807을 %%ld로 출력: %ld\n", 8223372036554775807);
printf("8223372036554775807을 %%lld로 출력: %lld\n", 8223372036554775807);
return 0;
}
|
cs |
8223372036554775807 을 %d 와 %ld 로 출력했더니 다른 값이 나온 것을
확인할 수 있다.
각각 2진수로 나타내서 확인하는 게 확실하지만... 넘어가도록 하자.
참고로 %%는 %를 출력하기 위함이다. 그냥 %만 쓰면 서식 문자로 인식되기 때문에,
%를 출력하고 싶다면 %%라고 써야 한다.
② 실수: %f, %Lf, %e, %E, %g, %G
앞에서 %g와 %G는 값에 따라 %e와 %f 중 하나를 선택해서 출력한다고 했다.
이는 값의 범위에 따라 선택하는 것인데, 계산기를 생각하면 쉽다.
휴대전화의 계산기로 3×5를 계산해보면, 결과 값 15가 그대로 나오지만
50!를 계산하면 3.0414e+64와 같은 형식으로 나온다.
그리고 1÷2를 계산하면 결과 값 0.5가 나오지만
1÷56354345를 계산하면 1.77448e-8와 같은 형식으로 나온다.
%e와 %f를 선택하는 것이 바로 이것이다.
즉, 일정 범위의 수는 그대로 출력하다가 그 범위를 벗어나면 e 표기법으로 나타낸다는 것이다.
%e와 %E 두 가지를 사용하는 것은 3.0414e+64로 나타낼 것인지,
3.0414E+64로 나타낼 것인지를 선택하기 위함이다.
참고로 변수를 초기화할 때 e 표기법을 사용할 수도 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <stdio.h>
int main()
{
double num1 = 0.00123;
double num2 = 1.23e-6; //0.00000123
printf("num1을 %%f로 출력: %f\n", num1);
printf("num2를 %%f로 출력: %f\n", num2);
printf("num1을 %%e로 출력: %e\n", num1);
printf("num2를 %%E로 출력: %E\n", num2);
printf("num1을 %%G로 출력: %G\n", num1);
printf("num2를 %%g로 출력: %g\n", num2);
return 0;
}
|
cs |
③ 문자열 출력
문자열(string)은 여러 개의 문자를 나열한 것을 말한다. 두 글자 이상의 단어라고 보면 된다.
C언어에서 문자 하나는 작은 따옴표로, 문자열은 큰 따옴표로 감싸서 나타낸다.
아직 문자열에 대해 여러가지 이야기를 하기에는 이르기 때문에, 모든 것을 설명하진 않겠다.일단은 서식 문자 %s의 활용법만 알고 넘어가자.
1
2
3
4
5
6
7
8
|
#include <stdio.h>
int main()
{
printf("%s %s %s\n", "AAA", "BB", "CCCC");
return 0;
}
|
cs |
ㅁㄴㅇ
④ 주소값 출력
이 부분은 참고만 하고 넘어가자.
그냥 이런 것도 있구나 정도까지만 하는 게 좋다.
1
2
3
4
5
6
7
8
9
10
|
#include <stdio.h>
int main()
{
int num;
printf("num의 주소: %p\n", &num);
return 0;
}
|
cs |
num 은 메모리 공간 상의 0x00EFFD70 번째 바이트에 위치하고 있다는 뜻이다.
printf 함수는 출력의 필드 폭을 지정하는 옵션을 통해 정렬해서 출력하는 것도 가능하다.
printf 함수는 명령 프롬프트 상에 출력하기 때문에, 결과의 가독성을 높이기 위해
필드의 폭을 지정해야 하는 경우도 생긴다.
필드 폭은 다음과 같이 지정한다.
%8d 8칸의 필드를 확보하고 오른쪽으로 정렬해 출력한다.
%-8d 8칸의 필드를 확보하고 왼쪽으로 정렬해 출력한다.
1
2
3
4
5
6
7
8
9
10
11
|
#include <stdio.h>
int main()
{
printf("%-8s %18s %13s\n", "이 름", "전공", "학번");
printf("%-8s %18s %13d\n", "김수한무", "물리학과", 201914076);
printf("%-8s %18s %13d\n", "박귀선", "경호보안학과", 201316813);
printf("%-8s %18s %13d\n", "엄판근", "유아교육학과", 201612584);
return 0;
}
|
cs |
%-8s 로 출력한 이름은 왼쪽으로 정렬됐고, %18s 로 출력한 전공은 오른쪽으로 정렬된 것을
확인할 수 있다.
이제 printf 함수로 여러 가지 데이터를 출력할 수 있다는 것도 알고,
문자열은 큰 따옴표로 감싸서 나타낸다는 것도 알았다.
그럼 다음 문장은 어떻게 출력할까?
"아, 책이 있다!" 아가씨는 책을 집어 들더니 눈을 반짝이며 읽었다.
_<장 발장>, 빅토르 위고
지금까지 해왔던 것처럼, 앞 뒤에 큰 따옴표를 붙여보자.
printf(""아, 책이 있다!"
아가씨는 책을 집어 들더니 눈을 반짝이며 읽었다.");
이제 이것을 실행하려고 하면 에러가 발생할 것이다.
왜 그럴까?
C언어는 문자열을 큰 따옴표로 감싸서 나타낸다고 했는데, 이는 바꿔 말하면 다음과 같다.
큰 따옴표의 시작은 문자열의 시작으로, 큰 따옴표의 끝은 문자열의 끝으로 간주한다.
그러니까 앞의 문장에서 문자열을 표시하면 다음과 같다.
printf(""아, 책이 있다!" 아가씨는 책을 집어 들더니 눈을 반짝이며 읽었다.");
컴파일러는 아, 책이 있다!를 해석할 수 없어 에러가 발생하는 것이다.
이런 이유로 특수 문자 이스케이프 시퀀스(escape sequence)가 등장했다.
이스케이프 시퀀스는 출력할 문자 앞에 백슬래시(backslash, \)를 붙여 나타낸다.
특수 문자 |
의미 |
\a |
경고음 |
\b |
백스페이스(backspace) |
\f |
폼 피드(form feed) # |
\n |
개행(line feed) |
\r |
캐리지 리턴(carriage return) |
\t |
수평 탭(horizontal tab) |
\v |
수직 탭(vertical tab) # |
\' |
작은 따옴표 |
\" |
큰 따옴표 |
\? |
물음표 |
\\ |
백슬래시 |
# 표시된 문자들은 프린터 출력을 위해 정의된 문자들이기 때문에, 모니터 출력에서는
의미가 없다. 출력해보면 이상한 문자가 출력될 것이다.
이제 앞의 문장을 출력해보자.
1
2
3
4
5
6
7
8
|
#include <stdio.h>
int main()
{
printf("\"아, 책이 있다!\" 아가씨는 책을 집어 들더니 눈을 반짝이며 읽었다.");
return 0;
}
|
cs |
나머지 문자들은 직접 해보자.
3. scanf 함수
앞에서 언급했듯이, scanf 함수는 입력에 쓰이는 함수다.
scanf 함수의 호출을 위해서는 기본적으로 다음 두 개의 정보가 필요하다.
ⅰ. 입력받을 형식
ⅱ. 입력받은 값을 저장할 장소
printf 함수와 마찬가지로 scanf 의 f 는 formatted(서식화된)의 약자라고 했다.
따라서 scanf 함수 역시 서식 문자로 입력받을 형식을 지정한다.
그러니까 %d 를 쓰면 부호 있는 10진수 정수의 형태로,
%e 를 쓰면 e 표기법으로 나타낸 실수로 입력받는다는 이야기다.
scanf 함수의 사용법은 다음과 같다.
scanf("%d", &num);
앞에서 언급했듯이, 입력에는 두 가지 정보가 필요하다.
첫 번째 인자로 형식을 지정했으니, 두 번째 인자로 장소를 지정해야 한다는 것이다.
이 때 쓰이는 것이 &(ampersand) 연산자다.
& 연산자는 피연산자의 주소값을 반환하는 연산자로, &피연산자의 형식으로 사용한다.
피연산자는 주로 변수로, 주소값은 그 변수의 위치를 나타낸다.
변수는 메모리 공간 어딘가에 있다.
그리고 & 연산자는 메모리 공간 상의 변수의 위치를 반환한다.
잘 모르겠다면 다음을 참조하자.
컴퓨터에서 메모리라고 하면 보통 메인 메모리(주기억장치)를 말한다.
메인 메모리는 1바이트씩 구분되는데, 이렇게 구분된 메모리 단위에는
주소 또는 번지라고 부르는 번호가 있다.
메모리의 위치를 1바이트씩 나눠서 0번지, 1번지, 2번지, ...로 나타내는 것이다.
쉽게 말해, 메모리 상의 위치를 쉽게 나타내기 위해 1바이트 단위로 숫자를 매기고,
이를 주소라고 부르는 것이다.
그러니까 변수에 담긴 값이 아니라 변수의 위치가 필요하다는 것이다.
scanf("%d", &num);
따라서 위 문장은 다음을 의미한다.
입력받은 값을 부호 있는 10진수로 해석한 다음, 그 값을 num에 저장하라.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <stdio.h>
int main()
{
int num1, num2, num3;
printf("num1 num2 num3 입력: ");
scanf("%d %o %x", &num1, &num2, &num3);
printf("num1: %d, num2: %d, num3: %d", num1, num2, num3);
return 0;
}
|
cs |
num1 에서는 12 를 10진수로 해석했기 때문에 그대로 12 가 출력되었고,
num2 에서는 12 를 8진수로 해석했기 때문에 10진수로는 10 이 출력되었고,
num3 에서는 12 를 16진수로 해석했기 때문에 10진수로는 18 이 출력되었다.
scanf 함수 역시 모든 서식 문자가 사용 가능하다.
다만 실수형을 입력할 때, %f 와 %e, %g는 모두 float 형을 의미한다.
그러니까 셋 중 무엇을 쓰든 float형으로 해석한다는 것이다.
double 형은 %lf 나 %Lf 로 입력받아야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include <stdio.h>
int main()
{
float num1;
double num2;
long double num3;
printf("\nnum1 입력: ");
scanf("%f", &num1);
printf("\nnum2 입력: ");
scanf("%lf", &num2);
printf("\nnum3 입력: ");
scanf("%Lf", &num3);
printf("\nnum1: %f\n", num1);
printf("num2:%f\n", num2);
printf("num3: %Lf", num3);
return 0;
}
|
cs |
위 예제를 통해 말하고 싶은 것은 다음의 두 가지다.
① 실수는 e 표기법으로도 입력할 수 있다.
② float, double, long double을 출력할 때의 서식 문자는 %f, %f, %Lf고,
float, double, long double을 입력할 때의 서식 문자는 %f, %lf, %Lf다.
'Programming > C' 카테고리의 다른 글
조건 분기 (0) | 2019.03.04 |
---|---|
반복문 (0) | 2019.03.03 |
연산자 (0) | 2019.03.01 |
변수와 자료형 (0) | 2019.02.26 |
C 프로그램의 기본 구조 (1) | 2019.02.24 |