Как перезаписать stdout в C

Вот подход с базой R:

rbind(tmp <- colSums(is.na(prueba[ , -"YEAR"])), nrow(prueba) - tmp)
#      aa bb cc
# [1,]  0  2  2
# [2,]  7  5  5
32
задан radbrawler 4 November 2016 в 08:08
поделиться

8 ответов

Это не управляет 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 возврат каретки, который интерпретирует терминал, поскольку "кладут обратно курсор к запуску текущей строки".

Ваша оболочка, если это bash, использует библиотека GNU Readline , который обеспечивает намного более общую функциональность, включая обнаружение терминальных типов, управления историей, программируемых привязок клавиш, и т.д.

Еще одна вещь - когда в сомнении, источник для Вашего wget, Вашей оболочки, и т.д. все доступен.

44
ответ дан 27 November 2019 в 20:04
поделиться

Перезаписывать текущую строку стандартного вывода (или части его) использование \r (или \b.) Специальный символ \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);, потому что стандартный вывод обычно буферизуется , и информация не может иначе быть сразу распечатана на выводе или терминале

22
ответ дан 27 November 2019 в 20:04
поделиться

В дополнение к \r и \b, смотрите на ncurses для некоторого усовершенствованного управления тем, что находится на консольном экране. (Включая столбцы, перемещаясь произвольно, и т.д.).

12
ответ дан 27 November 2019 в 20:04
поделиться

Программа, работающая в текстовом терминале/, консоль может управлять текстом, отображенным в его консоли различными способами (сделайте текст полужирным, переместите курсор, ясный экран и т.д.). Это выполняется путем печати последовательностей специального символа, названных "escape-последовательности" (потому что они обычно запускают с Escape, ASCII 27).

, Если stdout переходит к терминалу, который понимает эти escape-последовательности, дисплей терминала изменится соответственно.

при перенаправлении stdout в файл escape-последовательности появятся в файле (который обычно является не, что Вы хотите).

нет никакого полного стандарта для escape-последовательностей, но большинство терминалов использует последовательности, представленные VT100 со многими расширениями. Это - то, что понимает большинство терминалов под Unix/Linux (xterm, rxvt, консоль) и другие как PuTTY.

На практике, Вы не были бы непосредственно hardcode escape-последовательности в свое программное обеспечение (хотя Вы могли), но пользуйтесь библиотекой для печати их, такой как ncurses или упомянутый выше GNU readline. Это позволяет совместимость с различными терминальными типами.

5
ответ дан 27 November 2019 в 20:04
поделиться

Это сделано с библиотека readline ... Я не уверен, как это выполняет незаметную работу, но я не думаю, что это имеет какое-либо отношение к stdout или потокам. Я подозреваю, что readline использует своего рода загадочное (для меня, по крайней мере) терминальные команды - то есть, он сотрудничает с терминальной программой, которая на самом деле отображает Вашу сессию оболочки. Я не знаю, что можно получить подобное readline поведение только путем печати вывода.

(Думают об этом: stdout может быть перенаправлен в файл, но/стрелка вниз прием ключей не работает над файлами.)

2
ответ дан 27 November 2019 в 20:04
поделиться

Можно использовать возврат каретки для моделирования этого.

#include <stdio.h>

int main(int argc, char* argv[])
{
    while(1)
    {
        printf("***********");
        fflush(stdout);
        sleep(1);
        printf("\r");
        printf("...........");
        sleep(1);
    }

    return 0;
}
1
ответ дан 27 November 2019 в 20:04
поделиться

Программа делает это путем печати специальных символов, которые терминал интерпретирует специальным способом. Самая простая версия этого (на большинстве терминалов linux/unix) для печати '\r' (возврат каретки) к нормальному stdout, который сбрасывает позицию курсора к первому символу в текущей строке. Таким образом, вещь, которую Вы пишете затем, перезапишет строку, которую Вы записали ранее. Это может использоваться для простых индикаторов хода выполнения, например.

int i = 0;
while (something) {
  i++;
  printf("\rprocessing line %i...", i);
  ...
}

, Но существуют более сложные последовательности символов ESC, которые интерпретируются различными способами. Все виды вещей могут быть сделаны с этим, как расположение курсора в определенной позиции по экрану или установке цвета текста. То, если или как эти последовательности символов интерпретируются, зависит от Вашего терминала, но общий класс, поддерживаемый большинством терминалов, ansi escape-последовательности . Таким образом, если Вы хотите красный текст, попробуйте:

printf("Text in \033[1;31mred\033[0m\n");
1
ответ дан 27 November 2019 в 20:04
поделиться

Самый простой путь состоит в том, чтобы распечатать к stdout символ возврата каретки ('\r').

курсор будет перемещен в запуск строки, позволяя Вам перезаписать ее содержание.

0
ответ дан 27 November 2019 в 20:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: