-
Notifications
You must be signed in to change notification settings - Fork 0
/
ft_printf.c
145 lines (121 loc) · 3.96 KB
/
ft_printf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* ************************************************************************** */
/* */
/* :::::::: */
/* ft_printf.c :+: :+: */
/* +:+ */
/* By: kawish <[email protected]> +#+ */
/* +#+ */
/* Created: 2021/01/24 14:35:22 by kawish #+# #+# */
/* Updated: 2021/03/06 11:21:20 by kawish ######## odam.nl */
/* */
/* ************************************************************************** */
#include "ft_printf.h"
/* Initializes members of the t_fields *fields struct.
Precision is initiliazed to -1 because a precision of 0
will have consequences for formatting.
Width is initiliazed to 0 because a width of 0 won't have
consequences for formatting, but a width of 1 does.
t_fields *fields -- pointer to struct that contains information
on fields
*/
static void init_fields(t_fields *fields)
{
fields->count = 0;
fields->is_minus = 0;
fields->padding_char = ' ';
fields->width = 0;
fields->precision = -1;
fields->conv_char = '\0';
}
/* Resets members of the t_fields *fields struct.
t_fields *fields -- pointer to struct that contains information
on fields
*/
static void reset_fields(t_fields *fields)
{
fields->is_minus = 0;
fields->padding_char = ' ';
fields->width = 0;
fields->precision = -1;
fields->conv_char = '\0';
}
/* Splits program flow up according to
conversion specifier.
va_list ap -- arguments pointer to list of unnamed arguments
t_fields *fields -- pointer to struct that contains information
on fields
*/
static void format(va_list ap, t_fields *fields)
{
const char *sval;
if (fields->conv_char == 's')
{
sval = va_arg(ap, char *);
if (sval == NULL)
format_s(fields, "(null)");
else
format_s(fields, sval);
}
else if (fields->conv_char == 'd' || fields->conv_char == 'i')
format_di(fields, va_arg(ap, int));
else if (fields->conv_char == 'c')
format_c(fields, va_arg(ap, int));
else if (fields->conv_char == 'u')
format_u(fields, va_arg(ap, unsigned int));
else if (fields->conv_char == 'x' || fields->conv_char == 'X')
format_x(fields, va_arg(ap, unsigned int));
else if (fields->conv_char == 'p')
format_p(fields, va_arg(ap, unsigned long));
else if (fields->conv_char == '%')
format_c(fields, '%');
}
/* Iterates over const char *fmt.
Prints characters untill it finds a '%'.
After which it processes flags/fields/specifiers.
Then it prints the formatted variadic argument(s).
Lastly it resets the processed flags/fields/specifiers.
const char *fmt -- string to be formatted
va_list ap -- arguments pointer to list of unnamed arguments
t_fields *fields -- pointer to struct that contains information
on fields
*/
static void interate_fmt(const char *fmt, va_list ap, t_fields *fields)
{
const char *p_fmt;
p_fmt = fmt;
init_fields(fields);
while (*p_fmt)
{
if (*p_fmt != '%')
{
write(1, p_fmt, 1);
fields->count++;
}
else
{
p_fmt = set_fields(p_fmt, ap, fields);
format(ap, fields);
reset_fields(fields);
}
p_fmt++;
}
}
/* Produces output according to a format.
ft_printf converts, formats and prints its arguements
on the standard output under control of the format. It
returns the number of characters printed.
It handles the '0' and '-' flags. It handles field with
and precision, also when given as arguments using '*'.
It handles the following specifiers: d, i, u, x, X, s, c, p.
const char *fmt -- string to be formatted
... -- variadic arguments
*/
int ft_printf(const char *fmt, ...)
{
va_list ap;
t_fields fields;
va_start(ap, fmt);
interate_fmt(fmt, ap, &fields);
va_end(ap);
return (fields.count);
}