C08은 전반적으로 헤더파일에 관한 내용이다. 헤더파일은 복수개의 파일을 컴파일하거나 작성할 때 같은 헤더나 선언을 여러 번 하지 않도록 도와준다. 해당 프로젝트는 헤더파일과 구조체에 대한 기초적인 이해를 가지고 풀 수 있다. 헤더파일 같은 경우 내용이 어렵지 않지만, 구조체는 처음 본다면 조금 헷갈릴 수 있는데, 사실 해당 프로젝트에서는 활용보다는 선언 정도를 하기 때문에 처음 익히기 어렵지 않을 것이다.
Exercise 00: ft.h
Create your ft.h file.
Allowed Function: None
첫 번째 문제는 간단히 주어진 프로토타입의 함수를 포함한 헤더파일을 작성하기만 하면 된다. 다만 42에서 헤더파일을 작성할 때에 주의해야 할 점이 몇 가지 있다.
첫 번째는 #ifndef와 #endif이다. 42에서 헤더파일을 작성할 때는 꼭 이를 활용해주어야 한다. 사실 #ifndef와 #endif는 평소 코딩할 때도 많이 사용하기 때문에 알아두는 편이 좋다. 의미는 만약 FT_H가 아직 정의되지 않았다면(#ifndef FT_H), FT_H를 정의한다(#define FT_H). #endif는 이런 선언을 끝내는 역할을 한다. FT_H라는 이름은 42 norm에서 그렇게 하라고 지정했다. 그리고 #과 define 사이에 공백을 하나 줘야 한다. 이것도 42 norm에서 하라고 했다.
#ifndef FT_H
# define FT_H
void ft_putchar(char c);
void ft_swap(int *a, int *b);
void ft_putstr(char *str);
int ft_strlen(char *str);
int ft_strcmp(char *s1, char *s2);
#endif
Exercise 01: ft_boolean.h
Create a ft_boolean.h file. It’ll compile and run the following main appropriately:
Allowed Function: None
두 번째 문제는 아래 코드를 컴파일할 수 있는 헤더 파일을 작성하는 것이다.
#include "ft_boolean.h"
void ft_putstr(char *str)
{
while (*str)
write(1, str++, 1);
}
t_bool ft_is_even(int nbr)
{
return ((EVEN(nbr)) ? TRUE : FALSE);
}
int main(int argc, char **argv)
{
(void)argv;
if (ft_is_even(argc - 1) == TRUE)
ft_putstr(EVEN_MSG);
else
ft_putstr(ODD_MSG);
return (SUCCESS);
}
우선 위 코드에서 header 파일 내에 정의해야 할 것을 찾아야 한다. 내가 정리한 정의해야 할 목록은 다음과 같았다.
write() 사용을 위한 헤더
t_bool type
EVEN() macro function
TRUE, FALSE
EVEN_MSG, ODD_MSG
SUCCESS
이를 바탕으로 코드를 작성해주었다. 정의하는 데에는 딱히 어려움은 없다. TRUE, FALSE나 메시지들을 정의할 때는 상수를 정의하는 것이므로 #define을 사용해 주면 되고, t_bool을 boolean 타입으로 설정해 주기 위해서는 typedef를 사용해 주면 된다. 이를 위해서는 stdbool.h 헤더도 추가해주어야 한다. 이 과정이 싫다면 그냥 TRUE를 1, FALSE를 2로 define 해주고 t_bool을 int로 설정해 주어도 된다. macro fucntion인 EVEN() #define을 이용하여 정의해 준다.
#ifndef FT_BOOLEAN_H
# define FT_BOOLEAN_H
# include <stdbool.h>
# include <unistd.h>
typedef bool t_bool;
# define TRUE true
# define FALSE false
# define EVEN(x) ((x) % 2 == 0)
# define EVEN_MSG "I have an even number of arguments.\n"
# define ODD_MSG "I have an odd number of arguments.\n"
# define SUCCESS 0
#endif
Exercise 02: ft_abs.h
Create a macro ABS which replaces its argument by it absolute value.
Allowed Function: None
세 번째 문제는 절대값을 리턴하는 ABS() macro function을 작성하면 된다. 나는 이 문제가 삼항 연산자를 사용할 수 없어서 까다롭다고 느껴졌는데, 나중에 평가를 하다 보니 신박한 방법으로 푼 사람들이 많았다.
내가 사용한 방식은 BIGGER()라는 helper function을 만들어서, ABS()' 함수의 인자로 입력받은 숫자 자체와 여기서 -1을 곱한 값 중 더 큰 것을 리턴하게 했다. BIGGER()라는 helper function은 첫 번째 인자가 더 크면 1, 두 번째가 더 크면 0을 리턴하므로, 현재 확인하는 값을 첫 번째 인자로 주어 결괏값을 해당 값과 곱하면 된다.
#ifndef FT_ABS_H
# define FT_ABS_H
# define BIGGER(Value1, Value2) (Value1 > Value2)
# define ABS(Value) (Value) * BIGGER(Value, -Value)\
+ (-(Value)) * BIGGER(-Value, Value)
#endif
Exercise 03: ft_point.h
Create a file ft_point.h that’ll compile the following main:
Allowed Function: None
해당 문제는 주어진 코드의 main 함수를 컴파일할 수 있는 ft_point.h 헤더 파일을 작성하는 것이 목표이다. 이 문제는 구조체에 대한 기본적인 이해만 있으면 간단히 해결할 수 있다.
#include "ft_point.h"
void set_point(t_point *point)
{
point->x = 42;
point->y = 21;
}
int main(void)
{
t_point point;
set_point(&point);
return (0);
}
우선 위 코드를 보면, t_point 타입을 설정해야 하는데, 이 타입으로 정의된 포인터 변수에서 ->x 이런 식으로 다른 값을 얻어내는 것을 볼 수 있다. 이것이 구조체 내 값을 가져오는 방식이다. t_point 구조체 내에는 x와 y 변수가 있는 것으로 보이고, struct POINT와 같이 타입을 선언하지 않은 것을 보니 typedef를 이용하여 타입 이름을 따로 설정했다는 것을 알 수 있다.
이를 바탕으로 코드를 작성하면 우선 struct TPOINT를 선언해서 그 안에 int x, int y를 넣어준다. 그리고 typedef를 이용하여 이 구조체의 이름을 t_point로 설정해준다. typedef를 이용하여 구조체 이름을 설정해주지 않을 경우, 해당 구조체를 사용하고 싶을 때마다 "struct TPOINT" 이 타입의 이른바 풀네임을 작성해주어야 한다. 이 과정이 여러 번 반복되면 번거롭기 때문에 대체로 구조체를 사용할 때는 typedef를 이용한다.
#ifndef FT_POINT_H
# define FT_POINT_H
typedef struct TPOINT
{
int x;
int y;
} t_point;
#endif
Exercise 04: ft_strs_to_tab
Create a function that takes an array of string as argument and the size of this array.
It will transform each element of av into a structure.
The structure will be defined in the ft_stock_str.h file that we will provided, like this:
◦ size being the length of the string;
◦ str being the string;
◦ copy being a copy of the string;
It should keep the order of av.
The returned array should allocated in memory and its last element’s str set to 0, this will mark the end of the array.
It should return a NULL pointer if an error occurs.
Allowed Function: malloc, free
해당 문제는 아래 주어진 구조체를 이용하여 인자로 받은 문자열들을 구조체에 각각 저장하여 구조체 배열을 리턴하는 문제이다. 이 구조체는 "ft_stock_str.h" 헤더 파일로 주어질 예정이므로, 코드에 이를 포함하기만 하면 된다.
typedef struct s_stock_str
{
int size;
char *str;
char *copy;
} t_stock_str;
코드를 보면 총 두 개의 helper function을 사용했다. ft_strlen()으로 입력받은 문자열 길이를 파악하는 함수를, ft_strdup으로 입력받은 src 인자를 복사한 새로운 배열을 리턴하는 함수를 만들었다. 앞선 과제에서 모두 나왔던 함수이므로 따로 구체적으로 언급하지는 않겠다.
ft_strs_to_tab() 함수를 보면, 우선 입력받은 문자열의 개수만큼의 크기를 가진 t_stock_str 타입의 포인터 변수에 메모리를 할당해준다. 그리고 while문으로 av에 입력된 문자열들을 순회하면서, 구조체 내 str에는 해당 문자열 자체를, size에는 ft_strlen()으로 파악한 문자열의 길이를, copy에는 ft_strdup()으로 만든 복사된 새로운 문자열을 각각 넣는다.
#include <stdlib.h>
#include "ft_stock_str.h"
int ft_strlen(char *str)
{
int len;
len = 0;
while (str[len])
len++;
return (len);
}
char *ft_strdup(char *src, int size)
{
char *dest;
int i;
dest = (char *)malloc(sizeof(char) * (size + 1));
if (dest == NULL)
return (NULL);
i = 0;
while (i < size)
{
dest[i] = src[i];
i++;
}
dest[i] = 0;
return (dest);
}
struct s_stock_str *ft_strs_to_tab(int ac, char **av)
{
t_stock_str *s;
int i;
s = (t_stock_str *)malloc(sizeof(t_stock_str) * (ac + 1));
if (s == NULL)
return (NULL);
i = 0;
while (i < ac)
{
s[i].str = av[i];
s[i].size = ft_strlen(av[i]);
s[i].copy = ft_strdup(av[i], s[i].size);
i++;
}
s[i].str = 0;
return (s);
}
Exercise 05: ft_show_tab
Create a function that displays the content of the array created by the previous function.
The structure will be the same as the previous exercise and will be defined in the ft_stock_str.h file.
For each element, we’ll display:
◦ the string followed by a ’\n’
◦ the size followed by a ’\n’
◦ the copy of the string (that could have been modified) followed by a ’\n’
Allowed Function: write
해당 문제는 앞선 ex04의 결과로 리턴된 구조체 배열을 주어진 규칙에 맞게 출력하는 문제이다. 규칙은 각각의 요소 다음에 new line character를 출력해 주면 된다.
여기서는 int type인 size를 출력하는 것이 가장 까다롭다. 하지만 앞선 과제에서 모두 put_num을 작성해보셨다면, 이 문제도 큰 어려움 없이 해결 가능하다. 나는 put_int() 함수를 만들어서 size를 출력해 주고, 나머지는 따로 putstr을 만들지 않고 size를 이용해서 그냥 write() 함수를 사용해 줬다.
#include <unistd.h>
#include "ft_stock_str.h"
void put_int(int num)
{
int pow;
char c;
pow = 1;
while (num / pow >= 10)
pow *= 10;
while (pow > 0)
{
c = (num / pow) + '0';
write(1, &c, 1);
num = num % pow;
pow /= 10;
}
}
void ft_show_tab(struct s_stock_str *par)
{
while (par->str)
{
write(1, par->str, par->size);
write(1, "\n", 1);
put_int(par->size);
write(1, "\n", 1);
write(1, par->copy, par->size);
write(1, "\n", 1);
par++;
}
}
'개발 프로젝트 > Hive Helsinki [42 Helsinki]' 카테고리의 다른 글
[Hive Helsinki / Piscine] C09 (0) | 2024.05.25 |
---|---|
[Hive Helsinki / Piscine] BSQ (0) | 2024.05.13 |
[Hive Helsinki / Piscine] Rush02 (0) | 2024.04.30 |
[Hive Helsinki / Piscine] C07 (1) | 2024.04.26 |
[Hive Helsinki / Piscine] C06 (1) | 2024.04.19 |