├── README.md ├── _printf.c ├── converter.c ├── get_flag.c ├── get_print.c ├── holberton.h ├── man_3_printf ├── print_address.c ├── print_alpha.c ├── print_bases.c ├── print_custom.c ├── print_nums.c ├── tests └── main.c └── write_funcs.c /README.md: -------------------------------------------------------------------------------- 1 | # 0x10. C - printf 2 | 3 | ## Description 4 | This team project is part of the first year curriculum of Holberton School. 5 | _printf replicates the C standard library printf() function. 6 | 7 | What you should learn from this project: 8 | 9 | * How to use git in a team setting 10 | * Applying variadic functions to a big project 11 | * The complexities of printf 12 | * Managing a lot of files and finding a good workflow 13 | 14 | --- 15 | 16 | ## Prototype 17 | ```int _printf(const char *format, ...);``` 18 | 19 | ## Usage 20 | * Prints a string to the standard output, according to a given format 21 | * All files were created and compiled on Ubuntu 14.04.4 LTS using GCC 4.8.4 with the command ```gcc -Wall -Werror -Wextra -pedantic *.c``` 22 | * Returns the number of characters in the output string on success, -1 otherwise 23 | * Call it this way: ```_printf("format string", arguments...)``` where ```format string``` can contain conversion specifiers and flags, 24 | along with regular characters 25 | 26 | ## Examples 27 | 28 | * ```_printf("Hello, Holberton\n")``` *prints "Hello, Holberton", followed by a new line* 29 | * ```_printf("%s", "Hello")``` *prints "Hello"* 30 | * ```_printf("This is a number: %d", 98)``` *prints "This is a number: 98"* 31 | 32 | --- 33 | 34 | # Tasks 35 | 36 | These are all the tasks of this project, the ones that are completed link to the corresponding files. 37 | 38 | ### [0. I'm not going anywhere. You can print that wherever you want to. I'm here and I'm a Spur for life](./_printf.c) 39 | * Write a function that produces output according to format. 40 | - c : converts input into a character 41 | - s : converts input into a string 42 | 43 | ### [1. Education is when you read the fine print. Experience is what you get if you don't](./print_nums.c) 44 | * Handle the following conversion specifiers: 45 | - d : converts input into a base 10 integer 46 | - i : converts input into an integer 47 | 48 | ### [2. Just because it's in print doesn't mean it's the gospel](./man_3_printf) 49 | * Create a man page for your function 50 | 51 | ### [3. With a face like mine, I do better in print](./print_bases.c) 52 | * Handle the following conversion specifiers: 53 | - b : the unsigned int argument is converted to binary 54 | 55 | ### [4. What one has not experienced, one will never understand in print](./print_bases.c) 56 | * Handle the following conversion specifiers: 57 | - u : converts the input into an unsigned integer 58 | - o : converts the input into an octal number 59 | - x : converts the input into a hexadecimal number 60 | - X : converts the input into a hexadecimal number with capital letters 61 | 62 | ### [5. Nothing in fine print is ever good news](./write_funcs.c) 63 | * Use a local buffer of 1024 chars in order to call write as little as possible. 64 | 65 | ### [6. My weakness is wearing too much leopard print](./print_custom.c) 66 | * Handle the following custom conversion specifier: 67 | - S : prints the string 68 | - Non printable characters (0 < ASCII value < 32 or >= 127) are printed this way: \x, followed by the ASCII code value in hexadecimal (upper case - always 2 characters) 69 | 70 | ### [7. How is the world ruled and led to war? Diplomats lie to journalists and believe these lies when they see them in print](./print_address.c) 71 | * Handle the following conversion specifier: 72 | - p : int input is converted to a pointer address 73 | 74 | ### [8. The big print gives and the small print takes away](./get_flag.c) 75 | * Handle the following flag characters for non-custom conversion specifiers: 76 | - \+ : adds a \+ in front of signed positive numbers and a \- in front of signed negative numbers 77 | - space : same as \+, but adds a space (is overwritten by \+) 78 | - \# : adds a 0 in front of octal conversions that don't begin with one, and a 0x or 0X for x or X conversions 79 | 80 | ### [9. Sarcasm is lost in print] 81 | * Handle the following length modifiers for non-custom conversion specifiers: 82 | - l : converts d, i, u, o, x, X conversions in short signed or unsigned ints 83 | - h : converts d, i, u, o, x, X conversions in long signed or unsigned ints 84 | 85 | ### [10. Print some money and give it to us for the rain forests] 86 | * Handle the field width for non-custom conversion specifiers. 87 | 88 | ### [11. The negative is the equivalent of the composer's score, and the print the performance] 89 | * Handle the precision for non-custom conversion specifiers. 90 | 91 | ### [12. It's depressing when you're still around and your albums are out of print] 92 | * Handle the 0 flag character for non-custom conversion specifiers. 93 | 94 | ### [13. Every time that I wanted to give up, if I saw an interesting textile, print what ever, suddenly I would see a collection] 95 | * Handle the - flag character for non-custom conversion specifiers. 96 | 97 | ### [14. Print is the sharpest and the strongest weapon of our party](./print_custom.c) 98 | * Handle the following custom conversion specifier: 99 | - r : prints the reversed string 100 | 101 | ### [15. The flood of print has turned reading into a process of gulping rather than savoring](./print_custom.c) 102 | * Handle the following custom conversion specifier: 103 | - R : prints the rot13'ed string 104 | 105 | ### [16. * ] 106 | * All the above options work well together. 107 | 108 | --- 109 | 110 | ### Authors 111 | * **Tu Vo** - [tuvo1106@gmail.com](https://github.com/tuvo1106) 112 | * **Laura Roudge** - [laura.derohan@gmail.com](https://github.com/lroudge) 113 | -------------------------------------------------------------------------------- /_printf.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * _printf - produces output according to a format 5 | * @format: format string containing the characters and the specifiers 6 | * Description: this function will call the get_print() function that will 7 | * determine which printing function to call depending on the conversion 8 | * specifiers contained into fmt 9 | * Return: length of the formatted output string 10 | */ 11 | int _printf(const char *format, ...) 12 | { 13 | int (*pfunc)(va_list, flags_t *); 14 | const char *p; 15 | va_list arguments; 16 | flags_t flags = {0, 0, 0}; 17 | 18 | register int count = 0; 19 | 20 | va_start(arguments, format); 21 | if (!format || (format[0] == '%' && !format[1])) 22 | return (-1); 23 | if (format[0] == '%' && format[1] == ' ' && !format[2]) 24 | return (-1); 25 | for (p = format; *p; p++) 26 | { 27 | if (*p == '%') 28 | { 29 | p++; 30 | if (*p == '%') 31 | { 32 | count += _putchar('%'); 33 | continue; 34 | } 35 | while (get_flag(*p, &flags)) 36 | p++; 37 | pfunc = get_print(*p); 38 | count += (pfunc) 39 | ? pfunc(arguments, &flags) 40 | : _printf("%%%c", *p); 41 | } else 42 | count += _putchar(*p); 43 | } 44 | _putchar(-1); 45 | va_end(arguments); 46 | return (count); 47 | } 48 | -------------------------------------------------------------------------------- /converter.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * convert - converts number and base into string 5 | * @num: input number 6 | * @base: input base 7 | * @lowercase: flag if hexa values need to be lowercase 8 | * Return: result string 9 | */ 10 | char *convert(unsigned long int num, int base, int lowercase) 11 | { 12 | static char *rep; 13 | static char buffer[50]; 14 | char *ptr; 15 | 16 | rep = (lowercase) 17 | ? "0123456789abcdef" 18 | : "0123456789ABCDEF"; 19 | ptr = &buffer[49]; 20 | *ptr = '\0'; 21 | do { 22 | *--ptr = rep[num % base]; 23 | num /= base; 24 | } while (num != 0); 25 | 26 | return (ptr); 27 | } 28 | -------------------------------------------------------------------------------- /get_flag.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * get_flag - turns on flags if _printf finds 5 | * a flag modifier in the format string 6 | * @s: character that holds the flag specifier 7 | * @f: pointer to the struct flags in which we turn the flags on 8 | * 9 | * Return: 1 if a flag has been turned on, 0 otherwise 10 | */ 11 | int get_flag(char s, flags_t *f) 12 | { 13 | int i = 0; 14 | 15 | switch (s) 16 | { 17 | case '+': 18 | f->plus = 1; 19 | i = 1; 20 | break; 21 | case ' ': 22 | f->space = 1; 23 | i = 1; 24 | break; 25 | case '#': 26 | f->hash = 1; 27 | i = 1; 28 | break; 29 | } 30 | 31 | return (i); 32 | } 33 | -------------------------------------------------------------------------------- /get_print.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * get_print - selects the right printing function 5 | * depending on the conversion specifier passed to _printf 6 | * @s: character that holds the conversion specifier 7 | * Description: the function loops through the structs array 8 | * func_arr[] to find a match between the specifier passed to _printf 9 | * and the first element of the struct, and then the approriate 10 | * printing function 11 | * Return: a pointer to the matching printing function 12 | */ 13 | int (*get_print(char s))(va_list, flags_t *) 14 | { 15 | ph func_arr[] = { 16 | {'i', print_int}, 17 | {'s', print_string}, 18 | {'c', print_char}, 19 | {'d', print_int}, 20 | {'u', print_unsigned}, 21 | {'x', print_hex}, 22 | {'X', print_hex_big}, 23 | {'b', print_binary}, 24 | {'o', print_octal}, 25 | {'R', print_rot13}, 26 | {'r', print_rev}, 27 | {'S', print_bigS}, 28 | {'p', print_address}, 29 | {'%', print_percent} 30 | }; 31 | int flags = 14; 32 | 33 | register int i; 34 | 35 | for (i = 0; i < flags; i++) 36 | if (func_arr[i].c == s) 37 | return (func_arr[i].f); 38 | return (NULL); 39 | } 40 | -------------------------------------------------------------------------------- /holberton.h: -------------------------------------------------------------------------------- 1 | #ifndef HOLBERTON_H 2 | #define HOLBERTON_H 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * struct flags - struct containing flags to "turn on" 9 | * when a flag specifier is passed to _printf() 10 | * @plus: flag for the '+' character 11 | * @space: flag for the ' ' character 12 | * @hash: flag for the '#' character 13 | */ 14 | typedef struct flags 15 | { 16 | int plus; 17 | int space; 18 | int hash; 19 | } flags_t; 20 | 21 | /** 22 | * struct printHandler - struct to choose the right function depending 23 | * on the format specifier passed to _printf() 24 | * @c: format specifier 25 | * @f: pointer to the correct printing function 26 | */ 27 | typedef struct printHandler 28 | { 29 | char c; 30 | int (*f)(va_list ap, flags_t *f); 31 | } ph; 32 | 33 | /* print_nums */ 34 | int print_int(va_list l, flags_t *f); 35 | void print_number(int n); 36 | int print_unsigned(va_list l, flags_t *f); 37 | int count_digit(int i); 38 | 39 | /* print_bases */ 40 | int print_hex(va_list l, flags_t *f); 41 | int print_hex_big(va_list l, flags_t *f); 42 | int print_binary(va_list l, flags_t *f); 43 | int print_octal(va_list l, flags_t *f); 44 | 45 | /* converter */ 46 | char *convert(unsigned long int num, int base, int lowercase); 47 | 48 | /* _printf */ 49 | int _printf(const char *format, ...); 50 | 51 | /* get_print */ 52 | int (*get_print(char s))(va_list, flags_t *); 53 | 54 | /* get_flag */ 55 | int get_flag(char s, flags_t *f); 56 | 57 | /* print_alpha */ 58 | int print_string(va_list l, flags_t *f); 59 | int print_char(va_list l, flags_t *f); 60 | 61 | /* write_funcs */ 62 | int _putchar(char c); 63 | int _puts(char *str); 64 | 65 | /* print_custom */ 66 | int print_rot13(va_list l, flags_t *f); 67 | int print_rev(va_list l, flags_t *f); 68 | int print_bigS(va_list l, flags_t *f); 69 | 70 | /* print_address */ 71 | int print_address(va_list l, flags_t *f); 72 | 73 | /* print_percent */ 74 | int print_percent(va_list l, flags_t *f); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /man_3_printf: -------------------------------------------------------------------------------- 1 | .TH man 3 "17 March 2019" "HOLBERTON SCHOOL" "_PRINTF" 2 | .SH NAME 3 | .B _printf 4 | - formatted output conversion 5 | .SH SYNOPSIS 6 | .B #include \(dqholberton.h\(dq 7 | .sp 8 | .B int _printf(const char * 9 | .I format 10 | .B , ...); 11 | .SH DESCRIPTION 12 | The function _printf is a variadic function that produces a string according to a 13 | .I format 14 | and prints it to the standard output, much like the C standard library function printf. It can receive a variable number of arguments. 15 | This function has been created in the context of a first-year project for Holberton School. 16 | .sp 17 | .B Return value 18 | .sp 19 | On success, _printf returns the number of characters printed. If 20 | .I format 21 | is NULL or if the functions encounters any errors, it returns -1. 22 | .sp 23 | .B Format of the format string 24 | .sp 25 | The format string can contain any characters, just like a regular string, in double quotes, which will be printed as is. For example, _printf(\(dqHello\(dq) will print: Hello. 26 | However, this format string can contain 27 | .I conversion specifiers. 28 | These start with a %, and are followed with a character (see 29 | .I conversion specifiers 30 | ). Special characters like a new line are escaped, for example _printf(\(dq\\n\(dq) will print a new line. 31 | .sp 32 | .B Conversion specifiers 33 | .sp 34 | These are the characters that specify the type of the variable that needs to be printed. The variables to be printed are separated from the format string with a comma. Each variable passed to _printf need to have a conversion specifier. 35 | .sp 36 | .B i, d 37 | - Both these specifiers are for 38 | .I int 39 | arguments. They convert the variable to a decimal number, positive or negative. 40 | .sp 41 | .B c 42 | - Prints a 43 | .I single character. 44 | .sp 45 | .B s 46 | - Prints an entire 47 | .I string. 48 | .sp 49 | .B u 50 | - Prints an 51 | .I unsigned int. 52 | .sp 53 | .B x, X 54 | - Respecively print a number in lowercase and uppercase 55 | .I hexadecimal 56 | base. 57 | .sp 58 | .B o, b 59 | - Respectively print a number in 60 | .I octal 61 | and 62 | .I binary 63 | base. 64 | .sp 65 | .B % 66 | - Acts like an escape for the character %. To print \(dq%\(dq, the format string should contain \(dq%%\(dq. 67 | .sp 68 | .B r, R 69 | - Respectively print a string in reverse and in ROT13 encryption. 70 | .sp 71 | .B S 72 | - Prints a string, but non-printable characters are printed this way: \\x, followed by the ASCII code value in uppercase hexadecimal. 73 | .sp 74 | .B p 75 | - Prints an address, given by a pointer variable 76 | .sp 77 | .B Flag characters for conversion specifiers 78 | .sp 79 | .B + 80 | - Prints a plus sign in front of positive signed integers and a minus sign in front of negative signed integers. 81 | + overrides a space when both flags are given. 82 | .sp 83 | .B ' ' 84 | - Prints a space in front of signed integers. 85 | .sp 86 | .B # 87 | - Modifier for unsigned conversions. For x, prepends \(dq0x\(dq, and for X, prepends \(dq0X\(dq. For o, if the converted number doesn't already begin with a 0, prepends a 0. 88 | .sp 89 | .SH SEE ALSO 90 | .I printf(3) 91 | .I _putchar.c 92 | .SH NOTES 93 | _printf uses a custom character printing function called _putchar, that uses the system call write(). 94 | _putchar uses a static buffer of 1024 bytes and a static incrementing variable. 95 | That way, everytime _putchar is called inside _printf, the character is stored inside the buffer and the function moves to the next character, 96 | until _printf calls _putchar(-1), which \(dqflushes\(dq the buffer and resets the incrementing variable to 0. 97 | That way, _putchar only needs to call write one time, passing to it the whole buffer and the number of bytes in it, which is given by the value of the incrementing variable. 98 | .sp 99 | .SH BUGS 100 | _printf does not take care of length and precision modifiers yet. For example, _printf(\(dq%hx\(dq) will not produce the same output as the call to the standard library printf. 101 | .SH AUTHORS 102 | Tu Vo and Laura Roudge, Cohort 8. 103 | -------------------------------------------------------------------------------- /print_address.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * print_address - prints address of input in hexa format 5 | * @l: va_list arguments from _printf 6 | * @f: pointer to the struct flags that determines 7 | * if a flag is passed to _printf 8 | * Return: number of char printed 9 | */ 10 | int print_address(va_list l, flags_t *f) 11 | { 12 | char *str; 13 | unsigned long int p = va_arg(l, unsigned long int); 14 | 15 | register int count = 0; 16 | 17 | (void)f; 18 | 19 | if (!p) 20 | return (_puts("(nil)")); 21 | str = convert(p, 16, 1); 22 | count += _puts("0x"); 23 | count += _puts(str); 24 | return (count); 25 | } 26 | -------------------------------------------------------------------------------- /print_alpha.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * print_string - loops through a string and prints 5 | * every character 6 | * @l: va_list arguments from _printf 7 | * @f: pointer to the struct flags that determines 8 | * if a flag is passed to _printf 9 | * Return: number of char printed 10 | */ 11 | int print_string(va_list l, flags_t *f) 12 | { 13 | char *s = va_arg(l, char *); 14 | 15 | (void)f; 16 | 17 | if (!s) 18 | s = "(null)"; 19 | return (_puts(s)); 20 | } 21 | 22 | /** 23 | * print_char - prints a character 24 | * @l: va_list arguments from _printf 25 | * @f: pointer to the struct flags that determines 26 | * if a flag is passed to _printf 27 | * Return: number of char printed 28 | */ 29 | int print_char(va_list l, flags_t *f) 30 | { 31 | (void)f; 32 | _putchar(va_arg(l, int)); 33 | return (1); 34 | } 35 | -------------------------------------------------------------------------------- /print_bases.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * print_hex - prints a number in hexadecimal base, 5 | * in lowercase 6 | * @l: va_list arguments from _printf 7 | * @f: pointer to the struct flags that determines 8 | * if a flag is passed to _printf 9 | * Description: the function calls convert() which in turns converts the input 10 | * number into the correct base and returns it as a string 11 | * Return: the number of char printed 12 | */ 13 | int print_hex(va_list l, flags_t *f) 14 | { 15 | unsigned int num = va_arg(l, unsigned int); 16 | char *str = convert(num, 16, 1); 17 | int count = 0; 18 | 19 | if (f->hash == 1 && str[0] != '0') 20 | count += _puts("0x"); 21 | count += _puts(str); 22 | return (count); 23 | } 24 | 25 | /** 26 | * print_hex_big - prints a number in hexadecimal base, 27 | * in uppercase 28 | * @l: va_list arguments from _printf 29 | * @f: pointer to the struct that determines 30 | * if a flag is passed to _printf 31 | * Description: the function calls convert() which in turns converts the input 32 | * number into the correct base and returns it as a string 33 | * Return: the number of char printed 34 | */ 35 | int print_hex_big(va_list l, flags_t *f) 36 | { 37 | unsigned int num = va_arg(l, unsigned int); 38 | char *str = convert(num, 16, 0); 39 | int count = 0; 40 | 41 | if (f->hash == 1 && str[0] != '0') 42 | count += _puts("0X"); 43 | count += _puts(str); 44 | return (count); 45 | } 46 | 47 | /** 48 | * print_binary - prints a number in base 2 49 | * @l: va_list arguments from _printf 50 | * @f: pointer to the struct that determines 51 | * if a flag is passed to _printf 52 | * Description: the function calls convert() which in turns converts the input 53 | * number into the correct base and returns it as a string 54 | * Return: the number of char printed 55 | */ 56 | int print_binary(va_list l, flags_t *f) 57 | { 58 | unsigned int num = va_arg(l, unsigned int); 59 | char *str = convert(num, 2, 0); 60 | 61 | (void)f; 62 | return (_puts(str)); 63 | } 64 | 65 | /** 66 | * print_octal - prints a number in base 8 67 | * @l: va_list arguments from _printf 68 | * @f: pointer to the struct that determines 69 | * if a flag is passed to _printf 70 | * Description: the function calls convert() which in turns converts the input 71 | * number into the correct base and returns it as a string 72 | * Return: the number of char printed 73 | */ 74 | int print_octal(va_list l, flags_t *f) 75 | { 76 | unsigned int num = va_arg(l, unsigned int); 77 | char *str = convert(num, 8, 0); 78 | int count = 0; 79 | 80 | if (f->hash == 1 && str[0] != '0') 81 | count += _putchar('0'); 82 | count += _puts(str); 83 | return (count); 84 | } 85 | -------------------------------------------------------------------------------- /print_custom.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * print_bigS - Non printable characters 5 | * (0 < ASCII value < 32 or >= 127) are 6 | * printed this way: \x, followed by the ASCII code 7 | * value in hexadecimal (upper case - always 2 characters) 8 | * @l: va_list arguments from _printf 9 | * @f: pointer to the struct flags that determines 10 | * if a flag is passed to _printf 11 | * Return: number of char printed 12 | */ 13 | int print_bigS(va_list l, flags_t *f) 14 | { 15 | int i, count = 0; 16 | char *res; 17 | char *s = va_arg(l, char *); 18 | 19 | (void)f; 20 | if (!s) 21 | return (_puts("(null)")); 22 | 23 | for (i = 0; s[i]; i++) 24 | { 25 | if (s[i] > 0 && (s[i] < 32 || s[i] >= 127)) 26 | { 27 | _puts("\\x"); 28 | count += 2; 29 | res = convert(s[i], 16, 0); 30 | if (!res[1]) 31 | count += _putchar('0'); 32 | count += _puts(res); 33 | } 34 | else 35 | count += _putchar(s[i]); 36 | } 37 | return (count); 38 | } 39 | 40 | /** 41 | * print_rev - prints a string in reverse 42 | * @l: argument from _printf 43 | * @f: pointer to the struct flags that determines 44 | * if a flag is passed to _printf 45 | * Return: length of the printed string 46 | */ 47 | int print_rev(va_list l, flags_t *f) 48 | { 49 | int i = 0, j; 50 | char *s = va_arg(l, char *); 51 | 52 | (void)f; 53 | if (!s) 54 | s = "(null)"; 55 | 56 | while (s[i]) 57 | i++; 58 | 59 | for (j = i - 1; j >= 0; j--) 60 | _putchar(s[j]); 61 | 62 | return (i); 63 | } 64 | 65 | /** 66 | * print_rot13 - prints a string using rot13 67 | * @l: list of arguments from _printf 68 | * @f: pointer to the struct flags that determines 69 | * if a flag is passed to _printf 70 | * Return: length of the printed string 71 | */ 72 | int print_rot13(va_list l, flags_t *f) 73 | { 74 | int i, j; 75 | char rot13[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 76 | char ROT13[] = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"; 77 | char *s = va_arg(l, char *); 78 | 79 | (void)f; 80 | for (j = 0; s[j]; j++) 81 | { 82 | if (s[j] < 'A' || (s[j] > 'Z' && s[j] < 'a') || s[j] > 'z') 83 | _putchar(s[j]); 84 | else 85 | { 86 | for (i = 0; i <= 52; i++) 87 | { 88 | if (s[j] == rot13[i]) 89 | _putchar(ROT13[i]); 90 | } 91 | } 92 | } 93 | 94 | return (j); 95 | } 96 | 97 | /** 98 | * print_percent - prints a percent 99 | * @l: va_list arguments from _printf 100 | * @f: pointer to the struct flags in which we turn the flags on 101 | * Return: number of char printed 102 | */ 103 | int print_percent(va_list l, flags_t *f) 104 | { 105 | (void)l; 106 | (void)f; 107 | return (_putchar('%')); 108 | } 109 | -------------------------------------------------------------------------------- /print_nums.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * print_int - prints an integer 5 | * @l: va_list of arguments from _printf 6 | * @f: pointer to the struct flags determining 7 | * if a flag is passed to _printf 8 | * Return: number of char printed 9 | */ 10 | int print_int(va_list l, flags_t *f) 11 | { 12 | int n = va_arg(l, int); 13 | int res = count_digit(n); 14 | 15 | if (f->space == 1 && f->plus == 0 && n >= 0) 16 | res += _putchar(' '); 17 | if (f->plus == 1 && n >= 0) 18 | res += _putchar('+'); 19 | if (n <= 0) 20 | res++; 21 | print_number(n); 22 | return (res); 23 | } 24 | 25 | /** 26 | * print_unsigned - prints an unsigned integer 27 | * @l: va_list of arguments from _printf 28 | * @f: pointer to the struct flags determining 29 | * if a flag is passed to _printf 30 | * Return: number of char printed 31 | */ 32 | int print_unsigned(va_list l, flags_t *f) 33 | { 34 | unsigned int u = va_arg(l, unsigned int); 35 | char *str = convert(u, 10, 0); 36 | 37 | (void)f; 38 | return (_puts(str)); 39 | } 40 | 41 | /** 42 | * print_number - helper function that loops through 43 | * an integer and prints all its digits 44 | * @n: integer to be printed 45 | */ 46 | void print_number(int n) 47 | { 48 | unsigned int n1; 49 | 50 | if (n < 0) 51 | { 52 | _putchar('-'); 53 | n1 = -n; 54 | } 55 | else 56 | n1 = n; 57 | 58 | if (n1 / 10) 59 | print_number(n1 / 10); 60 | _putchar((n1 % 10) + '0'); 61 | } 62 | 63 | /** 64 | * count_digit - returns the number of digits in an integer 65 | * for _printf 66 | * @i: integer to evaluate 67 | * Return: number of digits 68 | */ 69 | int count_digit(int i) 70 | { 71 | unsigned int d = 0; 72 | unsigned int u; 73 | 74 | if (i < 0) 75 | u = i * -1; 76 | else 77 | u = i; 78 | while (u != 0) 79 | { 80 | u /= 10; 81 | d++; 82 | } 83 | return (d); 84 | } 85 | -------------------------------------------------------------------------------- /tests/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "holberton.h" 4 | 5 | /** 6 | * main - Entry point 7 | * 8 | * Return: Always 0 9 | */ 10 | int main(void) 11 | { 12 | int len; 13 | int len2; 14 | unsigned int ui; 15 | void *addr; 16 | 17 | len = _printf("Let's try to printf a simple sentence.\n"); 18 | len2 = printf("Let's try to printf a simple sentence.\n"); 19 | ui = (unsigned int)INT_MAX + 1024; 20 | addr = (void *)0x7ffe637541f0; 21 | _printf("Length:[%d, %i]\n", len, len); 22 | printf("Length:[%d, %i]\n", len2, len2); 23 | _printf("Negative:[%d]\n", -762534); 24 | printf("Negative:[%d]\n", -762534); 25 | _printf("Unsigned:[%u]\n", ui); 26 | printf("Unsigned:[%u]\n", ui); 27 | _printf("Unsigned octal:[%o]\n", ui); 28 | printf("Unsigned octal:[%o]\n", ui); 29 | _printf("Unsigned hexadecimal:[%x, %X]\n", ui, ui); 30 | printf("Unsigned hexadecimal:[%x, %X]\n", ui, ui); 31 | _printf("Character:[%c]\n", 'H'); 32 | printf("Character:[%c]\n", 'H'); 33 | _printf("String:[%s]\n", "I am a string !"); 34 | printf("String:[%s]\n", "I am a string !"); 35 | _printf("Address:[%p]\n", addr); 36 | printf("Address:[%p]\n", addr); 37 | len = _printf("Percent:[%%]\n"); 38 | len2 = printf("Percent:[%%]\n"); 39 | _printf("Len:[%d]\n", len); 40 | printf("Len:[%d]\n", len2); 41 | _printf("Unknown:[%r]\n"); 42 | //printf("Unknown:[%r]\n"); 43 | return (0); 44 | } 45 | -------------------------------------------------------------------------------- /write_funcs.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | #include 3 | 4 | /** 5 | * _putchar - writes the character c to stdout 6 | * @c: The character to print 7 | * Return: On success 1. 8 | * On error, -1 is returned, and errno is set appropriately. 9 | * Description: _putchar uses a local buffer of 1024 to call write 10 | * as little as possible 11 | */ 12 | int _putchar(char c) 13 | { 14 | static char buf[1024]; 15 | static int i; 16 | 17 | if (c == -1 || i >= 1024) 18 | { 19 | write(1, &buf, i); 20 | i = 0; 21 | } 22 | if (c != -1) 23 | { 24 | buf[i] = c; 25 | i++; 26 | } 27 | return (1); 28 | } 29 | 30 | /** 31 | * _puts - prints a string to stdout 32 | * @str: pointer to the string to print 33 | * Return: number of chars written 34 | */ 35 | int _puts(char *str) 36 | { 37 | register int i; 38 | 39 | for (i = 0; str[i] != '\0'; i++) 40 | _putchar(str[i]); 41 | return (i); 42 | } 43 | --------------------------------------------------------------------------------