Excercise 00 ~ 02는 앞서 나온 문제들과 중복됨
Exercise 03 : ft_atoi
• Write a function that converts the initial portion of the string pointed by str to its int representation
int is_space(char c)
{
char *space;
space = " \n\t\v\f\r";
while (*space != '\0')
{
if (c == *space)
return (1);
space++;
}
return (0);
}
int ft_atoi(char *str)
{
int count;
int result;
count = 0;
result = 0;
while (is_space(*str))
str++;
while (*str == '-' || *str == '+')
{
if (*str == '-')
count++;
str++;
}
while (*str >= '0' && *str <= '9')
{
result = result * 10 + *str - '0';
str++;
}
if (count % 2 == 1)
return (result * (-1));
return (result);
}
문자열이 주어지면 해당 문자열을 숫자로 바꾸어주는 atoi함수
입력받는 문자열은 ( 공백 / 부호 / 숫자 ) 의 순으로 입력받고 그 이외에는 모두 잘라내야한다.
ex) " ---+--+1234ab567" -> -1234
ex) " \n\t -+-- +- 1245 -> 0
두번째 예시의 경우 앞 공백문자들 이후에 부호가 왔지만 그 부호 이후에는 다시 공백이 오기때문에 숫자가 오지 않은걸로 판단한다.
white space에 해당하는 문자를 확인하기 위해 isspace(3)의 메뉴얼을 찾아서 총6글자의 해당 문자들을 찾았고 이를 이용해 is_space함수를 구현함
공백문자가 없을 때까지 str포인터를 이동하고, 부호의 개수를 세면서 또한 부호가 없을 때 까지 포인터를 이동시킨다.
마지막으로 숫자가 나오지 않을 때 까지 결과값에 10을 곱해서 더하는 과정을 거쳐서 부호에 따라서 양/음에 맞춰 리턴한다.
Exercise 04 : ft_putnbr_base
• Create a function that displays a number in a base system in the terminal.
#include <unistd.h>
int base_check(char *base)
{
int len;
int i;
int j;
len = 0;
i = 0;
j = 0;
while (base[len] != '\0')
{
if (base[len] == '-' || base[len] == '+')
return (0);
len++;
}
while (i < len - 1)
{
j = i + 1;
while (j < len)
{
if (base[i] == base[j])
return (0);
j++;
}
i++;
}
return (len);
}
void ft_putnbr_base(int nbr, char *base)
{
int i;
int len;
int num;
char result[32];
i = 0;
len = base_check(base);
if (len < 2)
return ;
if (nbr == 0)
write(1, &base[0], 1);
if (nbr < 0)
write(1, "-", 1);
while (nbr != 0)
{
num = nbr % len;
if (num < 0)
num *= (-1);
result[i++] = base[num];
nbr /= len;
}
while (i > 0)
write(1, &result[--i], 1);
}
숫자와 진법이 주어지면 해당 진법에 맞춰 숫자를 바꾸어 출력하는 함수
base에 진법의 규칙이 주어지는데,
0123456789ABCDEF 는 흔히 아는 16진법이지만,
poneyvif 이 경우는 8진법이지만 각 인덱스에 해당하는 문자가 그 숫자를 대표하게 된다.
ex) nbr : 175 / base : poneyvif
-> 8진수로 257이고 이를 base에 기반해서 바꾸면 nvf가 된다.
base의 제한조건이 있는데, 크기가 1보다 작거나, 중복된 요소가 있거나, 부호가 들어있는 경우 아무것도 표시하면 안된다. 따라서 먼저 base check를 통해 base가 적법한지 판단한다. 효율성을 높이기 위해 base의 길이를 리턴하는 함수를 기본으로하고, 적법하지 않은 base의 경우 0을 리턴한다.
그 후의 코드는 이전에 작성했던 putnbr과 유사하게 배열에 저장하고 출력한다. 2진법의 base가 입력받아졌을 경우가 가장 길어질 수 있는데 int의 상한이 2^31이므로 배열을 32로 지정하면 더 길어질 일은 없다.
Exercise 05 : ft_atoi_base
• Write a function that converts the initial portion of the string pointed by str to int representation.
int is_space_2(char c)
{
char *space;
space = " \n\t\v\f\r";
while (*space != '\0')
{
if (c == *space)
return (1);
space++;
}
return (0);
}
int base_check_2(char *base)
{
int len;
int i;
int j;
len = 0;
i = 0;
j = 0;
while (base[len] != '\0')
{
if (is_space_2(base[len]) || base[len] == '-' || base[len] == '+')
return (0);
len++;
}
while (i < len - 1)
{
j = i + 1;
while (j < len)
{
if (base[i] == base[j])
return (0);
j++;
}
i++;
}
return (len);
}
int find_base(char *base, char c)
{
int i;
i = 0;
while (base[i] != '\0')
{
if (base[i] == c)
return (i);
i++;
}
return (-1);
}
int atoi_simple(char *str, char *base, int len)
{
int result;
int temp;
result = 0;
temp = 0;
while (1)
{
temp = find_base(base, *str++);
if (temp < 0)
break ;
result = result * len + temp;
}
return (result);
}
int ft_atoi_base(char *str, char *base)
{
int nbr;
int count;
int len;
nbr = 0;
count = 0;
len = base_check_2(base);
if (len < 2)
return (0);
while (is_space_2(*str))
str++;
while (*str == '-' || *str == '+')
{
if (*str == '-')
count++;
str++;
}
nbr = atoi_simple(str, base, len);
if (count % 2 == 1)
return (nbr * (-1));
return (nbr);
}
앞서 푼 두문제가 결합된 문제이다.
putnbr_base에서는 숫자를 base로 변환하기 때문에 해당 index에 접근하면 바로 해결됐지만, 해당 base에 맞는 인덱스를 찾아야하기 때문에 find_base를 구현해 해당 character의 인덱스를 반환했다.
atoi_simple은 굳이 구현하지 않아도 됐지만, 42서울의 특성상 한 함수의 크기가 25줄을 넘어서면 안되기 때문에 부득이하게 전처리(공백 제거, 부호 제거)가 끝난 문자열을 입력받으면 base에 맞춰서 숫자로 반환해주는 함수를 구현했다.