如果我在控制台中显示了一个字符网格,是否有任何实用的方法可以重写这些多行,以便在控制台的相同行上输出更改的网格。
例如,我想要这段代码:
#include <iostream>
using namespace std;
int main() {
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
cout << "-";
}
cout << endl;
}
getchar();
for (int i=0; i<5; i++) {
cout << '\r';
for (int j=0; j<5; j++) {
cout << "x";
}
cout.flush();
}
return 0;
}
输出:
-----
-----
-----
-----
-----
然后,在用户输入时,用;
覆盖它xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
我看到人们通过输出'\ r'重新编写单行来显示加载栏类型显示的其他示例,但我不确定是否有任何直接的方法来实现多个行?
我正在使用MinGW。
一个解决方案:
#include <iostream>
#include <stdio.h>
#include <windows.h>
using namespace std;
void gotoxy( int column, int line )
{
COORD coord;
coord.X = column;
coord.Y = line;
SetConsoleCursorPosition(
GetStdHandle( STD_OUTPUT_HANDLE ),
coord
);
}
int main() {
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
cout << "-";
}
cout << endl;
}
getchar();
gotoxy(0,0);
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
cout << "x";
}
cout << endl;
}
return 0;
}
答案 0 :(得分:2)
您可以使用SetConsoleCursorPosition
设置光标位置。
答案 1 :(得分:2)
您可以在两个循环之间添加此代码块以清除屏幕。
printf("\033[2J");
printf("\033[%d;%dH", 0, 0);
它使用ANSI转义序列来执行此操作。您还需要添加#include <stdio.h>
以支持printf()
。
也不需要\r
,您应该将cout.flush();
替换为cout << endl;
你的代码最终应该是这样的:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
cout << "-";
}
cout << endl;
}
getchar();
printf("\033[2J");
printf("\033[%d;%dH", 0, 0);
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
cout << "x";
}
cout<<endl;
}
return 0;
}
答案 2 :(得分:1)
是为多行实现这一目标的直接方法吗?
是。 Ansi终端是一种直接的便携式解决方案。我曾经使用的每台PC都有Ansi终端仿真。在ubuntu上,gnome-terminal工作正常。我一直使用ansi转义序列。
对于这项工作,您可能只需要goto和clear screen,但还有更多的ansi终端功能。
由于您已将此帖标记为C ++,请考虑以下事项。
#include <chrono>
// 'compressed' chrono access --------------vvvvvvv
typedef std::chrono::high_resolution_clock HRClk_t; // std-chrono-hi-res-clk
typedef HRClk_t::time_point Time_t; // std-chrono-hi-res-clk-time-point
typedef std::chrono::milliseconds MS_t; // std-chrono-milliseconds
typedef std::chrono::microseconds US_t; // std-chrono-microseconds
typedef std::chrono::nanoseconds NS_t; // std-chrono-nanoseconds
using namespace std::chrono_literals; // support suffixes like 100ms, 2s, 30us
#include <iostream>
#include <iomanip>
#include <thread>
class Ansi_t // use ansi features of gnome-terminal,
{ // or any ansi terminal
// note: Ubuntu 15.10 gnome-terminal ansi term cursor locations
// are 1-based, with origin 1,1 at top left corner
enum ANSI : int { ESC = 27 }; // escape
public:
static std::string clrscr(void)
{
std::stringstream ss;
ss << static_cast<char>(ESC)<< "[H" // home
<< static_cast<char>(ESC)<< "[2J"; // clrbos
return(ss.str());
}
// r/c are 0 based------v------v------0 based from C++
static std::string gotoRC(int r, int c)
{
std::stringstream ss;
// Note: row/col of my apps are 0 based (as in C++)
// here I fix xy to 1 based, by adding 1 while forming output
ss << static_cast<char>(ESC)<< "["
<< (r+1) << ';' << (c+1) << 'H';
return(ss.str());
}
// tbr - add more ansi functions when needed
}; // Ansi_t
注意:我偶尔会添加断言以强制执行r和c>> =。
用法示例:
int main(int, char**)
{
int retVal = -1;
{
Time_t start_us = HRClk_t::now();
{
std::cout << Ansi_t::clrscr() << std::flush; // leaves cursor at top left of screen
for (int i=0; i<10; ++i)
{
for (int r=0; r<5; ++r) // 0 based
{
std::cout << Ansi_t::gotoRC(r+5, 5) // set cursor location
<< "-----" << std::flush;
}
std::this_thread::sleep_for(500ms);
// to overwrite
for (int r=0; r<5; ++r)
{
std::cout << Ansi_t::gotoRC(r+5, 5) // set cursor location
<< "xxxxx" << std::flush;
}
std::this_thread::sleep_for(500ms);
std::cout << Ansi_t::gotoRC(11,5) << 9-i << std::flush;
}// for i
std::cout << "\n\n" << std::endl;
return 0;
}
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
std::cout << "\n\n duration " << duration_us.count() << " us" << std::endl;
}
return(retVal);
}
使用这些Ansi_t方法可以直接进行记忆。来自工作代码的示例片段:
std::string m_toRowCol; // cursor position string
FOO_t::FOO_t( ... ) : m_seqId (a_gb.gBoardSz()) , m_toRowCol (a_gb.gotoRC(aRow, aCol)) // pre-compute // other data attribute init { // ctor body }
m_gb.termUpdate(m_toRowCol + // position cursor <output string>); // provide state info