[ft_printf](6)길이옵션[l,h], 서식지정자(c, s)출력
이번 포스트는 (ft_printf)길이옵션[l,h], 서식지정자(c, s)출력 조건문 구현에 관한 내용입니다.
1️⃣ 자료형 길이옵션 추가하기[ h, hh, l, ll ]
% + length + 자료형 | data type |
---|---|
%hhi, %hhd | signed char |
%hi, %hd | signed short |
%li, %ld | signed long int |
%lli, %lld | signed long long int |
(1) set_form함수에 길이옵션함수 추가
- 서식지정자의 길이옵션을 관리하는 함수set_lenth를 form_spec함수[서식지정자를 만나면 출력하는 함수]바로 앞에 위치시켜 서식지정자를 체크하기전에 길이옵션을 체크하도록 합니다.
< set_form함수 >
void set_form(va_list ap, const char **format, int *len)
{
t_flag fg = { 0, };
set_flag(ap, &fg, format);
set_lenth(&fg, format, len);
form_spec(ap, *format, &fg, len);
(*format)++;
}
(2) 길이옵션에 사용될 변수 구조체에 추가
- 길이옵션을 사용하게 되면 다양한 자료형을 다룰 수 있는 변수가 필요합니다.
- 또한 ' l ', ' h '의 개수를 기억하는 변수가 필요합니다.
< t_flag구조체에 추가된 요소 >
typedef struct flags
{
/* 기존 요소 생략 */
int data_length;
char c;
short s;
long long int lli;
unsigned long long int ulli;
} t_flag;
(3) set_lenth함수 구현[ l , h 의 개수를 새주는 함수]
< set_lenth함수 >
void set_lenth(t_flag *fg, const char **format, int *len)
{
while (**format == 'l' || **format == 'h')
{
if (**format == 'l')
fg->data_length++;
if (**format == 'h')
fg->data_length--;
(*format)++;
}
}
(4) print_di함수에 길이옵션추가[ d, i자료형만을 출력하는 함수]
va_arg
매크로 함수로 받아오는long long int temp
변수를 길이 옵션에 따라 다양한 자료형으로 받아올 수 있게 세분화시켰습니다.[ t_flag 구조체의 새로운 요소를 사용]- 버퍼오버플로우의 경우로 들어오는 경우가 있기 때문에 매개변수 포인터를 적절한 자료형으로 받아와야 합니다.
< 버퍼오버플로우 단순예 >
printf("%hd\n", 123456);
printf("%hhd\n", 1234);
-7616
-46
va_arg(ap, char)
를va_arg(ap, short)
의 방법으로char형
과short형
을 받을 수 있을까 생각할 수 있지만 사용하지 못합니다.[ 예전 표준상의 문제로 가변 인자 목록의 기본 자료형 인자들이 정수형은int
로 실수형은double
승격됬습니다. ]- 그렇기 때문에
va_arg(ap, int)
를char형
,short형
의 변수로 직접 받아오도록 했습니다.
< 길이옵션 조건문 >
if (fg->data_length == -2) // hhi, hhd
{
fg->c = va_arg(ap, int);
fg->lli = fg->c;
}
if (fg->data_length == -1) // hi, hd
{
fg->s = va_arg(ap, int);
fg->lli = fg->s;
}
if (fg->data_length == 0) // i, d
fg->lli = va_arg(ap, int);
else if (fg->data_length == 1) // li, ld
fg->lli = va_arg(ap, long int);
else if (fg->data_length == 2) // lli, lld
fg->lli = va_arg(ap, long long int);
if (fg->lli < 0)
{
fg->ulli = fg->lli * (-1);
fg->minus = 1;
cnt++;
}
else
fg->ulli = fg->lli;
2️⃣ 문자형(' c ')서식지정자 출력함수 구현
(1) 문자형c 서식규칙
printf("%c끝\n", 't');
printf("%3c끝\n", 't');
printf("%-3c끝\n", 't');
printf("%*c끝\n",3,'t');
printf("% c\n", 't'); // 컴파일 오류
printf("%03c끝\n", 't'); // 컴파일 오류
printf("%3.4c끝\n", 't'); // 컴파일 오류
t끝
t끝
t 끝
t끝
- 너비 옵션을 사용이 가능합니다.
- ' - '플래그(왼쪽정렬) 사용이 가능합니다.
- ' * '옵션 사용이 가능합니다.
(2) 문자형(' c ')서식지정자 출력함수 구현
< print_c함수 >
int print_c(va_list ap, t_flag *fg)
{
int cnt;
fg->c = va_arg(ap, int);
cnt = 0;
while ((fg->left != 1) && (fg->padding_front - 1 > 0)) // 앞쪽너비
{
write(1, " ", 1);
cnt++;
fg->padding_front--;
}
write(1, &(fg->c), 1); // 본문자출력
cnt++;
while ((fg->left == 1) && (fg->padding_front - 1 > 0)) // 뒤쪽너비
{
write(1, " ", 1);
cnt++;
fg->padding_front--;
}
return (cnt);
}
3️⃣ 문장형(' s ')서식지정자 출력함수 구현
(1) 문자형s 서식규칙
printf("%s끝\n", "hello");
printf("%7s끝\n", "hello");
printf("%-7s끝\n", "hello");
printf("%.3s끝\n", "hello");
printf("%.7s끝\n", "hello");
printf("%*.*s끝\n", 7, 3, "hello");
printf("% s끝\n", "hello"); // 컴파일 오류
printf("%0s끝\n", "hello"); // 컴파일 오류
hello끝
hello끝
hello 끝
hel끝
hello끝
hel끝
- 너비 옵션을 사용이 가능합니다.
- ' - '플래그(왼쪽정렬) 사용이 가능합니다.
- ' * . * '옵션 사용이 가능합니다.
- ' . '(정밀도)는 문자열 최대출력크기 입니다.
(2) 문자열(' s ')서식지정자 출력함수 구현
< print_s함수 >
int print_s(va_list ap, t_flag *fg)
{
int cnt; // 총 출력할 문장길이
int cnt2; // 실제 출력할 문자열길이
char* temp;
temp = va_arg(ap, char*);
cnt2 = ft_strlen(temp);
if (fg->point == 1) // [. ]정밀도 옵션이 있을시
cnt2 = (cnt2 > fg->padding_back) ? fg->padding_back : cnt2;
fg->padding_front -= cnt2;
cnt = cnt2;
while ((fg->left != 1) && (fg->padding_front > 0)) // 앞쪽너비
{
write(1, " ", 1);
cnt++;
fg->padding_front--;
}
write(1, temp, cnt2); // 실제 문자열 출력
while ((fg->left == 1) && (fg->padding_front > 0)) // 뒤쪽너비
{
write(1, " ", 1);
cnt++;
fg->padding_front--;
}
return (cnt);
}