在执行`freopen(“file.txt”, “wb”, stdout);`之后在终端中打印:

huangapple go评论57阅读模式
英文:

Print in terminal after`freopen("file.txt", "wb", stdout);` (or similar solution to preserve a printing function)

问题

I want to store the printed output of a function with freopen("file.txt", "wb", stdout); (or another solution, but the function matrix_output_printf() should remain untouched.

However, I want to be able to further print something after having closed fclose(stdout); as shown below but the hello of printf("hello"); does not appear in the terminal. Is it possible to print "hello" in another way (on a MacOS system).

/* 
 *  main.c 
 *  https://stackoverflow.com/questions/75349098/stream-the-output-of-a-void-function-using-printf/75352112#75352112
 */
#include <stdio.h>
#include <stdlib.h>

void matrix_output();

void matrix_output_printf(){
  for (int i = 0; i < 3; i++){
    for (int j = 0; j < 3; j++){
      printf("%d\t", i+j);
    }
    printf("\n");
  }
}

int main ()
{ 
  freopen("file.txt", "wb", stdout);
  matrix_output_printf();
  fclose(stdout);
  printf("hello");
  return 0;
}

Edit

The code provided in the answer is not working on my MacOS computer ( 'io.h' file not found). Is there another solution portable for UNIX-like systems?

英文:

I want to store the printed output of a function with freopen(&quot;file.txt&quot;, &quot;wb&quot;, stdout); (or another solution, but the function matrix_output_printf() should remained untouched.
However, I want to be able to further print something after having closed fclose(stdout); as shown below but the hello of printf(&quot;hello&quot;); does not appear in terminal. Is it possible print hello in another way (on a MacOS system).

/* 
 *  main.c 
 *  https://stackoverflow.com/questions/75349098/stream-the-output-of-a-void-function-using-printf/75352112#75352112
 */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void matrix_output();

void matrix_output_printf(){
  for (int i = 0; i &lt; 3; i++){
    for (int j = 0; j &lt; 3; j++){
      printf(&quot;%d\t&quot;, i+j);
    }
    printf(&quot;\n&quot;);
  }
}

int main ()
{ 
  freopen(&quot;file.txt&quot;, &quot;wb&quot;, stdout);
  matrix_output_printf();
  fclose(stdout);
  printf(&quot;hello&quot;);
  return 0;
}

Edit

The code provided in the answer is not working on my MacOS computer ( &#39;io.h&#39; file not found). Is there another solution portable for UNIX like systems?

答案1

得分: 1

以下是您代码的中文翻译部分:

已在我的Windows计算机上测试并验证
#include <stdio.h>
#include <stdlib.h>
#include <io.h>;

void matrix_output_printf() {
    for( int i = 0; i < 3; i++ ) {
        for( int j = 0; j < 3; j++ )
            printf( "%d\t", i+j );
        printf( "\n" );
    }
}

int main( void ) {
    int saved = _dup( fileno( stdout ) );

    freopen( "file.txt", "w", stdout );
    matrix_output_printf();
    fclose( stdout );

    _dup2( saved, 1 );

    printf( "hello\n" );

    return 0;
}
英文:

Tried and tested on my Windows box:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;io.h&gt;

void matrix_output_printf() {
	for( int i = 0; i &lt; 3; i++ ) {
		for( int j = 0; j &lt; 3; j++ )
			printf( &quot;%d\t&quot;, i+j );
		printf( &quot;\n&quot; );
	}
}

int main( void ) {
	int saved = _dup( fileno( stdout ) );

	freopen( &quot;file.txt&quot;, &quot;w&quot;, stdout );
	matrix_output_printf();
	fclose( stdout );

	_dup2( saved, 1 );

	printf( &quot;hello\n&quot; );

	return 0;
}

答案2

得分: 0

If stdout was originally tied to the console, you can reopen the stream to /dev/tty:

#include <stdio.h>;

void matrix_output_printf(void) {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d\t", i + j);
        }
        printf("\n");
    }
}

int main() { 
    freopen("file.txt", "w", stdout);
    matrix_output_printf();
    freopen("/dev/tty", "w", stdout);
    printf("hello");
    return 0;
}

This should work on most unix systems, such as macOS, but if stdout was redirected to another file or device, reopening it with freopen won't work. You could try and duplicate the system handle with dup() and use fdopen() to open a standard stream after closing stdout, but there is no guarantee that the stream returned by fdopen will be the same as stdout.

Using freopen for your purpose is a hack. A much better approach is to rewrite matrix_output_printf to take a FILE * argument for the output stream, or a const char *filename for the name of the file to produce:

void matrix_output_printf(const char *filename) {
    FILE *fp = stdout;
    if (filename) {
        fp = fopen(filename, "w");
        if (fp == NULL) {
            /* handle error */
            return;
        }
    }
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            fprintf(fp, "%d\t", i + j);
        }
        fprintf(fp, "\n");
    }
    if (filename)
        fclose(fp);
}
英文:

