본문 바로가기

별걸다하는 IT/프로그래밍언어

[C/C++언어]sprintf 함수와 fprintf 함수 사용법, 원하는 출력을 다양한 서식으로 구성하고 문자열이나 파일로 저장하기. stdio.h 라이브러리

반응형

[C/C++ 프로그래밍 강좌 목차]

안녕하세요 주인장 양햄찌입니다.

오늘은 마치 생긴건 기본적인 printf 랑 비슷하게 생긴,

정말정말 유용하게 많이 쓰이는 printf 친척쯤 되는 sprintf와 fprintf 함수를 들고 왔어요.

 

printf는 서식지정이 가능한 출력 함수죠?! 얘네들은 printf의 서식표현 방법을 기본적으로 따라가기 때문에 printf를 사용하실 줄 알아야 합니다. 

%d, %s, %c, %e, %f 등의 서식연사자들,, 그리고 0, #, + 등의 플래그들..

혹 해당 함수의 다양한 사용법을 다시 확인하고 싶은 방문자들은 아래 포스팅을 참고 바라요.

jhnyang.tistory.com/159

 

[C, Java] Hello World 출력, printf 출력 함수 서식과 포맷, 소수점 자리 지정법, 채우기

[ C/ C++ / Java] 프로그래밍 기초 목차편! 안녕하세요~! 프로그래밍 기초편 포스팅을 시작해봅시다 ㅎㅎ 저번시간에 개발할 수 있는 개발환경을 다 설치했으니 간단한 프로그램을 작성해봐야겠죠 �

jhnyang.tistory.com

printf, sprintf, fprintf 함수 헤더

#include <cstdio> //C++
#include <stdio.h> //C

세 함수는 모두 같은 라이브러리에 속해있습니다. stdio.h나 cstdio 라이브러리를 인클루드 시켜주면 사용 가능해요.

해당 헤더에 속하는 printf 비스므리하게 생긴 애들 중 vprintf, vsprintf, vsnprintf 요런 애들도 있는데 요 함수들은 가변인자때 사용되는 출력함수예요. 가변인자 사용법에 대해 공부하고 싶으신 분은 아래 포스팅을 참고해주세요.

sprintf 알아보기

printf는 여러가지 서식들을 조합해서 출력을 해줘요. 영어+숫자+헥사값 등등 포맷연산자에 포맷만 지정해주면 다양한 값을 한 번에 출력을 해주죠! 근데 출력말고, 개발하다보면 이를 변수에다가 저장해서 활용하고 싶을 때가 많습니다.

그렇습니다~~! sprintf는 출력하는 결과 값을 변수에 저장하게 해주는 기능이 있어요. 저는 그래서 'string = printf'의 줄임말이 sprintf이다 라고 생각을 하고 있습니다. printf가 출력하는 함수라면 sprintf는 출력값을 문자열에 저장하는 함수인거죠ㅎㅎ. 

 

해당 함수로 인해 문자열 사이에 특정 값을 끼어넣는다던가,, 문자열+숫자 조합을 쉽게 컨트롤한다던가,, 

마스킹처리와 같은 특정 포맷을 만든다던가,,  다양하게 활용할 수 있습니다. 

sprintf 프로토타입

int sprintf ( char * str, const char * format, ... );

리턴 값

문자열 변수 str에 쓰기가 성공한 문자 개수가 반환된다. 

인자 값

char* str : 출력값을 저장할 문자열. 

const char* format : 서식 문자열 

... : 서식 연산자에 치환할 값들 

(2번째 인자부터는 printf 출력함수 사용 방법과 동일합니다)

sprintf 기본적인 사용 예시 

가장 빠르게 익히는 법은 사용예시를 보는 거죠. 

#include <stdio.h>
#include <string.h>
int main()
{
	char msg1[50] = { 0x00, }, msg2[50] = { 0x00, }, msg3[50] = { 0x00, };
	int y = 2020;  int m = 8; int d = 30;

	sprintf(msg1, "hello");  //msg1에 단순 문자열 저장.
	printf("%s\n", msg1);
	
	sprintf(msg2, "%s world!", msg1); //msg2에 "msg1 문자열 내용 + world!"
	printf("%s\n", msg2);
	
	sprintf(msg3, "%s%.6s 오늘은 %d%d%d", msg1, msg2 + strlen(msg1), y, m, d); //msg3에 문자열과 숫자 조합해서 저장하기
	printf("%s\n", msg3);
	return 0;
}

이렇게 내가 넣고 싶은 정보들을 같이 조합하여 문자열로 만들어 저장할 수 있습니다.

출력 값

리턴 값까지 확인해보기!

#include <stdio.h>
#include <string.h>
int main()
{
	char msg1[50] = { 0x00, }, msg2[50] = { 0x00, }, msg3[50] = { 0x00, };
	int y = 2020;  int m = 8; int d = 30;

	int len = sprintf(msg1, "hello");  //msg1에 단순 문자열 저장.
	printf("%d %d :%s \n", len, strlen(msg1), msg1);

	len = sprintf(msg2, "%s world!", msg1); //msg2에 "msg1 문자열 내용 + world!"
	printf("%d %d :%s \n", len, strlen(msg2), msg2);

	//msg3에 문자열과 숫자 조합해서 저장하기
	len = sprintf(msg3, "%s%.6s 오늘은 %d%d%d", msg1, msg2 + strlen(msg1), y, m, d); 
	printf("%d %d :%s \n", len, strlen(msg3), msg3);
	return 0;
}

