【问题标题】:How to print both to stdout and file in C如何在C中同时打印到标准输出和文件
【发布时间】:2011-06-21 03:59:32
【问题描述】:

我读过这个话题,但他的问题可能与我的不同 Writing to both stdout & a file

我想编写一个函数,该函数需要同时打印到标准输出和文件。我的 C 程序通过 scanf 获取用户输入。

我打算写一个类似 printf 的函数,但我真的不知道怎么写:

我试过了,但它只能使用“纯”字符串,不能转换 %d, %.*lf(我的打印功能只需要两次转换)

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

    return;
}

我尝试了 dup2 和 freopen,但它们对我不起作用。

#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;
}

本 dup2() 教程仅打印到文件。

我也尝试过 tee,但它可能不起作用,因为我必须从用户那里获得输入(如果有效,它不“公平”,因为 tee 不在我的程序中)。

我认为实现类似 printf 会解决问题,但我不知道如何转换 .*lf (以用户输入的精度打印出双精度)

#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' //?????
           }
       }       

}

谁能为我的问题提出解决方案?

【问题讨论】:

  • fprintf 可以打印到标准输出以及文件
  • 可以打开一个调用tee 的管道并将数据打印到该文件句柄,但这可能不够可靠(如果这需要在没有@987654326 的系统上运行@)。
  • "我的 C 程序通过 scanf 获取用户输入" - 你正处于一个痛苦的世界 :-)

标签: c file-io


【解决方案1】:

幸运的是,您不需要这样做。您只想使用 printffprintfv 变体,它们采用 va_list 而不是直接传递参数:

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

【讨论】:

    【解决方案2】:

    您可以使用vfprintfva_list/ va_start / va_end 来实现您的dupPrint 函数。

    【讨论】:

      【解决方案3】:

      使用可变参数函数和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);
      }
      

      (可选)实现vdupPrint,让dupPrint 调用vdupPrint,并使用va_copy(如果C99 可用)复制va_list,而不是我使用的停止和重启方法。 (如果您无法使用 va_copy,您必须启动两个单独的 va_lists 并将它们都传递给 vdupPrint,这是一个次优解决方案,但可以安全地用于 C89。)

      【讨论】:

        【解决方案4】:

        在中间层:

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

        在您的应用代码中:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-09
          • 2015-08-31
          • 2014-07-22
          • 2016-03-04
          • 2022-08-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多