ft_printf의 기록들

정하나둘·2022년 12월 1일
0

ft_printf

목록 보기
1/1

해당 벨로그 주인장은 보너스를 구현하지 않았다. 나중에 해볼 의향이 있으나 그거 할 시간에 다음 과제를 밀겠다.

1. 과제 설명

printf를 구현하시오

ft_printf의 프로토타입은 int ft_printf(const char , ...); 이어야 합니다.

The prototype of ft_printf should be int ft_printf(const char *, ...);

당신은 libc의 printf 함수를 다시 구현해야 합니다.

You have to recode the libc’s printf function

실제 printf 함수처럼 버퍼 관리를 수행해서는 안 됩니다.

It must not do the buffer management like the real printf

다음과 같은 서식 지정자들을 구현할 것입니다: cspdiuxX%

It will manage the following conversions: cspdiuxX%

모든 서식문자에서 0.* 플래그와 최소 필드 너비의 조합을 어떤 조합도 처리할 것입니다.

It will manage any combination of the following flags: ’-0.*’ and minimum field width with all conversions

실제 printf 함수와 비교될 것입니다.

It will be compared with the real printf

라이브러리를 생성할 때에는 ar 명령어를 이용하세요. libtool 명령어는 허용되지 않습니다.

You must use the command ar to create your librairy, using the command libtool is forbidden.

-> 그냥 %+(cspdiuxX%)의 기능을 잘 구현하시면 됩니다.

2. 가변 인수 함수(va_list, va_start, var_arg, va_end)

가변 인수는 함수가 선언될 때 매개변수로 고정인수를 받고 ...으로 받는 나머지 인수들을 말한다.

-> 고정인수는 반드시 하나 이상 있어야한다!

va_list ap

함수로 전달되는 인수들은 스택(stack)이라는 기억 장소에 저장되며 함수는 스택에서 인수를 꺼내 쓴다. 스택에 있는 인수를 읽을 때 포인터 연산을 해야 하는데 현재 읽고 있는 번지를 기억하기 위해 va_list형의 포인터 변수 하나가 필요하다. 변수 이름은 ap로 되어 있는데 ap는 어디까지나 지역 변수일 뿐이므로 이름은 마음대로 정할 수 있되 관습적으로 가변 인수를 다루는 매크로에서는 ap라는 이름을 사용한다. va_list타입은 char *형으로 정의되어 있다. 가변 인수를 읽기위한 포인터 변수를 선언했다고 생각하면 된다.

va_start(ap, 마지막고정인수)

이 명령은 가변 인수를 읽기위한 준비를 하는데 ap 포인터 변수가 첫 번째 가변 인수를 가리키도록 초기화한다. 첫 번째 가변 인수의 번지를 조사하기 위해서 마지막 고정 인수를 전달해주어야 한다. va_start 내부에서는 마지막 고정 인수 다음 번지로 ap를 맞추어 주므로 이후부터 ap 번지를 읽으면 순서대로 가변 인수를 읽을 수 있다.

va_arg(ap,인수타입)

가변 인수를 실제로 읽는 명령이다. va_start가 ap를 첫 번째 가변 인수 번지로 맞추어 주므로 ap위치에 있는 값을 읽기만 하면 된다. 단, ap번지에 있는 값이 어떤 타입인지를 알아야 하므로 두 번째 인수로 읽고자 하는 값의 타입을 지정해주어야 한다. 에를 들어 ap위치에 있는 정수값을 읽고자 한다면 va_arg(ap,int)를 호출하고 실수값을 읽고자 한다면 va_arg(ap,double)이라고 호출하면 된다. 이 명령은 ap위치에서 타입에 맞는 값을 읽어 리턴해주며 또한 ap를 다음 가변 인수 위치로 옮겨준다. 그래서 va_arg를 반복적으로 호출하면 전달된 가변 인수를 순서대로 읽을 수 있다.
va_arg함수는 매크로 함수이므로 인수타입에 int, double 같은 타입 이름을 인수로 전달할 수 있다. va_arg의 두 번째 인수는 내부적으로 sizeof 연산자와 캐스트 연산자로 전달되기 때문에 타입명이 될 수 있다.

va_end(ap)

이 명령은 가변 인수를 다 읽은 후 뒷정리를 하는데 별다른 동작은 하지 않고 실제로 없어도 상관이 없다. 이 명령이 필요한 이유는 호환성 때문인데 플랫폼에 따라서는 가변 인수를 읽은 후에 뒷처리를 할 필요가 있기 때문이다. intel계열의 CPU에서는 아무 일도 하지 않는다. 하지만 호환성을 위해 관례적으로 넣어주는 것이 좋다.

3. 과제 진행(ft_print)

  1. 가변인수를 사용하기 위해 va_list ap;로 ap 선언
  2. printf함수는 출력되는 문자의 길이를 출력해주기 때문에 길이를 세어줄 int count; 함수 선언 후 0으로 초기화 (생각해보니 0은 초기화 해줄 필요 없을 것 같음)
  3. va_start(ap, str);로 고정인수 str 다음의 가변인수를 가르키도록 지정
  4. count+=ret_count(함수)(str,ap); 카운트 해주는 함수 만듦
  5. va_end(ap);로 정리해줌.
  6. return (count);로 길이를 리턴해준다

4. 과제 진행2(ret_count)

  1. int ret_count(const char *save, va_list ap);
  2. str의 인덱스 넘버를 가르킬 int 변수 i 선언 후 0 초기화
  3. 길이를 리턴해주기 위해 int 변수 count 선언 후 0 초기화
  4. while(save[i])로 반복 실행.
  5. while문 내부에서 i = find_next(함수)(save, ap, &count, i);로 save의 모든 문자에 대해 % + cisduxX%인지 검사
  6. i++; 후 while문 종료
  7. return (count); 로 길이 리턴

5. 과제 진행3(find_next)

  1. int fin_next(const char save, va_list ap, int count, int i);
  2. if와 else로 분기.
    if는 save[i]==% && save[i + 1] != '\0' 이 조건, else는 *count += ft_putchar(save[i]); 로 출력해주고 ft_putchar가 정상 출력되면 return (1)을 해주기 때문에 count가 1씩 올라감
  3. 다시 if문 내부에서 if와 else if 여러개로 분기.
    c,s,p,d,u,x,X,%의 조건을 처리한다.
    else로 %뒤에 cspduxX%를 제외한 다른 값이 나오면 오류처리를 해주는게 맞으나 기계평가에서 어떻게 될지 모르기 때문에 따로 처리해주지 않고 넘어갔다.
  4. return (i);로 인덱스 번호 리턴
profile
내가 다시 보려고 만드는 42서울 본과정 블로그

0개의 댓글