C/C++ 관련 포스팅 목록
2020/07/02 - [Linux/C] - C/C++ C에서 Split 구현 예제(문자열 자르기 strtok)
2020/07/01 - [Linux/C] - C/C++ API 문자열 특정 문자로 나누기(strtok)
2020/06/28 - [Linux/C] - C/C++ API strchr(특정 문자 위치 검색)
2020/06/27 - [Linux/C] - C/C++ API access(파일 존재 여부 확인)
2020/06/26 - [Linux/C] - C/C++ API sprintf(문자열 붙이기)
목차
API의 필요성
안녕하세요 이번 포스팅에서는 아주 기본적이고 흔히 알고 있는 printf에 대하여 알아보겠습니다. 처음 C언어를 접하게되면 배우는 것이 printf("Hello world\n") 입니다. 이 구문은 간단하면서도 정말 많은 의미를 가지고 있는 예제입니다. print 라는 단어는 "출력하다" 라는 의미를 가지고 있습니다. 즉 화면에 나타내거나 무언가 실제 형상으로 내보낸다는 의미가 있습니다. print 다음의 f는 포멧을 의미합니다. 즉, printf API는 지정된 형식에 따라 출력한다 라는 의미가 됩니다.
자 이제 printf가 단순히 "Hello world" 같은 문자열을 출력하는 API가 아니라는 것을 조금씩 느끼게 됩니다. 다음으로 포멧이란 무엇일까요? 정해진 형식을 의미합니다. "Hello world" 라는 것은 문자열입니다. 이 문자열이 숫자가 될 순 없습니다. 반대로 볼까요? 3 이라는 것은 숫자일까요? 문자일까요? 덧셋, 뺄셈, 나눗셈 등 처리를 위해 사용한다면 숫자가 될 것이고 "3" 이라는 문자로 표시한다면 이것은 문자가 될것입니다.
바로 이 숫자냐 문자냐의 문제를 해결해주는 것이 포멧입니다.
포멧이란, 어떤 값을 어떠한 형태로 나타낼 것인지 결정하는 형태입니다. 흔히 printf에서 사용되는 "%s", "%d", "%ld" 등과 같은 포멧들은 너가 지금 출력하려는 값이 문자냐? 정수냐? 실수냐? 라는 것을 의미하는 포멧입니다.
printf는 이러한 포멧을 다양하게 지원하고 있습니다. 포멧이 다양하다는 의미는 많은 종류의 값들을 화면에 문자로 출력할 수 있다는 의미가 됩니다.
자 그러면 이제 printf의 여러가지 예제들을 확인하여 이해력을 높여보도록 하겠습니다.
함수 구조 설명
#include <stdio.h>
int printf(const char *format, ...);
#인자
const char *format
- 다음 입력하는 인자 값들이 어떤 포멧의 값인지 설명하는 문자열
...
- format 문자열을 입력한 후 포멧 개수에 맞게 해당하는 값들을 "," 로 구분하여 입력한다.
- 예) 포멧이 "%s %s" 인 경우, 문자열 포인터 값을 두개 입력해야한다. printf("%s %s", str1, str2)
#반환
int
- 출력에 성공한 문자 수
printf의 구조는 위와 같습니다. 자 여기서 한가지 원리를 파악해보겠습니다. format과 출력할 값을 반드시 같은 형식으로 매칭 해주어야 하는 이유가 있습니다.
C에서 문자열이 시작되어 끝을 파악하는 기준은 '/x0' 즉 NULL이 읽힐때까지 읽는 것입니다. 만약 NULL이 없으면 프로그램은 계속 끝까지 읽습니다. 그래서 반드시 중요하죠. "%s" 포멧은 입력할 값이 문자열이고 마지막 NULL이 정상적으로 입력된 값이어야 하는 포멧입니다.
"%d"는 정수의 값을 의미합니다. integer를 의미하고 일반적으로 4byte의 값입니다.
이처럼 포멧은 입력될 값의 크기를 미리 지정된 형식이기때문에 반드시! 반드시! 꼭! 포멧과 값의 크기를 동일하게 해주어야 합니다.
대표적인 포멧
포멧명 | 내용 |
%c | 1 Byte 값 또는 문자 출력 |
%s | 문자열 출력 |
%d | 정수 출력(부호 있음) |
%x | 16진수 소문자로 출력 |
%X | 16진수 대문자로 출력 |
%f | 소수 출력 |
%05d | 0을 5개 붙이고 정수출력 |
대표적인 포멧으로 위와 같이 사용하고 있습니다.
예제 목표
이번 예제의 목표는 printf의 출력 원리를 확실하게 이해하는 것입니다. NULL까지 출력하는 문자열 포멧, 정수를 표현하는 다양한 방법, character 값의 문자표현 방식과 정수 표현방식, 16진수 표현방법을 이해하는 것입니다.
코드작성
$ cd /tmp
$ mkdir c_printf_example; cd c_printf_example
$ vim c_printf_test.c
#include <stdio.h>
void example1() {
char *text = "this is text(const char *)";
char c = 'A';
printf("\n----------- 문자열 출력 예제 -----------\n");
printf("하드코딩 문자열 출력 : %s\n", "this is hard coding string");
printf("하드코딩 A문자 출력 : %c\n", 'A');
printf("char * 변수 문자열 출력 : %s\n", text);
printf("char 변수 1Byte 문자 값 출력 : %c\n", c);
printf("-------------------------------------------\n");
}
void example2() {
int integer1 = 300;
int minus1 = -454;
printf("\n----------- 정수 출력 예제 -----------\n");
printf("하드코딩 정수 출력 : %d\n", 155);
printf("int 변수 값 출력 : %d\n", integer1);
printf("음수 정수 값 출력 : %d\n", minus1);
printf("정수 값에 '0' 문자 4개 추가후 출력 : %04d\n", 120);
printf("정수 값에 '0' 문자 7개 추가후 출력 : %07d\n", 120);
printf("-------------------------------------------\n");
}
void example3() {
double double1 = 2355.123;
float float1 = 33.221;
printf("\n----------- 소수 출력 예제 -----------\n");
printf("double 소수 출력 : %f\n", double1);
printf("double 소수를 정수로 출력 : %d\n", double1);
printf("소수점 2자리까지 출력 : %.2f\n", double1);
printf("-------------------------------------------\n");
}
void example4() {
int test = 53;
char c = 'A';
printf("\n----------- 포인터 출력 예제 -----------\n");
printf("test 정수 변수의 포인터값 16진수 대문자 출력 : 0x%X\n", &test);
printf("test 정수 변수의 포인터값 16진수 소문자 출력 : 0x%X\n", &test);
printf("test 정수 변수의 포인터값 정수 출력 : %d\n", &test);
printf("A 알파벳의 값을 16진수 대문자 형식으로 출력 : 0x%X\n", c);
printf("A 알파벳의 값을 16진수 소문자 형식으로 출력 : 0x%x\n", c);
printf("정수 10 값을 16진수 값으로 출력 : 0x%X\n", 10);
printf("정수 10 값을 2자리의 16진수 값으로 출력 : 0x%02X\n", 10);
printf("-------------------------------------------\n");
}
void main() {
example1();
example2();
example3();
example4();
}
위의 예제는 문자열, 정수, 소수, 16진수들의 값을 출력하는 방법에 대한 예제입니다. character 변수는 1Byte의 값을 표시할 수 있습니다. 일반적으로 'A' 라는 단어는 아스키 코드로 0x41의 값입니다. 이를 정수의 값으로 표현하면 65가 됩니다. 따라서 16진수로도 출력할 수 있고 10진수의 값으로도 표시가 가능합니다.
이제 이 에제를 빌드하여 실행해보도록 하겠습니다.
실행
$ cd /tmp/c_printf_example
$ gcc -c c_printf_test.c -o c_printf_test.out
$ gcc -o c_printf_test c_printf_test.out
$ ./c_printf_test
결과
위와 같이 각 포멧에 대해 값들이 다양한 모습으로 출력되는 것을 알 수 있었습니다.