ft_printf_2일차

아따맘마·2020년 11월 9일
0

ft_printf

목록 보기
3/9

본격적으로 ft_printf를 만들어보자.

내가 처음으로 생각했던 메커니즘은 다음과 같다. 처음 노베이스에서 생각한 부분이라 많이 부족하다.

main에서 ft_printf("...", a, b, c);와 같이 함수를 받으면 ft_printf에서 메인에서 인자를 잘 받아왔는지 확인해야 한다.
그럼 어떨 때 오류가 발생하는지 생각해보자. man printf를 통해 printf의 정보를 보면

int printf(const char *format, ...);

기본적으로 받는 첫번째 인자는 string이다. 그러면 이럴 때 오류가 발생하지 않을까??
1. printf(a);처럼 string이 아닌 일반 변수를 받을 때
2. printf();처럼 아무 인자를 받지 않을 때
두가지 정도가 존재한다.

그럼 이렇게 오류를 받을때 printf는 어떤 값을 반환해야 할까?
printf의 반환값을 보면 int형을 반환한다. printf는 출력을 하는 함수라 void형의 함수인줄 알았는데, 확인해보니 int형이였다. printf는 어떤 것을 반환할 지 확인해보고 싶어 테스트를 해보았다.

#include <stdio.h>

int main()
{
	int a = 5;
	int size;

	size = printf("%d\n", a);
	printf("%d", size);
}

c6r6s6% ./a.out
5
2%

컴파일 후 실행을 해보면 첫번째 printf는 a의 값인 5를 출력하고 printf의 반환값을 받은 size는 2를 출력했다. 대충 어떤 값인지는 감이 온다. 숫자 5와 '\n'을 출력했으니 총 갯수(?) 2를 출력한 것 아닐까??
다른 값으로 테스트를 해보자

#include <stdio.h>

int main()
{
	char *str = "abcd";
	int size;

	size = printf("%s\n", str);
	printf("%d", size);
}

./a.out
abcd
5%

string 변수로 확인했을 때, 문자열 abcd와 '\n'을 포함한 문자열의 길이를 출력했다.
그럼 printf에서 오류가 날 때 -1을 반환해주면 되지 않을까??

Return value
Upon successful return, these functions return the number of characters printed (excluding the null byte used to end output to strings).
The functions snprintf() and vsnprintf() do not write more than size bytes (including the terminating null byte ('\0')). If the output was truncated due to this limit then the return value is the number of characters (excluding the terminating null byte) which would have been written to the final string if enough space had been available. Thus, a return value of size or more means that the output was truncated. (See also below under NOTES.)
If an output error is encountered, a negative value is returned.

혹시나 해서 확인하고자 man printf를 봤는데 마지막 문장에서 neg value를 반환한다고 친절히 설명해줬다.

1차 문제점

/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   ft_printf.c                                        :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: hwalee <marvin@42.fr>                      +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2020/11/09 14:55:11 by hwalee            #+#    #+#             */
/*   Updated: 2020/11/09 17:51:35 by hwalee           ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "ft_printf.h"

int	ft_check_for(const char *format)
{

}

int	ft_printf(const char *format, ...)
{
	va_list ap;

	va_start(ap, format);
	if (ft_check_for(format) == ERROR)
		return (ERROR);
    size = ft_strlen(format);
	return (size);
}

무심코 생각나는대로 코드를 짜다가 문제점을 발견했다. 솔직히 다른사람이 짠 코드를 한번 훑어봤었는데 왜 구조체를 썻는지 이해가 되지 않았었다. 그래서 나는 그냥 일반 변수를 만들고(엄청나게 많이 만들어내겠지만) 필요할 때마다 호출하여 쓰려고 했었는데, 시작하자마자 문제점을 발견했다. 본 함수에서 return(size)를 해주려고 strlen을 쓰면서 반환값을 내보내려고 했는데,

format에 "%d"라면 strlen에서 2를 반환한다.

와 같은 문제점이 발견됬다. 그렇다고 다른 함수에서 반환하자고 하니 본함수에서 return값이 없어 문제가 발생하고...
해서 결국 구조체를 쓰게 됬다.

typedef struct  s_list{
    int size;
}               t_list;

일단 코드를 짜보면서 리스트에 하나하나씩 변수를 추가해나갈 예정이다.

int ft_check_for

첫번째 서브함수를 짜보자.
첫번째 함수는 인자값으로 받아온 format 문자열을 체크해보는 함수이다.

int ft_check_for(va_list ap, const char *format, t_list *list)

반환값

ft_check_for()의 반환값은 int로 설정해줬다. 그 이유는 본 함수에서 오류일때, 즉 negative value일 때를 조건으로 해주었기 때문이다. 그래서 이 함수에서 위에 말했듯이 오류가 발생하면 ERROR을 반환, 정상적으로 작동이 된다면 다른 수를 반환하고자 한다.
ERROR은 ft_printf.h에서

#define ERROR -1

로 정의해줬다.

매개변수

va_list ap

가변인자 ap에는 ft_printf(const char *format, ...)에서 ...의 값들을 가지고 있다. ft_printf를 실행하면서 이 값들을 계속 가지고 다녀야하기 때문에 포함시켜 주었다.
처음에 가변인자를 함수의 매개변수로 넣을 때 자료형을 어떻게 넣어줘야 하는지 몰랐는데, 찾아본 결과 va_list로 똑같이 넣어주면 된다.

const char *format

기본적으로 가지고 다녀야 하는 변수이다. 이 format 문자열을 가지고 모든것을 판단하기 때문이다. '%'가 포함되어 있는지, printf옵션을 가지고 있는지, 다 포함하고 있기 때문

t_list *list

구조체 변수 t_list를 가지고 가는 이유는 일단
1. ft_printf함수에서 마지막으로 반환할 때 size를 보내야 하는데, 이를 본 함수에서가 아니라 서브함수에서 size를 구해야 한다.
2. 다른 함수들에서 flag, width를 처리해야할 때 이 구조체를 쓸 것 같은 예감이 든다.

profile
늦게 출발했지만 꾸준히 달려서 도착지점에 무사히 도달하자

0개의 댓글