포스트

printf, fprintf, snprintf

printf, fprintf, sprintf와 snprintf에 대해 정리한 글

1. printf 함수


image

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

printf_flag

  • flag : 부호 공백, 소수점, 8진 및 16진 접두부, 출력과 정렬 서식등을 결정
    width

    bandicam_2016-12-21_23-16-35-806

  • width : 출력된 문자의 최소 개수 지정
    .precision

    bandicam_2016-12-21_23-27-43-115

  • 문자열, 유효 자리수 또는 부동 소수점값의 뒷자리 수 등
    prefix
  • 인수의 크기 지정
    서식지정자 종류

    printf_format

  • 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 함수


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

image


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 함수와 차이점

sprintfvssnprintf

  • 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

https://modoocode.com/64

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.