2016-01-07 23 views
5

我想编写printf函数。问题是我的代码变得非常混乱,我需要一些帮助来尝试使其组织起来(希望)。我被告知应该使用“数组函数指针”,所以我在下面尝试(ft_print_it),正如你所看到的,但我不知道如何构造我的代码,以便我可以使用大量的函数指针来放置每个函数都像int_decimal_octal和朋友。你能帮助我吗?我可以从哪里打电话给他们?使用函数指针数组编码printf

另外,我意识到下面的小函数(cast_in_short)给了我和printf相同的结果,如果我用我的ft_putnbr写出输出的话。我的第二个问题是:我可以让我的printf使用这样的小功能吗?非常感谢。

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); 
} 
+0

您是否在某些免费软件C标准库中研究了'printf'的源代码? –

+0

是的,我尝试过,但他们不使用函数指针数组... – zakk8889

+1

你似乎对C相当陌生,你为什么要实现像printf这样的复杂函数? – Stuart

回答

2

我认为组织你的代码避免像“flag_code”这样的函数的最好方法是使用一个结构数组。使用包含char(对应于标志)和函数指针的结构。

例如:

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

而且instatiate这样说,这(与{相应功能的 '标志',名称}):

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

然后,当你知道%后有焦(国旗)你可以这样做:

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

例如,如果flag ='S'while循环将停止时i = 1,当您调用fptrs [1] .ptr()时,您将调用结构中的相应函数。

0

我认为不是通过使用函数指针来使你的代码变得混乱,因为最终你不能在没有提供格式的情况下专门化printf函数,在C中没有函数重载或模板函数。我的建议是按特殊类型打印特殊的printf函数。

// 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); } 

测试try here

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

输出

999 3.16 test 

另一个选项

从理论上讲,你可以在一个结构定义多态性打印功能,如果你可以做一些事情喜欢这个。我还没有测试过。

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

使用printf实现printf有什么意义? – realUser404

+0

@ realUser404 OP正试图通过printf找到一种专业化的方法,不难看出他的代码看起来如何混乱,我提供了一个简单的版本来说明如何应用,我的例子表明它可以在同一行,类似于C++中的std :: cout简单。 –