subject en:
Assignment name : ft_printf
Expected files : ft_printf.c
Allowed functions: malloc, free, write, va_start, va_arg, va_copy, va_end
--------------------------------------------------------------------------------
Write a function named `ft_printf` that will mimic the real printf with the following constraints:
- It will manage only the following conversions: s,d and x
- It will manage the minimum field width. (we will never test with a field with of 0)
- It will manage only the precison flag `.`.
Your function must be declared as follows:
int ft_printf(const char *, ... );
Before you start we advise you to read the `man 3 printf` and the `man va_arg`.
To test your program compare your results with the true printf.
Exemples of the function output:
call: ft_printf("%10.2s\\n", "toto");
out: to$
call: ft_printf("Magic %s is %5d", "number", 42);
out:Magic number is 42%
call: ft_printf("Hexadecimal for %d is %x\\n", 42, 42);
out:Hexadecimal for 42 is 2a$
subject ru:
Название задания : ft_printf
Ожидаемые файлы : ft_printf.c
Разрешенные функции: malloc, free, write, va_start, va_arg, va_copy, va_end
--------------------------------------------------------------------------------
Напишите функцию с именем ft_printf, которая будет имитировать реальный printf со следующими ограничениями:
- Он будет управлять только следующими преобразованиями: s, d и x
- Он будет управлять минимальной шириной поля. (мы никогда не будем тестировать поле с 0)
- Он будет управлять только флагом точности `.`.
Ваша функция должна быть объявлена следующим образом:
int ft_printf(const char *, ... );
Прежде чем начать, мы советуем вам прочитать `man 3 printf` и `man va_arg`.
Чтобы протестировать свою программу, сравните свои результаты с истинным printf.
Примеры вывода функции:
call: ft_printf("%10.2s\\n", "toto");
out: to$
call: ft_printf("Magic %s is %5d", "number", 42);
out:Magic number is 42%
call: ft_printf("Hexadecimal for %d is %x\\n", 42, 42);
out:Hexadecimal for 42 is 2a$
Решение:
<https://github.com/parismart/exam_rank02/blob/master/ft_printf/ft_printf.c>
#include <unistd.h>
#include <stdarg.h>
static int ft_nbrlen(long n, int base_len)
{
int i;
i = 1;
while (n >= base_len)
{
n /= base_len;
i++;
}
return (i);
}
static void ft_putnbr(long nbr, int base_len, char *base)
{
if (nbr >= base_len)
ft_putnbr(nbr / base_len, base_len, base);
write(1, &base[nbr % base_len], 1);
}
int ft_printf(const char *format, ...)
{
va_list args;
char *str;
char *s;
long nbr;
int neg;
int len;
int width;
int prec;
int spaces;
int zeros;
int length;
va_start(args, format);
str = (char *)format;
length = 0;
while (*str)
{
if (*str == '%')
{
str++;
neg = 0;
len = 0;
width = 0;
prec = -1;
spaces = 0;
zeros = 0;
while (*str >= '0' && *str <= '9')
{
width = width * 10 + (*str - 48);
str++;
}
if (*str == '.')
{
prec = 0;
str++;
while (*str >= '0' && *str <= '9')
{
prec = prec * 10 + (*str - 48);
str++;
}
}
if (*str == 's')
{
s = va_arg(args, char *);
if (!s)
s = "(null)";
while (s[len])
len++;
}
if (*str == 'd')
{
nbr = va_arg(args, int);
if (nbr < 0)
{
nbr = -nbr;
neg = 1;
}
len = ft_nbrlen(nbr, 10) + neg;
}
if (*str == 'x')
{
nbr = va_arg(args, unsigned);
len = ft_nbrlen(nbr, 16);
}
if (prec >= len && *str != 's')
zeros = prec - len + neg;
else if (prec > -1 && prec < len && *str == 's')
len = prec;
else if (prec == 0 && (*str == 's' || nbr == 0))
len = 0;
spaces = width - zeros - len;
while (spaces-- > 0)
length += write(1, " ", 1);
if (neg == 1)
write(1, "-", 1);
while (zeros-- > 0)
length += write(1, "0", 1);
if (*str == 's')
write(1, s, len);
else if (len > 0 && *str == 'd')
ft_putnbr(nbr, 10, "0123456789");
else if (len > 0 && *str == 'x')
ft_putnbr(nbr, 16, "0123456789abcdef");
length += len;
}
else
length += write(1, str, 1);
str++;
}
va_end(args);
return (length);
}