-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_printf.c
184 lines (168 loc) · 4.6 KB
/
_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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include "main.h"
/**
* _printf - variadic function
* @format: named parameter specification of format
* Return: the number of characters printed
*/
int _printf(const char *format, ...)
{
va_list args;
int count;
/* struct two dimensional array */
fmt fmt_specs[] = {
{'c', char_print}, {'s', string_print}, {'d', dec_print},
{'i', int_print}, {'b', bin_print}, {'u', uint_print},
{'o', oct_print}, {'x', hex_print}, {'X', cap_hex_print},
{'S', str_hex_print}, {'p', ptr_print}, {'\0', NULL}
};
count = 0;
va_start(args, format);
if (format != NULL)
{
if (print_fmt(format, args, &count, fmt_specs) == -1)
return (-1);
}
else
return (-1);
va_end(args);
return (count);
}
/**
* print_fmt - _printf function format printing check
* @format: named parameter specification of format
* @args: variable arguments list
* @count: pointer to integer to store the count of characters printed
* @fmt_specs: struct two dimensional array, typedefed to fmt
* Return: the number of characters printed
*/
int print_fmt(const char *format, va_list args,
int *count, fmt fmt_specs[])
{
int i;
char flag = '\0';
char space = '\0';
for (i = 0; format[i] != '\0'; i++)
{
if (format[i] != '%') /* check for fmt spec */
{ _putchar(format[i]);
(*count)++; }
else /* start fmt spec */
{
i++; /* increment to next character after the % */
/* check for flag characters */
if (format[i] == '+' || format[i] == '-' || format[i] == '#')
{ flag = format[i];
i++;
if (format[i] == ' ')
i++;
}
else if (format[i] == ' ')
{ space = format[i];
i++;
if (format[i] == '+' || format[i] == '-' || format[i] == '#')
{ flag = format[i];
i++; }
} /* check standalone %, flag and if %, flag is the last char */
if (format[i] == '\0')
return (-1);
/* search for corresponding conversion specifier */
if (!handle_fmt_spec(format[i], args,
count, fmt_specs, &flag, &space))
{ _putchar('%');
_putchar(format[i]);
(*count) += 2;
}
}
}
return (0);
}
/**
* handle_fmt_spec - search for corresponding conversion specifier
* @fmt_char: the format specifier
* @args: variable arguments list
* @count: pointer to integer to store the count of characters printed
* @fmt_specs: struct two dimensional array, typedefed to fmt
* @flag: pointer to flag character
* @space: pointer to space character
* Return: true if conversion specifier is found and handled, false otherwise
*/
bool handle_fmt_spec(char fmt_char, va_list args, int *count,
fmt fmt_specs[], char *flag, char *space)
{
int j;
if (fmt_char == '%') /* print a percent sign */
{
_putchar(fmt_char);
(*count)++;
return (true);
}
for (j = 0; fmt_specs[j].fmt_sign != '\0'; j++)
{
if (fmt_char == fmt_specs[j].fmt_sign) /* valid fmt handling */
{
fmt_specs[j].fmt_func_ptr(*flag, args, count, *space);
return (true);
}
}
return (false); /* invalid fmt handling */
}
/**
* dec_print - decimal (base 10) printing function
* @flag: flag characters for non-custom conversion specifiers
* @args: variable argument list
* @count: pointer to integer to store the count of characters printed
* @space: space character for non-custom conversion specifiers
* d - decimal (int) parameter passed
*/
void dec_print(char flag, va_list args, int *count, char space)
{
int d, i, j, d_len;
unsigned int num, abs_num;
char *digits;
d = va_arg(args, int);
(d < 0) ? (abs_num = d * -1) : (abs_num = d);
num = abs_num; /* hold the value of abs_num b4 passing it to count */
/* count number of digits */
d_len = 0;
while (abs_num / 10 != 0)
{ d_len++;
abs_num = abs_num / 10; }
d_len++;
digits = malloc(sizeof(char) * (d_len + 1));
if (digits == NULL)
return;
/* convert integer to string of digits */
i = 0;
while (num / 10 != 0)
{ digits[i] = (num % 10) + '0';
num = num / 10;
i++; }
digits[i] = (num % 10) + '0';
/* print (flag), - if negative, + if positive, ' ' if space*/
if (d < 0)
{ _putchar('-');
(*count)++; }
else if (flag == '+')
{ _putchar('+');
(*count)++; }
else if (space == ' ' && d >= 0)
{ _putchar(' ');
(*count)++; }
/* print digits in reverse order */
for (j = i; j >= 0; j--)
{ _putchar(digits[j]);
(*count)++; }
free(digits);
}
/**
* int_print - integer printing function
* @args: variable argument list
* @count: pointer to integer to store the count of characters printed
* @flag: flag characters for non-custom conversion specifiers
* @space: space character for non-custom conversion specifiers
* i - integer (int) parameter to print
*/
void int_print(char flag, va_list args, int *count, char space)
{
dec_print(flag, args, count, space);
}