pantalla - imprimir datos en c
¿Por qué printf no se vacía después de la llamada a menos que haya una nueva línea en la cadena de formato? (9)
¿Por qué printf
no se vacía después de la llamada a menos que haya una nueva línea en la cadena de formato? Es este comportamiento POSIX? ¿Cómo podría tener printf
inmediatamente vaciar cada vez?
La secuencia stdout
está almacenada en búfer, por lo que solo mostrará lo que hay en el búfer después de que llegue a una nueva línea (o cuando se le indique). Tienes algunas opciones para imprimir de inmediato:
Imprima en stderr en lugar de usar fprintf
:
fprintf(stderr, "I will be printed immediately");
Flush stdout siempre que lo necesite para usar fflush
:
printf("Buffered, will be flushed");
fflush(stdout); // Will now print everything in the stdout buffer
Edición : Del comentario de Andy Ross a continuación, también puede deshabilitar el almacenamiento en búfer en la setbuf
utilizando setbuf
:
setbuf(stdout, NULL);
No, no es el comportamiento de POSIX, es el comportamiento de ISO (bueno, es el comportamiento de POSIX, pero solo en la medida en que se ajustan a ISO).
La salida estándar es un búfer de línea si puede detectarse para referirse a un dispositivo interactivo, de lo contrario, está completamente búfer. Por lo tanto, hay situaciones en las que printf
no se vaciará, incluso si se envía una nueva línea, como:
myprog >myfile.txt
Esto tiene sentido para la eficiencia, ya que, si estás interactuando con un usuario, probablemente quieran ver todas las líneas. Si está enviando la salida a un archivo, lo más probable es que no haya un usuario en el otro extremo (aunque no es imposible, podrían estar siguiendo el archivo). Ahora podría argumentar que el usuario quiere ver todos los caracteres, pero hay dos problemas con eso.
La primera es que no es muy eficiente. La segunda es que el mandato original de ANSI C era codificar principalmente el comportamiento existente , en lugar de inventar un nuevo comportamiento, y esas decisiones de diseño se tomaron mucho antes de que ANSI comenzara el proceso. Incluso hoy en día, la ISO tiene mucho cuidado al cambiar las normas existentes en las normas.
En cuanto a cómo lidiar con eso, si fflush (stdout)
después de cada llamada de salida que desea ver de inmediato, eso resolverá el problema.
Alternativamente, puede usar setvbuf
antes de operar en la setvbuf
, para configurarlo como sin búfer y no tendrá que preocuparse por agregar todas esas líneas de fflush
a su código:
setvbuf (stdout, NULL, _IONBF, BUFSIZ);
Solo tenga en cuenta que puede afectar bastante al rendimiento si está enviando la salida a un archivo. También tenga en cuenta que el soporte para esto está definido por la implementación, no está garantizado por la norma.
La sección 7.19.3/3
ISO C99 es el bit relevante:
Cuando un flujo no tiene buffer , se pretende que los caracteres aparezcan desde la fuente o en el destino tan pronto como sea posible. De lo contrario, los caracteres pueden acumularse y transmitirse hacia o desde el entorno host como un bloque.
Cuando un flujo está completamente almacenado en búfer , se pretende que los caracteres se transmitan hacia o desde el entorno del host como un bloque cuando se llena un búfer.
Cuando un flujo tiene un búfer de línea , se pretende que los caracteres se transmitan hacia o desde el entorno del host como un bloque cuando se encuentra un carácter de nueva línea.
Además, se pretende que los caracteres se transmitan como un bloque al entorno del host cuando se llena un búfer, cuando se solicita la entrada en un flujo no almacenado en búfer, o cuando se solicita la entrada en un flujo del búfer de línea que requiere la transmisión de caracteres desde el entorno del host .
El soporte para estas características está definido por la implementación y puede verse afectado a través de las funciones
setbuf
ysetvbuf
.
Nota: las bibliotecas de tiempo de ejecución de Microsoft no admiten el búfer de línea, por lo que printf("will print immediatelly to terminal")
:
Para vaciar de inmediato, llame a fflush(stdout)
o fflush(NULL)
( NULL
significa nivelar todo).
Probablemente sea así debido a la eficiencia y porque si tiene varios programas que escriben en un solo TTY, de esta manera no tendrá caracteres entrelazados en una línea. Entonces, si los programas A y B están dando salida, por lo general obtendrás:
program A output
program B output
program B output
program A output
program B output
Esto apesta, pero es mejor que
proprogrgraam m AB ououtputputt
prproogrgram amB A ououtputtput
program B output
Tenga en cuenta que ni siquiera se garantiza que se descargue en una nueva línea, por lo que debe vaciar explícitamente si el lavado es importante para usted.
Puede fprintf a stderr, que no tiene búfer, en su lugar. O puede vaciar la salida estándar cuando quiera. O puede establecer stdout en sin búfer.
Utilice setbuf(stdout, NULL);
para desactivar el almacenamiento en búfer.
por defecto, stdout tiene búfer de línea, stderr no tiene búfer y el archivo está completamente en búfer.
stdout está almacenado en búfer, por lo que solo se emitirá después de imprimir una nueva línea.
Para obtener salida inmediata, ya sea:
- Imprimir a stderr.
- Hacer stdout sin búfer.