Printf encoding with an array of function pointers

I am trying to code the printf function. The problem is that my code is getting very dirty and I need help to try to organize it and work (hopefully). I was told that I should use a "array of function pointers", so I tried below (ft_print_it), as you can see, but I donโ€™t know how to structure my code so that I can use a large array of function pointers for each function, such like int_decimal_octal and friends. Can you help me? Where can I name them?

Also, I realized that the little function below (cast_in_short) gives me the same result as printf if I write the output with my ft_putnbr. My second question is this: can I make my printf work with such small functions? Thank you very much.

int cast_in_short(int truc) { truc = (short)truc; return (truc); } /* here in the main I noticed that I get the same behaviour between my putnbr and printf thanks to my little function cast_in_short. This is the kind of function I want to use and put into an array of pointer of functions in order to make my printf work */ int main() { int n = 32769; n = cast_in_short(n); ft_putnbr(n); printf("\n"); return (0); } /* function to launch ft_print_it */ int ft_print_str_spec(va_list ap, char *flag) { if (ft_strlen(flag) == 1) ft_putstr(va_arg(ap, char *)); else { ft_nbzero(ap, flag, 0); ft_putstr(va_arg(ap, char *)); } return (1); } int ft_print_oct(va_list ap, char *flag) { if (ft_strlen(flag) == 1) ft_putnbr(decimal_octal((va_arg(ap, int)))); else { ft_nbzero(ap, flag, 1); ft_putnbr(decimal_octal((va_arg(ap, int)))); } return (1); } #include "libft.h" #include <stdarg.h> #include <stdio.h> char *ft_strjoin2(char const *s1, char const c); #include "libft.h" #include <stdarg.h> #include <stdio.h> int decimal_octal(int n) /* Function to convert decimal to octal */ { int rem; int i; int octal; i = 1; octal = 0; while (n != 0) { rem = n % 8; n /= 8; octal += rem * i; i *= 10; } return (octal); } 
+5
source share
2 answers

I think the best way to organize your code in order to avoid a function like your "flag_code" is to use an array of structures. With a structure containing char (corresponding to the flag) and a function pointer.

For instance:

 typedef struct fptr { char op; int (*ptr)(va_list); } fptr; 

And set it like this (with {'flag', name of the corresponding function}):

 fptr fptrs[]= { { 's', ft_print_nb_spec }, { 'S', ft_print_nb_up }, { 0, NULL } }; 

Then, when you know that char is after% (flag), you can do something like this:

  int i = -1; while (fptrs[++i].op != flag && fptrs[i].op != 0); if (fptrs[i].op != 0) { fptrs[i].ptr(); } 

For example, if the flag = 'S', the while loop will stop when I = 1, and when you call fptrs [1] .ptr (), you will call the corresponding function in the structure.

+2
source

I think, instead of making your code messy with function pointers, because at the end you cannot specialize the printf function without providing a format, there is no function overload function or template function in C. My suggestion is a special printf function by type.

 // print seperator void p (int end) { printf(end?"\n":" "); } // print decimal void pi (long long n) { printf("%lld",n); } // print unsigned void pu (unsigned long long n) { printf("%llu",n); } // print floating point void pf (double n) { printf("%g",n); } // print char void pc (char n) { printf("%c",n); } // print string void ps (char* n) { printf("%s",n); } 

Test try here

 pi(999),p(0),pf(3.16),p(0),ps("test"),p(1); 

Output

 999 3.16 test 

Another variant

In theory, you can define a polymorphic print function in a structure if you can do something like this. I have not tested this yet.

 struct Node { enum NodeType {Long,Double,Char,String} type; union {long l,double d,char c,char* s}; }; void p(Node* n) { switch (n->type) { case Node::NodeType::Long: printf("%ld", n->l); case Node::NodeType::Double: printf("%g",n->d); case Node::NodeType::Char: printf("%c",n->c); case Node::NodeType::String: printf("%s",n->s); } } 
0
source

Source: https://habr.com/ru/post/1240062/


All Articles