printf, fprintf, snprintf
printf, fprintf, sprintf와 snprintf에 대해 정리한 글
1. printf 함수
1. printf 함수란
- C 표준 라이브리에서 제공하는 출력함수
서식화된 문자열
을표준 출력(Standard Output, stdout)
에 보내는 함수- 프로그램 실행 중 결과를 출력하거나, 디버깅을 위해 변수 값이나 프로그램의 상태를 출력하는데 자주 사용함
2. 함수 정의
1
2
3
4
int printf(
const char *format,
[argument]...
);
format
: 출력할 텍스트의 형식을 지정하는 문자열- 가변 인자 : format 문자열에 포함된 형식 지정자에 따라 출력할 값을 지정함
- 성공 시 출력된 문자들의 개수를 리턴, 에러 발생 시 음수값을 리턴함
형식 태그
%[플래그(flag)][폭(width)][.정밀도(precision)][크기(length)]서식 문자(specifier)
flags
- flag : 부호 공백, 소수점, 8진 및 16진 접두부, 출력과 정렬 서식등을 결정
width
- width : 출력된 문자의 최소 개수 지정
.precision
- 문자열, 유효 자리수 또는 부동 소수점값의 뒷자리 수 등
prefix
- 인수의 크기 지정
서식지정자 종류
- type : 자료형에 따른 문자. 정수면 ‘d’, 문자면 ‘c’
3. 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
int main()
{
int num = 0;
// %n기능을 설정합니다. 0을 넣으면 안되게 하는거고 그 외의 값은 가능하게 합니다.
_set_printf_count_output(1);
printf("abcde%n\n", &num);
printf("%d\n", num);
printf("%-10d10\n", num);
printf("%+d\n", num);
printf("% d\n", num); // 공백은 1개까지
printf("%#d, %#o, %#x\n", num, num, num);
printf("%010d\n", num);
printf("%*d\n", 10, num);
printf("%.3d, %.3f, %.3g, %.3s\n", num, 0.1, 0.1, "test");
printf("%.*d, %.*f\n", 3, num, 3, 0.1);
return 0;
}
/*
abcde
5
5 10
+5
5
5, 05, 0x5
0000000005
5
005, 0.100, 0.1, tes
005, 0.100
*/
2. fprintf 함수
1. fprintf 함수란
- printf 함수와 유사하지만, file을 의미하는 f가 앞에 붙어있는 함수
- 지정된 파일 스트림에 서식화된 문자열을 출력하는 함수
- 전체적으로 printf 함수와 유사하지만, 출력 대상이 표준 출력이 아닌 특정 파일이나 스트림이라느 차이점이 있다
2. 함수 정의
1
2
3
#include <stdio.h> // C++ 에서는 <cstdio>
int fprintf(FILE* stream, const char* format, ...);
stream
: 작업을 수행할 스트림의FILE
객체format
: C 문자열로 스트림에 쓰여질 텍스트- 포함할 수 있는 형식 태그는 printf와 유사함
- 리턴값 : 출력된 문자의 개수를 반환, 실패 시 음수 반환
%[플래그(flag)][폭(width)][.정밀도][크기(length)]서식 문자(specifier)
3. 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
int main() {
FILE* fp = fopen("output.txt", "w");
int integer = 123;
char character = 'c';
char string[] = "hello, world";
int* pointer = &integer;
double pi = 3.141592;
fprintf(fp, "integer : (decimal) %d (octal) %o \n", integer, integer);
fprintf(fp, "character : %c \n", character);
fprintf(fp, "string : %s \n", string);
fprintf(fp, "pointer addr : %p \n", pointer);
fprintf(fp, "floating point : %e // %f \n", pi, pi);
fprintf(fp, "percent symbol : %% \n");
fclose(); // 파일을 썼으면 꼭 닫을 것
return 0;
}
/*
생성된 파일은 output.txt 파일
interger : (decimal) 123 (octal) 173
character : c
string : hello, world
pointer addr : 001CFD1C
floating point : 3.141592e+000 // 3.141592
percent symbol : %
이 저장된다
*/
3. sprintf, snprintf
1. sprintf 함수란
서식화된 문자열
을string
에 출력하는 함수- printf 와 유사한 방식으로 동작하지만, 출력 대상이 콘솔이나 파일이 아닌 문자열
- 버퍼의 크기를 넘지 않도록 안전하게 데이터를 출력할 수 있음
- 주로 문자열을 조작하거나, 특정 형식의 데이터를 버퍼에 저장해야 할 때 사용
- 특히 버퍼 오버플로우를 방지해야 하는 상황에서 유용
- 지정된 크기 만큼 데이터를 저장하고, 초과하는 부분은 잘라냄
- 패킷 통신을 하거나, buffer에 원하는 문자열을 삽입, 이어붙이기 할때 자주 사용
2. 함수 정의
1
2
3
#include <stdio.h> // C++ 에서는 <cstdio>
int sprintf(char* str, const char* format, ...);
str
: 데이터를 저장할 버퍼. 출력된 문자열은 이 버퍼에 저장됨format
: C 문자열로, 스트림에 쓰여질 텍스트- printf, fprintf 함수와 마찬가지로 형식 태그를 포함 할 수 있다
- 출력된 문자열의 길이를 반환
%[플래그(flag)][폭(width)][.정밀도][크기(length)]서식 문자(specifier)
3. 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* 사용 예 */
#include <stdio.h>
int main() {
FILE *fp = fopen("output.txt", "w");
char buffer[100];
int i = 123;
int j = -123;
double f = 3.141592;
// 버퍼에 입력하고, 이를 파일에 입력한다
sprintf(buffer, "폭 맞추기 \n");
fputs(buffer, fp);
sprintf(buffer, "i : %6d \n", i);
fputs(buffer, fp);
sprintf(buffer, "i : %7d \n", i);
fputs(buffer, fp);
sprintf(buffer, "i : %2d \n\n", i);
fputs(buffer, fp);
sprintf(buffer, "왼쪽 정렬 \n");
fputs(buffer, fp);
sprintf(buffer, "i : %5d끝 \n", i);
fputs(buffer, fp);
sprintf(buffer, "오른쪽 정렬 \n");
fputs(buffer, fp);
sprintf(buffer, "i : %-5d끝 \n\n", i);
fputs(buffer, fp);
sprintf(buffer, "# 문자의 사용 \n");
fputs(buffer, fp);
sprintf(buffer, "i : %#x \n", i);
fputs(buffer, fp);
sprintf(buffer, "i : %#X \n\n", i);
fputs(buffer, fp);
sprintf(buffer, "부호 붙이기 \n");
fputs(buffer, fp);
sprintf(buffer, "%+d, %+d \n", i, j);
fputs(buffer, fp);
fclose();
return 0;
}
4. snprintf 함수와 차이점
sprintf
- 버퍼 크기를 제어하지 않음
- 버퍼의 크기와 상관 없이, 지정된 형식과 데이터를 버퍼에 그대로 기록
- 버퍼의 크기가 충분히 크지 않으면, 메모리 오버플로우가 발생할 수 있음
snprintf
- 버퍼 크기를 제어
- 두 번째 인자로 버퍼의 최대 크기를 지정하여, 이 크기를 초과하지 않도록 데이터를 저장함
- 버퍼에 출력할 내용이 지정된 크기를 넘으면, 남는 부분을 잘라내고, 버퍼의 끝에 널 문자를 추가함
- 출력하려고 시도한 전체 문자열의 길이를 반환
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main() {
char buffer[10];
int a = 12345;
// 버퍼에 데이터를 저장, 하지만 버퍼 크기 제한 없이 사용
sprintf(buffer, "Value: %d", a);
printf("%s\n", buffer);
// 버퍼 크기가 작으면 메모리 오버플로우 발생 가능
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main() {
char buffer[10];
int a = 12345;
// 버퍼 크기를 제한하여 데이터를 저장
snprintf(buffer, sizeof(buffer), "Value: %d", a);
printf("%s\n", buffer);
// 버퍼 크기를 초과한 경우, 초과된 부분은 잘림
return 0;
}
sprintf는 더 빠르고 간단하지만, 안정성에 문제가 있으므로 사용에 주의가 필요함
snrpintf 가 더 안전하며, 입력 크기나 버퍼가 가변적인 상황에서 추천
출처
https://cplusplus.com/reference/cstdio/printf/?kw=printf
https://blog.naver.com/dgw0103/222130590653 https://haruhiism.tistory.com/8
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.