strlen함수는 널문자가 나타나기까지 길이를 카운트하죠. sprintf함수로 만든 msg1 문자열의 strlen값이 5라는 것은, sprintf로 문자열을 만들시 마지막에 널문자를 자동적으로 삽입해준다는 의미가 됩니다.

★ sprintf 함수를 이용하여 문자열을 만들시 마지막 널문자도 같이 삽입이 된다!

성공적으로 write한 값과 strlen 값이 동일한 것을 확인할 수 있어요. 이 값은 결국 널문자를 제외한 문자열의 길이를 의미하죠 :) 

 

[예시, 절대경로포함한 파일명 만들기]

#pragma warning(disable:4996)
#include <stdio.h>
#define FILE_PATH "/home/ubuntu/"
int main()
{
	const char* fname = "hello.txt";
	char file[100] = { 0x00, };
	sprintf(file, "%s%s", FILE_PATH, fname); //절대경로를 가진 파일명 만들기
	printf("full path: %s", file);
	return 0;
}

보통 파일 절대 경로라던가, 날짜를 조합한다던가 이럴 경우 sprintf가 유용하게 쓰여요. 

fprintf 알아보기

fprintf 함수는 sprintf 함수와 매~~우 유사한데 출력 값을 쓰는(write하는) 공간이 다른 것 뿐이예요.

sprintf는 문자열에 쓰는 거라면 fprintf는 출력을 파일에다가 쓰는 거죠!

그래서 sprintf 첫번째 인자에 문자열이 왔다면, fprintf 첫번째 인자에는 파일구조체 포인터가 오는거랍니당.

fprintf 프로토타입

int fprintf (FILE* stream, const char* format, ...);

리턴 값

파일에 성공적으로 write한 문자의 개수

인자 값

FILE* stream : write할 파일 정보를 담고 있는 파일객체

const char* format : 서식 문자열

... : 서식 연산자에 치환할 값들 

(2번째 인자부터는 printf 출력함수 사용 방법과 동일합니다)

fprintf 기본적인 사용 예시 

hello.txt 파일에다가 단순히 hello world! 출력해보기!

#include <stdio.h>
#include <string.h>
int main()
{
	FILE* fpw = fopen("hello.txt", "w");
	fprintf(fpw, "hello world!");
	fclose(fpw);
	return 0;
}

단순히 hello.txt 파일을 w쓰기 모드로 연 다음에 해당 파일에다가 hello world!를 출력해줬어요.

짠 수행해보면 잘 쓰여진 것을 확인하실 수 있습니다. 

 

[fprintf는 버퍼에다가 값을 쓴다]

파일입출력 가장 중요한 내용 중 하나는 버퍼죠 

1. #include <stdio.h>
2. int main()
3. {
4. 	FILE* fpw = fopen("hello.txt", "w");
5. 	FILE* fpr = fopen("hello.txt", "r");
6. 	char msg[100];
	
7. 	fprintf(fpw, "hello world");
8. 	fgets(msg, 10, fpr);
9. 	printf("%s", msg);

10. 	fclose(fpr);
11. 	fclose(fpw);
12. 	return 0;
13. }

위 코드를 돌려보면 쓰레기 값이 나오는데요, 

왜 이런 값이 나왔을까요?? 

우리는 7번라인에서 파일에 'hello world'를 쓰고 8번라인에서 fgets함수로 fprintf함수로부터 쓰여진 hello world 문자열에서 10글자를 읽어들일 것이라고 예측하는데요.

사실 7번 라인이 끝났을 때 실질적으로 파일에 쓰여진 것은 아니기 때문에 해당 파일은 빈 파일로 남아있습니다.

따라서 8번 라인에서 빈 파일을 읽으려니까 쓰레기 값이 출력된거예요!

 

fputs 함수와 마찬가지로 fprintf는 파일에다가 바로 write하는 것이 아니라 버퍼에다가 적습니다. 그리고 fclose함수를 만나면 버퍼에 있던 문자열이 파일에 써지게 돼요. 만약 그 전에 파일에 써서 위와 같은 코드를 정상동작 시키려면 버퍼를 파일에 내보내, 즉 버퍼를 비우는 함수를 사용해야 합니다. 

#include <stdio.h>
int main()
{
	FILE* fpw = fopen("hello.txt", "w");
	FILE* fpr = fopen("hello.txt", "r");
	char msg[100];
	
	fprintf(fpw, "hello world");
	fflush(fpw); //버퍼 비우기 
	fgets(msg, 10, fpr);
	printf("%s", msg);

	fclose(fpr);
	fclose(fpw);
	return 0;
}

fflush를 통해 버퍼에 있던 값을 파일로 내보내 버퍼를 비워줬어요.

수행해보면 "hello world"에서 10글자에 해당하는 "hello wor"을 잘 출력해준 것을 확인하실 수 있어요.

 

오늘은 간단하게 sprintf, fprintf 함수에 대해 알아보았어요. ㅎㅎ

도움이 되셨다면 공감 어떠신가요?! 다음에 또 봐요 :)

반응형