
입력 : 자료를 컴퓨터 내부에 기억시킴
출력 : 컴퓨터 내부에 기억된 내용을 컴퓨터 외부로 나타냄
표준입출력함수는 라이브러리 <stdio.h>에 정의되어 있다.
printf(print formatted) 함수로 프로그램의 실행 결과를 출력할 수 있다.
양식 변환기호 퍼센트(%)는 자료의 입출력 양식을 저장하는 문자로, printf()와 scanf()에서 사용 가능하다.
| %문자 | 변환 양식 |
|---|---|
| %d | 부호 있는 10진 정수로 변환하여 출력 |
| %ld | 부호 있는 10진 long 정수로 변환하여 출력 |
| %lld | 부호 있는 10진 long long 정수로 변환하여 출력 |
| %u | 부호 없는 10진 정수로 변환하여 출력 |
| %o | 부호 없는 8진 정수로 변환하여 출력 |
| %x, %X | 부호 없는 16진 정수로 변환하여 출력 |
| %f | 10진 부동소수점 형식으로 변환하여 출력 |
| %lf | 10진 부동소수점 형식으로 변환하여 출력 |
| %e, %E | 지수 형태로 출력 |
| %g | f으로 출력되나 숫자값이 너무 길면 e로 출력 (유효숫자만 출력함) |
| %c | 한 문자로 변환하여 출력 |
| %s | 문자열로 변환하여 출력 |
| %p | 포인터 주소값 출력 |
양식 변환기호가 아닌 '%' 자체를 출력하기 위해선 '%%' 로 입력해야 한다.
⌨️ 예제 1
// printf() 함수로 다양한 데이터 출력하기
#include <stdio.h>
int main() {
// %d : 정수 출력
printf("%d + %d = %d\n\n", 2, 3, 5); //각 %마다 숫자 2, 3, 5,가 차례로 들어감
// %f : 실수 출력(소수점 여섯째 자리까지)
printf("%f\n", 3.14);
// %g : 실수 또는 지수 형태로 출력
printf("%g\n", 3.141592); // 실수 형태로 출력
printf("%g\n\n", 8723984712.12245674657); // 자릿수가 길어서 지수 형태로 출력
// %c : 문자 출력(한글, 한자 등 유니코드는 출력불가)
printf("%c %c %c\n\n", 'a', 'b', 'c');
// %s : 문자열(문자들의 열거) 출력(유니코드 가능)
printf("%s\n", "안녕하세요");
}
🖥️ 실행 결과
2 + 3 = 5
3.140000
3.14159
8.72398e+09
a b c
안녕하세요
printf 함수로 자료를 출력할 때 %문자 다음에 양수, 음수를 써서 출력 폭이나 각 변수에 대한 출력 자릿수를 지정 가능하다.
⌨️ 예제 2
#include <stdio.h>
int main() {
printf("|%d| \n", 123); // 출력 폭 : 숫자 길이만큼 자동 지정
printf("|%5d| \n", 123); // 출력 폭 : 5자리, 오른쪽부터 채움
printf("|%-5d| \n", 123); // 출력 폭 : 5자리, 왼쪽부터 채움
printf("|%05d| \n", 123); // 출력 폭 : 5자리, 오른쪽부터 채우고 공백은 0으로 채움
printf("|%6.1f| \n", 123.45); /* 출력 폭 : 6자리(소수점 포함),
반올림하여 소수 첫째 자리까지 출력 */
printf("|%07.2f| \n", 123.456); /* 출력 폭 : 7자리(소수점 포함),
반올림하여 소수 둘째 자리까지 출력 */
}
🖥️ 실행 결과
|123|
| 123|
|123 |
|00123|
| 123.5|
|0123.46|
키보드로부터 1개 이상의 자료를 입력받기 위해 scanf 함수를 사용한다. scanf 함수의 입력 양식에 %문자가 아닌 다른 문자는 포함시킬 수 없으며, 모든 변수 앞에는 주소를 의미하는 주소 연산자 &(앰퍼샌드)를 붙여야 한다. 다만 문자열, 배열명은 그 이름 자체가 주소의 의미를 갖고 있으므로 &를 생략한다. ❗️scanf() 쓸 땐 변수명 앞에 & 붙이는 것 잊지 않기
참조 : [C] 포인터
| %문자 | 변환 양식 |
|---|---|
| %d | 키보드를 통해 정수형을 입력받음 |
| %ld | 키보드를 통해 long 정수형을 입력받음 |
| %lld | 키보드를 통해 long long 정수형을 입력받음 |
| %f | 키보드를 통해 실수형을 입력받음 |
| %lf | 키보드를 통해 double 실수형을 입력받음 |
| %c | 키보드를 통해 문자형을 입력받음 |
| %s | 키보드를 통해 문자열을 입력받음 |
8진수 자료의 입력은 %o, 16진수 자료의 입력은 %x 를 사용한다.
scanf() 함수가 실행되면 자료를 입력 후 엔터 키를 누르면 된다. 하나 이상의 자료를 입력할 때는 자료 사이를 화이트 스페이스로 분리를 해야만 컴퓨터가 각각 개별의 자료로 구분할 수 있다.
✏️ 화이트 스페이스
컴퓨터에서 공백을 표현하는 문자들을 의미한다. 구분문자로 사용 가능한 것들이다.
- 공백문자 : space 키로 입력
- 탭문자 : tap 키로 입력(문자값은 \t)
- 새줄문자(newline) : enter 키로 입력(문자값은 \n)
⌨️ 예제 3
// 입력받은 두 정수의 합을 출력하는 프로그램
#include <stdio.h>
int main() {
int a, b; // 변수 2개 선언(값을 입력받기 때문에 초기화할 필요 없음)
printf("첫 번째 숫자 : ");
scanf("%d", &a);
printf("두 번째 숫자 : ");
scanf("%d", &b);
printf("%d + %d = %d\n", a, b, a+b);
}
🖥️ 실행 결과
첫 번째 숫자 : 3 [Enter↵]
두 번째 숫자 : 20 [Enter↵]
3 + 20 = 2
⌨️ 예제 4
// 2개의 숫자를 공백으로 구분하여 입력
#include <stdio.h>
int main() {
int num1, num2;
printf("두 개의 숫자를 순서대로 입력하기 : "); // num 1과 num2 사이를 스페이스로 구분
scanf("%d%d", &num1, &num2);
printf("첫번째 숫자 : %d\n", num1);
printf("두번째 숫자 : %d\n", num2);
}
🖥️ 실행 결과
두 개의 숫자를 순서대로 입력하기 : 2 3 [Enter↵]
첫번째 숫자 : 2
두번째 숫자 : 3
scanf("%d %d\n", &a, &b);
printf 함수에서는 이렇게 변환문자열 사이에 빈칸을 넣거나, 맨 끝에 줄바꿈을 하는 것이 일반적이지만,
scanf 함수에서는 필요가 없기 때문에 사용하지 않는 것이 더 추천된다.
❗️그러나 변환문자열 %c에서는 공백 사용이 중요한 역할을 한다
⌨️ 예제 5
// 2개의 문자를 공백으로 구분하여 함께 입력
#include <stdio.h>
int main() {
char ch1, ch2;
printf("두 개의 문자를 순서대로 입력하기 : ");
scanf("%c%c", &ch1, &ch2);
printf("첫번째 문자 : %c\n", ch1);
printf("두번째 문자 : %c\n", ch2);
}
🖥️ 실행 결과
두 개의 문자를 순서대로 입력하기 : a b [Enter↵]
첫번째 문자 : a
두번째 문자 :
첫번째 문자 a는 출력됐지만, b는 출력되지 않았다. 왜냐하면 ch2에는 b가 아니라 a 다음에 입력했던 공백문자가 저장됐기 때문이다.
예제 4처럼 숫자 데이터를 입력할 때는 공백문자 등을 구분문자로 사용하여 자료들을 구분할 수 있지만, 문자를 입력할 때는 화이트 스페이스 또한 문자값을 가진 데이터로 취급된다.
🛠️ 코드 수정
#include <stdio.h>
int main() {
char ch1, ch2;
printf("두 개의 문자를 순서대로 입력하기 : ");
scanf("%c %c", &ch1, &ch2); // 두번째 %c 앞에 공백문자 함께 작성
printf("첫번째 문자 : %c\n", ch1);
printf("두번째 문자 : %c\n", ch2);
}
🖥️ 실행 결과
두 개의 문자를 순서대로 입력하기 : a b [Enter↵]
첫번째 문자 : a
두번째 문자 : b
⌨️ 예제 6
// 2개의 문자를 하나씩 따로 입력
#include <stdio.h>
int main() {
char ch1, ch2;
printf("첫번째 문자 입력 : ");
scanf("%c", &ch1);
printf("두번째 문자 입력 : ");
scanf("%c", &ch2);
printf("첫번째 문자 : %c\n", ch1);
printf("두번째 문자 : %c\n", ch2);
}
🖥️ 실행 결과
첫번째 문자 입력 : a [Enter↵]
두번째 문자 입력 : 첫번째 문자 : a
두번째 문자 :
한편 두 문자를 하나씩 따로 입력해도 원하지 않은 출력값이 나오게 된다. 그 이유는 첫번째 문자 입력 후에 입력한 Enter 키가 버퍼에 남아있기 때문이다.
참조 : [C] 파일 입출력
키보드에서 입력하는 데이터는 바로 변수에 저장되지 않고 버퍼라고 하는 저장공간에 잠시 저장되었다가 입력이 되는 과정을 거치게 된다.
예제 5의 공백문자처럼 새줄문자 또한 하나의 문자로 인식되기 때문에 생기는 문제다.
🛠️ 코드 수정
#include <stdio.h>
int main() {
char ch1, ch2;
printf("첫번째 문자 : ");
scanf("%c", &ch1);
printf("두번째 문자 : ");
scanf(" %c", &ch2); // ch2의 입력문에서 %c 앞에 공백문자 함께 작성
printf("첫번째 문자 : %c\n", ch1);
printf("두번째 문자 : %c\n", ch2);
}
🖥️ 실행 결과
첫번째 문자 입력 : a [Enter↵]
두번째 문자 입력 : b [Enter↵]
첫번째 문자 : a
두번째 문자 : b
⌨️ 예제
// getchar 함수와 putchar 함수
#include <stdio.h>
int main() {
char ch; // getchar로 입력받은 문자를 저장할 변수(정수형이나 문자형)
printf("문자 하나를 입력하세요 : ");
ch = getchar(); // 문자 1개를 입력받아서 ch에 저장
putchar(ch); // ch에 저장된 문자 1개를 출력
putchar('\n'); // escape 문자 출력(문자 자체를 쓸 땐 작은 따옴표 안에)
}
🖥️ 실행 결과
문자 하나를 입력하세요 : a [Enter↵]
a
getchar 함수는 괄호 안에 인자를 지정하지 않으며, 문자 하나를 입력 후 엔터 키를 눌러서 자료를 입력한다.
gets 함수는 엔터 키를 누르기 전까지의 문자열(공백 포함)을 입력받는다. 공백 문자를 기준으로 입력받는 scanf 함수와의 차이점이다. 엔터 키를 누르면 맨 끝에 null 문자('\0')가 입력되어 문자열의 끝을 명시한다.
그러나, gets 함수는 보안상 취약점이 있어 더 이상 사용할 수 없으며, 대안으로 쓰는 gets_s 함수는 컴파일러에 따라 지원되지 않을 수도 있다.
예제에서는 이를 대체할 수 있는 fgets 함수를 사용했다. 이 함수는 괄호 안에 세 개의 매개 변수가 필요하다.
puts 함수는 문자열의 끝('\0' 문자)를 만나면 자동으로 '\n'으로 바꿔서 출력한다는 특징이 있어서, printf 함수처럼 개행문자 '\n'를 쓸 필요가 없다.
⌨️ 예제
// fgets 함수와 puts 함수
#include <stdio.h>
int main() {
char str1[100]; // gets 함수로 입력받은 문자열을 저장할 변수(char형 배열이나 포인터 변수)
fgets(str1, sizeof(str1), stdin); // 문자열을 입력받아서 str에 저장
puts(str1); // str에 저장된 문자열 출력
char str2[] = "Computer Science"; // 배열 str2를 초기화
puts(str2); // 자동으로 줄이 바뀌어 출력
}
🖥️ 실행 결과
Hello, World! [Enter↵]
Hello, World!
Computer Science
Hello, World! 이후에 2줄이 바뀌어 출력된 이유는 fgets 함수가 개행문자('\n')를 포함하여 입력받기 때문이다. 이미 지정한 문자열로 초기화된 배열을 출력할 때는 1줄만 바뀌는 것을 볼 수 있다.
scanf 함수가 콘솔(키보드)의 입력을 받는다면, sscanf 함수는 문자열로부터 입력받는다.
printf 함수가 콘솔(모니터)에 출력을 하는 함수라면, sprintf 함수는 문자열(버퍼)에 문자열을 출력한다.
⌨️ 예제
#include <stdio.h>
int main() {
// sscanf 함수
char str1[] = "123";
int n1;
sscanf(str1, "%d", &n1); // (입력받을 문자열, "입력받을 자료형", 입력받은 값을 저장할 변수)
printf("n1 : %d\n", n1);
// sprintf 함수
int n2 = 456;
char str2[100];
sprintf(str2, "%d", n2); // (출력할 문자열, "출력할 자료형", 문자열에 출력할 값)
printf("str2 : %s\n", str2);
}
🖥️ 실행 결과
n1 : 123
str2 : 456