エスケープシーケンス
第47回特殊な画面制御~コンソール入出力関数とエスケープシーケンス
右詰め/右詰め/ゼロ埋めの方法
プログレスバー
ここでのポイントは、setfill()
とsetw()
で任意文字で桁数だけ埋める処理と、キャリッジリターン\r
を出力して、標準出力のカーソルを行頭に移動することによって、画面スクロールせずにプログレスバーを表現させることができる。コマンドライン処理ではよく見る処理になる。
あと、\e[1;33;47m
(ボールド、黄色、背景白色)と\e[0m
で囲むことによって色が付与できる。最後は必ず\e[0m
をつけて「色の付与はここで終了」とさせないと以降の出力すべてに色がついてしまう。色のルールは上記サイトを参考にする。
1行だけで表現するときに有効な方法になる。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc, char*argv[]){
// スクリーンをクリア
system("clear");
int count = 0;
string progress = "";
int percent = 0;
while(1){
percent = count / 10;
if(count % 100 == 0 && progress.size()< 10){
progress += "#";
}
if( percent > 100 ){
percent = 100;
}
// 半角スペースを10個、左詰めで'#'を上書きする
// さらにスペースを7個、右詰めでパーセンテージを表示
cout << "[" << "\e[1;33;47m" << setfill(' ') << setw(10) << left << progress << "\e[0m"<<"]"
<< setfill(' ') << setw(7) << right << percent << "%";
// 100%まで行ったら改行を入れてループを抜ける
if( progress.size() == 10 && percent == 100 ){
cout<<endl;
break;
}
// キャリッジリターン(行頭にカーソルを移動する)
cout<<"\r";
count++;
usleep(10000);
}
return 0;
}
実行結果。バーと数値が若干ずれるが気にしない。
> g++ sample.cpp && ./a.out
[##### ] 43%
[##########] 100%
>
複数行
キャリッジリターンでは対応できない。\e[nA
でカーソルをn行上に移動するエスケープを使って表現する。あと、カーソルがちらつく場合、\e[?25l
(カーソル非表示)と\e[?25h
(カーソル表示)を使ったほうが良さそうだった。
終了時にカーソルを4行下まで移動(\e[4B
)した後でプログラムが終了してプロンプトが表示される。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc, char*argv[]){
// カーソルを非表示にする
cout<<"\e[?25l";
// スクリーンをクリア
system("clear");
int count = 0;
int count2 = 0;
while(1){
cout<<"-----\n";
cout<< setfill(' ') << setw(5) << right << count<< "|" << setfill(' ') << setw(3) << count/20<<"\n";
cout<<"-----\n";
cout<< setfill('#') << setw(count/50) <<"\n";
cout<<"-----\n";
cout<<flush;
// 5行上に移動
cout<<"\e[5A";
if( count > 1000 ){
break;
}
count++;
usleep(10000);
}
cout<<endl;
// 4行下にカーソル移動する
cout<<"\e[4B";
// カーソルを表示する
cout<<"\e[?25h";
return 0;
}
実行結果
複数行で動きのある標準出力になる。
> g++ sample.cpp && ./a.out
(一旦画面がクリアされる)
-----
254| 12
-----
####
-----
-----
1001| 50
-----
###################
-----
>