开发者

How to print both to stdout and file in C

I read this topic, but his problem maybe different from mine Writing to both stdout & a file

I want to write a function, that function need to print out to both stdout and a file.开发者_JS百科 My C program gets user input by scanf.

I intend to write a function like printf but I don't really know how:

I tried this, but it only can work with "pure" string, can't convert %d, %.*lf (my print function only need two conversions)

void dupPrint(FILE *fp,char *string)
{
    printf("%s",string);
    fprintf(fp,"%s",string);

    return;
}

I tried dup2 and freopen but they didn't work for me.

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
    int i;
    int file = open("input3.txt", O_APPEND | O_WRONLY);
    if(file < 0) return 1;

    if(dup2(file,1) < 0) return 1;

    printf("Redirect to file!\n");
    printf("enter i : ");
    scanf("%d",&i);



    return 0;
}

This dup2() tutorial only print to file.

I also tried tee, but may be it not work because I have to get input from user (if work, it's not "fair" because tee isn't in my program).

I think implement a printf-like will solved problem but I don't know how to convert .*lf (print out double with user-enter precision)

#include <stdio.h>
#include <stdarg.h>
void dupPrint(FILE *fp,char *fmt,  ...)
{
    va_list ap;
    char *p, *sval;
    int ival;
    double dval;

    va_start (ap, fmt); //make ap point to 1st unnamed arg
    for(p = fmt; *p; p++)
       {
           if (*p != '%') {
               putchar(*p);
               continue;
           }
           switch (*++p) {
               case 'd':
                   ival = va_arg(ap, int);
                   printf("%d", ival);
                   break;
               case '.*lf' //?????
           }
       }       

}

Can anyone suggest a solution for my problem?


Fortunately, you don't need to. You just want to use the v variants of printf and fprintf that take a va_list instead of your passing arguments directly:

void tee(FILE *f, char const *fmt, ...) { 
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);
    va_start(ap, fmt);
    vfprintf(f, fmt, ap);
    va_end(ap);
}


You can implement your dupPrint function using vfprintf and va_list/ va_start / va_end.


in the mid-layer:

#define DUPPRINT(fp, fmt...) do {printf(fmt);fprintf(fp,fmt);} while(0)

in your app code:

...
DUPPRINT(fd, "%s:%d\n", val_name, val_v);
...


Use a variadic function and vprintf!

void dupPrint(FILE *fp,char *fmt,  ...)
{
    va_list ap;

    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);

    va_start(ap, fmt);
    vfprintf(fp, fmt, ap);
    va_end(ap);
}

Optionally, implement vdupPrint, have dupPrint call vdupPrint, and use va_copy (if C99 is available) to duplicate the va_list instead of the stop-and-restart method I used. (If va_copy is not available to you, you'll have to start two separate va_lists and pass them both to vdupPrint, which is a sub-optimal solution but will work for C89 safely.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