printf()
함수란?
printf()
함수는 C 프로그래밍에서 데이터를 출력하기 위해 가장 널리 사용되는 함수이다. 형식 지정자를 활용하여 다양한 데이터 타입을 출력할 수 있으며, 콘솔 기반 출력의 기본 도구이다.
형식 문자열과 형식 지정자
printf()
함수는 형식 문자열을 입력받아 처리한다. 형식 문자열을 일반 텍스트와 형식 지정자로 구성되며, 형식 지정자는 %d
, %f
, %s
등으로 데이터 타입을 정의한다.
가변 인자의 처리 방법
printf()
는 가변 인자를 처리하기 위해 stdarg.h
에 정의된 va_list
, va_start
, va_arg
, va_end
를 사용한다. 이를 통해 함수 호출 시 전달된 인자들을 순차적으로 읽어 형식 지정자에 따라 처리한다.
stdarg.h
의 사용법
가변 인자를 처리하기 위해 반드시 알아야 할 라이브러리이다. va_list
를 선언하고, va_start
로 초기화한 뒤 va_arg
로 각 인자를 읽어보는 방식이다.
문자열 처리와 출력 스트림 개념
문자열을 구성하고 이를 출력 스트림에 전달하는 과정을 이해해야 한다. 저수준 출력 함수인 putchar()
를 활용해 출력 스트림을 관리할 수 있다.
함수 구현
Step 1 : 기본 출력 함수 만들기
가장 간단한 형태로 문자열을 출력하는 함수부터 시작해 보겠다.
- 문자열을 하나씩 읽어 출력하는 방식으로 작동한다.
putchar()
를 활용해 각 문자를 출력한다.
#include <stdio.h>
void my_printf(const char *str) {
while(*str) { // 가리키는 문자가 NULL이 아닐 때까지
putchar(*str); // 출력
str++; // 다음 문자로 이동
}
}
int main(void) {
my_printf("Hello, World!\n");
return 0;
}
이 함수는 문자열만 출력할 수 있고, 서식 지정(format specifiers, e.g., %d
, %s
)을 지원하지 않는다.
Step 2 : 포맷 처리 없이 숫자 출력
printf()
는 숫자도 출력할 수 있다. 이를 위해 숫자를 문자열로 변환하는 기능을 추가한다.
- 음수 처리 및 재귀적인 숫자 출력 로직을 작성한다.
- 각 자리 숫자를
putchar()
를 통해 출력한다.
#include <stdio.h>
void print_number(int num) {
if(num < 0) {
putchar('-');
num = -num;
}
if(num / 10) {
print_number(num / 10);
}
putchar('0' + (num % 10));
}
int main(void) {
print_number(12345);
putchar('\n');
print_number(-6789);
return 0;
}
음수인 경우 -
을 출력하고 양수로 변환한 후 숫자를 출력한다.
예를 들어, 12345
를 처리할 때
print_number(1234)
->print_number(123)
->print_number(12)
->print_number(1)
로 재귀 호출된다.
Step 3 : 간단한 %d 포맷 처리
숫자와 문자열 출력을 구분하여 처리하는 간단하나 버전을 구현한다.
stdarg.h
의va_list
를 사용해 가변 인자를 읽어온다.%d
형식 지정자를 만나면 정수를 출력한다.
#include <stdio.h>
#include <stdarg.h>
void print_number(int num) {
if(num < 0) {
putchar('-');
num = -num;
}
if(num / 10) {
print_number(num / 10);
}
putchar('0' + (num % 10));
}
void my_printf(const char *format, ...) {
va_list args;
va_start(args, format);
while(*format) {
if(*format == '%' && *(format + 1) == 'd') {
int num = va_arg(args, int); // 가변 인자에서 정수 가져오기
print_number(num);
format += 2;
} else {
putchar(*format);
format++;
}
}
va_end(args);
}
int main(void) {
my_printf("Number : %d\n", 42);
return 0;
}
format 문자열을 한 문자씩 읽어 처리하고 현재 문자가 '%'
이고 다음 문자(*(format + 1)
)가 'd'
라면
va_arg(args, int)
를 사용해 가변 인자 리스트에서 정수를 가져온다.print_number
를 호출해 해당 정수를 출력한다.format += 2
로 포맷 문자열에서%d
를 건너뛴다.
%d
가 아닌 일반 문자는 그대로 출력하고 *format
이 NULL이면 종료한다.
Step 4 : 다중 포맷 처리
이제 문자열 포맷인 '%s'를 추가한다.
void my_printf(const char *format, ...) {
va_list args;
va_start(args, format);
while (*format) {
if (*format == '%' && *(format + 1) == 'd') {
int num = va_arg(args, int);
print_number(num);
format += 2;
} else if (*format == '%' && *(format + 1) == 's') {
const char *str = va_arg(args, const char *);
my_printf(str);
format += 2;
} else {
putchar(*format);
format++;
}
}
va_end(args);
}
현재 문자가 '%'
이고 다음 문자가 's'
인 경우
va_arg(args, const char *)
로 가변 인자에서 문자열 포인터를 가져온다.my_printf(str)
를 호출하여 해당 문자열을 출력한다.- 문자열을 출력하기 위해
my_printf
자신을 재귀 호출한다.
- 문자열을 출력하기 위해
format += 2
로%s
를 건너뛴다.
오류 처리 및 예외 상황
기본적인 틀을 이렇게 잡고 잘못된 형식 문자열이나 부족한 인자 개수에 대해 오류를 감지하고 적절히 처리해야 한다.
'C언어' 카테고리의 다른 글
[C언어] 개행 문자 (0) | 2024.12.13 |
---|---|
[C언어] qsort() 함수란? (0) | 2024.11.18 |
srand() 함수란? (0) | 2024.11.15 |
[C언어] OOP 공부 (2) (1) | 2024.11.13 |
티스토리 기본모드 수식 삽입 (2) | 2024.11.13 |