1. 서식문자열에서 서식태그와 가변인자로 넣어주는 개수가 일치하지 않을 때
(printf와 ft_printf 모두 동일하게 서식문자와 서식태그에 대응 값만 출력되고 나머지는 무시한다.)
gcc -Wall -Wextra -Werror 에서 에러로 표현해주기때문에, 이러한 경우는 배제하기로한다.
2. 모든 정보는 결국 bit로 저장된다. -> signed unsigned도 값이 다르게 보여도 실제 bit값은 동일하다.
읽는 byte의 범위가 다르거나, 읽어서 해석하는 방법이 다를 뿐이다.
int 는 ft_itoa로 해결가능하지만, unsigned int 는 다른 방법으로 해결해야한다.
->ft_utoa.c 새로 만듦
3. flag처리
정확도 | s |
넓이(width) | cspdiuxX%(all) |
넓이에 0채움 | pdiuxX%(문자 관련 제외하고 all) |
좌측정렬 (-) | cspdiuxX%(all) |
- cspdiuxX에서는 모두 '-' 와 '0'이 같이 쓰이는 상황을 에러처리하고, %에서도 출력값에 0이 들어가지않는다. 즉, '-' 와 '0'이 같이 쓰이는 상황에 대해서는 '-'만 고려해주기로 한다.
- '-'와 '0' 플래그는 중복해서 많이 사용되도 error를 띄우지 않는다. 즉, 하나만 있다면 관련 플래그 처리를 해준다.
printf 빌드업 계획
1. 서식문자열을 서식태그로 나누고, 이를 출력하기
2. 서식태그에 가변인자값이 대응되도록 va_arg(ap, char*)를 이용하기
---flag가 여러값이 들어가는 것( "%00s" , "%--d")에 대해서는 잘된다고 봐야돼(debugging 필요가 없다)---
3. 실제로 다양한 경우에 대해서 단일 cspdiuxX%값에 대해서 ft_printf가 printf와 동일하게 작동하는지 확인
4. 단일 cspdiuxX%에 대해서 flag 적용 실시
내가 짜는 코드의 메커니즘
1. 서식 문자열에서 표현되는 피상적인 flag의 종류 및 개수를 t_flag 구조체의 멤버에 담는다.
2. t_flag 구조체의 데이터를 바탕으로 출력해야하는 정보를 t_flag 구조체의 "d_* " 멤버에 담는다(va_arg 및 서식문자열에 있는 숫자를 근거로)
3. 필요한 경우 va_arg()로 값을 가져오고, '-' flag에 유의하면서, t_flag구조체에 출력해야할 정보가 담긴 멤버를 바탕으로 값을 출력한다.
printf의 return 값을 얻기위한 두가지 방법
1. 출력하기전에 buffer에 담는다. -> buffer의 길이를 계산함으로써 출력문자열의 길이를 return하고, buffer를 출력할 수 있다.
2. buffer에 담지 않고, 갯수를 세어주는 변수를 만들어서 숫자를 더해서 계산한다.✅
buffer에 담는다는 것이 얼마나 들어올지모르는 길이에 대해, 동적할당하는 것은 매번 어려운 이슈이기 때문이기 때문에, buffer의 길이를 세면 된다는 비교적 깔끔한 마무리가 가지는 장점에도 불구하고, 변수에 숫자를 더해서 계산해주기로 한다.
정밀도에 관해서, 마이너스값이 명시될 수 없지만, *로 치환되서 들어올 수 있다.
일반적인 관계를 정수 서식문자 d로 표현하면, %.0d == %.d 이고, printf("%.*d, -12", 123) == printf("%d", 123) 즉, 다시말하면 -값이 정밀도에 들어가게되면 그냥 무시한다.
따라서 정밀도에 대한 값은 -1, 0, 양수로 구분한다.
width에 *로 들어갈 때, 음수가 들어가면 -를 - flag 좌측정렬로 생각한다. 하지만 014 -014 에 대해서는 0 flag가 적용되지않는다.
1. c
flag 0(x)
precision(x)
printf("!%10c!\n",'A');
printf("!%*c!\n",23, 'A');
printf("!%-10c!\n",'A');
이런꼴 외에는 전부 원형 그대로 출력
2. s
va_arg(ap, char *)로 들어온 string의 내용에서 정확도 길이만큼 짤린다. 정확도의 크기가 더 크면 상관 없음
정확도의 크기로 짤린 문자열에 대해서 padding을 시켜줌
-가 있으면 먼저 출력해줌
0 flag는 undefined behavior
printf("*.*%s);
1. width에 -값이 들어오면, -는 좌측정렬로 생각해주고, 부호를 뺀 부분을 max_width로 생각한다.
2. precision에 -값이 들어오면, 무시한다.
3. p
flag 0 : undefined -> 무시
precision : undefined -> 무시 (=별표가 두개이상 들어갈 수 없다고 생각함)
width의 크기와 -값만 처리해주었음,
4. x , X
x는 unsigned int 10진법을 16진법으로 표현하는 것이다.
flag 0 : '-' flag랑 같이 사용하면 무시당함
precision : 짤리는 것이 아니라 , 앞부분이 0으로 채워짐( flag '0'처럼
flag - : 좌측정렬
if (flag.d_zero == 1 && flag.d_left == 1)
flag.d_zero = 0;
으로 printf("%-023x", 0x23); 과 같은 경우 없애줌. ==> 결론적으로 -만 있거나, 0만 있다!
left로 먼저 출력하기전에 먼저 precision의 갯수를 생각해주어야 한다.
Code example
1. 0 flag vs .precision 우선순위
0으로 다 채워지지않고 precision의 갯수만큼 채워진다.
2. 최대너비가 정확도보다 작아도 정확도의 크기만큼 출력해준다.
printf("%023.12x\n",b);
000000000422
printf("%-4.8x\n",b);
00000422
printf("%-11.8x\n",b);
00000422
3.
printf("--------길이 및 채워넣기-------\n");
c = 0x43215;
printf("%1.2x\n",c);
printf("%10.2x\n",c);
printf("%10.12x\n",c);
printf("%14.12x\n",c);
//결과
43215
43215
000000043215
000000043215
4. printf(%x)의 크기에 대한 테스트케이스
unsigned int e;
e = 0x12345;//5개
printf("|너비|정확도|길이|\n");
printf("| 9 | 7 | 5 | :%9.7x\n",e);
printf("| 9 | 3 | 5 | :%9.3x\n",e);
printf("| 3 | 9 | 5 | :%3.9x\n",e);
printf("| 7 | 9 | 5 | :%7.9x\n",e);
printf("| 4 | 3 | 5 | :%4.3x\n",e);
printf("| 3 | 4 | 5 | :%3.4x\n",e);
//결과 값
|너비|정확도|길이|
| 9 | 7 | 5 | : 0012345
| 9 | 3 | 5 | : 12345
| 3 | 9 | 5 | :000012345
| 7 | 9 | 5 | :000012345
| 4 | 3 | 5 | :12345
| 3 | 4 | 5 | :12345
5. % 서식문자에 대한 처리
precision이 에러가 뜨진 않지면, 영향이 아예 없음
-> 별표로 대응될 때, 갯수와 위치에 맞게 대응시켜주어서 다음 별표로 대응되는 값에 대해서 에러가 먹지 않게 하기!
0, - , width 적용
6. %d(=i)처리
'0'은 '-'에 의해 무시된다. 라는 error가 있다.
d와 i에서 ft_itoa로 변환하면 안되는 이유가 "-000000042"가 "0000000-42"로 출력되기때문에, 양수로 바꾼다음 ft_utoa로 udi 모두 통일 시켰다
s와 마찬가지?
1. width에 -값이 들어오면, -는 좌측정렬로 생각해주고, 부호를 뺀 부분을 max_width로 생각한다.
2. precision에 -값이 들어오면, 무시한다.
1. 정밀도가 5이고 -7을 넣는다면 -00007이 됨 '-'는 별개로 생각해야함.
2. 현재 내 코드에서 음수의 숫자의 크기는 하나 작게 판단 ex) -7의 길이는 1.
그래서, width_most로 갈때, 여기서 출력해주는 정수가 음수 일때, widthspace를 하나 줄여주는 조건문이 필요하다.
printf("%12.*d\n",-3, -12);
printf("%12d\n", -12);
printf("%012.*d\n",-3, -12);
printf("%012d\n", -12);
정밀도에 -값을 직접적으로 넣어주는 것은 error에 걸리지만, *로 대체할 순 있다. 이때는 그냥 무시하면 된다.
출력의 세가지 경우와 printf의 return value
1.width가 최대 값인 경우 -> 음수인 경우 flag->d_width--;
2.정수가 iota된 문자열의 크기가 최대값인 경우 -> 음수인 경우 ft_strlen(utoa)++;
3.정밀도가 최대인 경우 -> 음수인 경우 flag->d_precision++;
'42cursus > printf' 카테고리의 다른 글
printf flowchart (0) | 2020.07.25 |
---|---|
printf 자료조사 (0) | 2020.07.06 |