If stdout was originally tied to the console, you can reopen the stream to /dev/tty:

#include &lt;stdio.h&gt;

void matrix_output_printf(void) {
    for (int i = 0; i &lt; 3; i++) {
        for (int j = 0; j &lt; 3; j++) {
            printf(&quot;%d\t&quot;, i + j);
        }
        printf(&quot;\n&quot;);
    }
}

int main() { 
    freopen(&quot;file.txt&quot;, &quot;w&quot;, stdout);
    matrix_output_printf();
    freopen(&quot;/dev/tty&quot;, &quot;w&quot;, stdout);
    printf(&quot;hello&quot;);
    return 0;
}

This should work on most unix systems, such as macOS, but if stdout was redirected to another file or device, reopening it with freopen won't work. You could try and duplicate the system handle with dup() and use fdopen() to open a standard stream after closing stdout, but there is no guarantee that the stream returned by fdopen will be the same as stdout.

Using freopen for your purpose is a hack. A much better approach is to rewrite matrix_output_printf to take a FILE * argument for the output stream, or a const char *filename for the name of the file to produce:

void matrix_output_printf(const char *filename) {
    FILE *fp = stdout;
    if (filename) {
        fp = fopen(filename, &quot;w&quot;);
        if (fp == NULL) {
            /* handle error */
            return;
        }
    }
    for (int i = 0; i &lt; 3; i++) {
        for (int j = 0; j &lt; 3; j++) {
            fprintf(fp, &quot;%d\t&quot;, i + j);
        }
        fprintf(fp, &quot;\n&quot;);
    }
    if (filename)
        fclose(fp);
}

答案3

得分: 0

另一个选项:

  1. 刷新流
  2. 在调用该函数之前,复制stdout的文件描述符,将文件描述符复制到所需文件的流的原始文件描述符值
  3. 调用函数
  4. 恢复原始的stdout描述符

类似于这样:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

void matrix_output_printf(void){
  for (int i = 0; i < 3; i++){
    for (int j = 0; j < 3; j++){
      printf("%d\t", i+j);
    }
    printf("\n");
  }
}

int main()
{ 
  int fd = open("file.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
  int savedStdoutFD = dup(fileno(stdout));
  fflush(stdout);
  dup2(fd, STDOUT_FILENO);
  close(fd);

  matrix_output_printf();

  fflush(stdout);
  dup2(savedStdoutFD, STDOUT_FILENO);
  close(savedStdoutFD);

  printf("hello\n");
  return 0;
}

请注意,此代码在多线程进程中使用时本质上是不安全的。

@chqrlie给出了最佳答案:"一个更好的方法是重写matrix_output_printf以接受输出流的FILE *参数,或者文件名的const char *filename来生成文件"。

英文:

Another option:

  1. Flush the stream
  2. Duplicate stdout's file descriptor before calling the function, duplicate a file descriptor open to the desired file to the stream's original file descriptor value
  3. Call the function
  4. Restore the original stdout descriptor

Similar to this:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;unistd.h&gt;

void matrix_output_printf(void){
  for (int i = 0; i &lt; 3; i++){
    for (int j = 0; j &lt; 3; j++){
      printf(&quot;%d\t&quot;, i+j);
    }
    printf(&quot;\n&quot;);
  }
}

int main()
{ 
  int fd = open(&quot;file.txt&quot;, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  int savedStdoutFD = dup(fileno(stdout));
  fflush(stdout);
  dup2(fd, STDOUT_FILENO);
  close(fd);

  matrix_output_printf();

  fflush(stdout);
  dup2(savedStdoutFD, STDOUT_FILENO);
  close(savedStdoutFD);

  printf(&quot;hello\n&quot;);
  return 0;
}

Note that this code is inherently unsafe to use in a multithreaded process.

@chqrlie had the best answer: "A much better approach is to rewrite matrix_output_printf to take a FILE * argument for the output stream, or a const char *filename for the name of the file to produce".

huangapple
  • 本文由 发表于 2023年2月6日 06:07:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75355851.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定