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_list
s and pass them both to vdupPrint
, which is a sub-optimal solution but will work for C89 safely.)
精彩评论