C에서 stdout을 덮어쓰는 방법
대부분의 최신 셸에서는 위/아래 화살표를 누를 수 있으며, 실행한 이전 명령이 프롬프트에 표시됩니다.제 질문은, 이게 어떻게 작동하는 거죠?
셸이 이미 작성한 내용을 덮어쓰기 위해 stdout을 어떻게든 조작하고 있는 것 같습니다.
우리와 같은 프로그램들도 이것을 한다는 것을 알고 있습니다.그들이 어떻게 하는지 아는 사람?
stdout을 조작하는 것이 아니라 단말기에 이미 표시된 문자를 덮어쓰는 것입니다.
시도해 보기:
#include <stdio.h>
#include <unistd.h>
static char bar[] = "======================================="
"======================================>";
int main() {
int i;
for (i = 77; i >= 0; i--) {
printf("[%s]\r", &bar[i]);
fflush(stdout);
sleep(1);
}
printf("\n");
return 0;
}
입니다에 꽤요.wget
출력, 맞지요?\r
는 캐리지 리턴(carriage-return)으로, 터미널은 이를 "커서를 현재 라인의 시작으로 다시 이동"하는 것으로 해석합니다.
가라면bash
, 는 터미널 유형 감지, 히스토리 관리, 프로그래밍 가능한 키 바인딩 등을 포함하여 훨씬 더 일반적인 기능을 제공하는 GNU Readline 라이브러리를 사용합니다.
한 가지 더 말하자면, 의심스러울 때, 당신의 wget의 출처, 당신의 shell 등은 모두 이용 가능합니다.
그 을 ( )를 합니다.\r
(또는\b
.)\r
맨 수 환)다.한 캐릭터는r\b
을 한 마지막 다)를 수 .
#include <stdio.h>
#include <unistd.h>
int i;
const char progress[] = "|/-\\";
for (i = 0; i < 100; i += 10) {
printf("Processing: %3d%%\r",i); /* \r returns the caret to the line start */
fflush(stdout);
sleep(1);
}
printf("\n"); /* goes to the next line */
fflush(stdout);
printf("Processing: ");
for (i = 0; i < 100; i += 10) {
printf("%c\b", progress[(i/10)%sizeof(progress)]); /* \b goes one back */
fflush(stdout);
sleep(1);
}
printf("\n"); /* goes to the next line */
fflush(stdout);
사용하다fflush(stdout);
왜냐하면 일반적으로 표준 출력은 버퍼링되고 그렇지 않으면 정보가 출력 또는 터미널에 즉시 인쇄되지 않을 수 있기 때문입니다.
\r, \b 외에 콘솔 화면에 있는 것에 대한 고급 제어를 위한 간호사 보기 (열 포함, 임의 이동 등)
텍스트 단말기/콘솔에서 실행 중인 프로그램은 콘솔에 표시되는 텍스트를 다양한 방식으로 조작할 수 있습니다(텍스트 굵게 만들기, 커서 이동, 화면 지우기 등).이것은 "탈출 시퀀스"라고 불리는 특수 문자 시퀀스를 인쇄함으로써 달성됩니다(보통 이스케이프, ASCII 27로 시작하기 때문입니다).
stdout이 이러한 이스케이프 시퀀스를 이해하는 터미널로 가면 터미널의 디스플레이가 그에 따라 바뀝니다.
stdout을 파일로 리디렉션하면 일반적으로 원하는 것이 아닌 이스케이프 시퀀스가 파일에 나타납니다.
이스케이프 시퀀스에 대한 완전한 표준은 없지만 대부분의 터미널은 VT100에서 도입한 시퀀스를 사용하며 확장이 많습니다.이것은 대부분의 유닉스/리눅스(xterm, rxvt, konsole) 및 PuTTY와 같은 기타 터미널에서 이해할 수 있는 것입니다.
실제로 탈출 시퀀스를 소프트웨어에 직접 하드코딩하지는 않지만 위에서 언급한 curses 또는 GNU 읽기 라인과 같은 라이브러리를 사용하여 인쇄합니다.이를 통해 다양한 터미널 유형과 호환이 가능합니다.
읽기 라인 라이브러리로 완성된 겁니다무대 뒤에서 어떻게 작동하는지는 잘 모르겠지만 stdout이나 stream과는 관련이 없는 것 같습니다.나는 읽기 라인이 일종의 암호화된(적어도 나에게는) 터미널 명령을 사용한다고 의심합니다. 즉, 실제로 셸 세션을 표시하는 터미널 프로그램과 협력합니다.출력물을 출력하는 것만으로 읽기 라인과 같은 동작을 얻을 수 있다는 것을 모릅니다.
(stdout은 파일로 리디렉션될 수 있지만 위쪽/아래쪽 화살표 키 트릭은 파일에서 작동하지 않습니다.)
캐리지 리턴을 사용하여 이를 시뮬레이션할 수 있습니다.
#include <stdio.h>
int main(int argc, char* argv[])
{
while(1)
{
printf("***********");
fflush(stdout);
sleep(1);
printf("\r");
printf("...........");
sleep(1);
}
return 0;
}
이 프로그램은 터미널이 특별한 방식으로 해석하는 특수 문자를 인쇄함으로써 이를 수행합니다.가장 간단한 버전은 (대부분의 Linux/Unix 터미널에서) 커서 위치를 현재 줄의 첫 번째 문자로 재설정하는 '\r'(캐리어 리턴)을 일반 stdout으로 인쇄하는 것입니다.따라서 다음에 쓰는 것은 이전에 쓴 줄을 덮어씁니다.예를 들어, 간단한 진행 표시기에 사용할 수 있습니다.
int i = 0;
while (something) {
i++;
printf("\rprocessing line %i...", i);
...
}
하지만 다양한 방식으로 해석되는 더 복잡한 탈출 캐릭터 시퀀스가 있습니다.화면의 특정 위치에 커서를 놓거나 텍스트 색상을 설정하는 등 모든 종류의 작업을 수행할 수 있습니다.이러한 문자 시퀀스가 해석되는지 또는 해석 방법은 단말기에 따라 다르지만 대부분의 단말기에서 지원하는 일반 클래스는 안시 탈출 시퀀스입니다.빨간색 텍스트를 원한다면 다음을 시도해 보십시오.
printf("Text in \033[1;31mred\033[0m\n");
가장 간단한 방법은 캐리지 리턴 문자('\r')를 인쇄하는 것입니다.
커서가 줄의 시작 부분으로 이동하여 내용을 덮어쓸 수 있습니다.
언급URL : https://stackoverflow.com/questions/656504/how-to-overwrite-stdout-in-c
'programing' 카테고리의 다른 글
CORS 정책에 의해 오리진에서 글꼴에 대한 액세스가 차단되었습니다.요청한 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다. (0) | 2023.10.14 |
---|---|
열거형 내에서 이러한 #정의의 목적은 무엇입니까? (0) | 2023.10.14 |
워드프레스 아약스 기법 (0) | 2023.10.14 |
워드에서 제출 양식을 만들려면 PHP를 누릅니다. (0) | 2023.10.14 |
MySQL 성능: 단일 테이블 및 파티션에서 여러 개의 테이블 대 인덱스 (0) | 2023.10.14 |