3

I am trying to clear the console in C++. I know printing a number of newlines is a bad practice, as it can be slow and is not always reliable to completely clear the console window, but I have researched multiple options and have found almost no other solutions besides system("cls"), which is an even worse option.

Essentially, I have used the line cout << string(100, '\n'); but I am getting a near-unidentifiable error when I try to run the program.

error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::basic_string<_Elem,_Traits,_Ax>' (or there is no acceptable conversion)

I have also researched this, and found that most explanations were too complicated for me as a beginning C++ programmer to understand, or completely unrelated to my problem.

My questions are (1) is there a way to fix this error, and (2) could there be a better, cross-platform way of clearing the console other than printing 100 newlines?

I also heard of Console.clear(), but I'm unsure if this is cross-platform. From what I've seen, it looks more like a Windows command. I've also heard of the curses library, which I was willing to research and use, until I read somewhere that it was not recommended to use the functions which I am familiar with coupled with the curses library functions.

Thank you in advance!

Abluescarab
  • 537
  • 8
  • 25
  • See here : http://stackoverflow.com/questions/228617/how-do-i-clear-the-console-in-both-windows-and-linux-using-c for an answer to your second question. – NickLH Oct 27 '11 at 02:47
  • Is clearing the screen the only non-teletype behavior you want...or do you more generally want curses behavior (knowing the size of the screen, positioning the cursor, overwriting text that's already written, etc. etc.)? If clearing the screen is it, I'd suggest leaving that to the user themselves, as there are keystrokes for it in many terminal programs. If you wrote a hundred newlines into my scrollback buffer for no good reason...I'd personally be annoyed! – HostileFork says dont trust SE Oct 27 '11 at 02:47
  • @HostileFork As I said, I know that printing 100 newlines is a bad practice for these reasons. May I ask what "keystrokes" you know of? – Abluescarab Oct 27 '11 at 02:51
  • @NickLH Ah, yes, I had also found that article. Still, thanks for the link so I can return to it and check it out again! – Abluescarab Oct 27 '11 at 02:58
  • @Abluescarab: `ctrl-v` followed by `escape` followed by writing `[2J` will clear the screen – Daniel Oct 27 '11 at 03:01
  • @Dani In which case? In Linux? – Abluescarab Oct 27 '11 at 03:04
  • @Abluescarab: everything that emulates VT100, thats xterm, I think also linux default terminal (the one before X starts up), Mac OSX Terminal, and there is even some in windows – Daniel Oct 27 '11 at 03:08
  • A lot of shortcuts that work at the terminal prompt, such as Ctrl-L in xterm, will not work while a program doing console I/O is running. But in mid-run if I want to clear my xterm I can say "Ctrl-Shift-X", on Macs its Command-K. (That actually clears the screen and the scrollback buffer too.) But this is not a bad thing...if you are pretty much a vanilla console I/O program, you should leave the clearing decision to the terminal user--that's the expectation in the unix toolbox model, and breaking it should be done only when you've got a very compelling reason to do so... – HostileFork says dont trust SE Oct 27 '11 at 03:11
  • @HostileFork I don't know what a "compelling reason" would be. As it is, it's a simple, console-based text game that's very stylistic in the way it displays text (if that makes any sense). On top of that, it's intended for really anyone, and I honestly don't know anyone other than power users who would know how to manually clear the console using a key combination. – Abluescarab Oct 27 '11 at 03:23
  • @Dani I see! It's still a bit complicated for me, but I'm not extremely experienced at using the console or writing C++ code. – Abluescarab Oct 27 '11 at 03:24
  • @ABluescarab If it's just a C++ learning exercise that no one else will ever run, it doesn't really matter how you do this--"whatever works" is fine. But if you are writing a game and doing stylized text, I'd suggest you might get more mileage out of using a cross-platform toolkit like Qt and getting full control over a rich text widget (or even a webkit widget)...that would give you a fat api that is reasonably supported ( http://doc.qt.nokia.com/latest/qtextedit.html ) But to get even more "meta", you'd get a bigger audience on stylized-text-games by targeting HTML5/JavaScript... – HostileFork says dont trust SE Oct 27 '11 at 03:43
  • @HostileFork True. Thank you for the help. It is more of a learning exercise, a fun thing that I don't really intend to release to the public. At some point, I'll check out those toolkits you mentioned, maybe once I'm more experienced. Thanks again! – Abluescarab Oct 27 '11 at 04:00

3 Answers3

3

At a guess, your immediate problem is probably that you're missing an #include <string>.

Probably the most portable way of dealing with the screen is via ncurses. It's included in POSIX and most POSIX-like systems, and available as a library for most others (e.g., Windows) as well.

Edit: For what it's worth, clearing the screen on Windows doesn't require anywhere close to 100 lines of code.

#include <windows.h>

void clear_screen(char fill = ' ') { 
    COORD tl = {0,0};
    CONSOLE_SCREEN_BUFFER_INFO s;
    HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);   
    GetConsoleScreenBufferInfo(console, &s);
    DWORD written, cells = s.dwSize.X * s.dwSize.Y;
    FillConsoleOutputCharacter(console, fill, cells, tl, &written);
    FillConsoleOutputAttribute(console, s.wAttributes, cells, tl, &written);
    SetConsoleCursorPosition(console, tl);
}

#ifdef TEST
int main(){ 
    clear_screen();
    return 0;
}
#endif

I'm the first to say that the code is more verbose than I'd like -- but it's less than ten lines, not to mention a hundred. Even the version in the MS knowledgebase is actually less than 40 lines -- of which many are blank or comments.

In fairness, however, I feel obliged to admit assembly language code writing directly to the hardware (or using the BIOS) does end up quite a bit shorter.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Thank you, that solution worked, though I know it is a bad practice and personally, I think it looks rather unattractive. I'm assuming that I should include both the Windows and Linux libraries of pcurses and ncurses, and use the below-mentioned #if method to check if the OS is Windows or Linux? – Abluescarab Oct 27 '11 at 02:54
  • 1
    @Abluescarab: I prefer *not* to use `#if` as a rule. Instead I separate the platform-specific code into a few particular files, and handle the differences in the makefiles. – Jerry Coffin Oct 27 '11 at 03:06
  • I'm very inexperienced when it comes to C++, I'm a high school student who just joined a C++ class to learn more, so I'm afraid I don't know much about splitting the platform-specific code and handling the differences in the makefiles. I wouldn't like to bug you to explain it, unless you feel the need to, because it's probably a bit more complicated than I had originally hoped. It would be wonderful if there was a simple, uncomplicated way to clear the console without all this extra nonsense. – Abluescarab Oct 27 '11 at 03:17
  • @Abluescarab: The *general* idea is pretty simple: have one file for Windows. Another file for Linux. Another for MacOS. When building for each OS, just compile in the file for that OS. Curses (for one example) will handle that part, so you can just do the job the same for any (supported) target. – Jerry Coffin Oct 27 '11 at 13:19
3

About your error... you have to...

#include <iostream> 
#include <string>

using namespace std;

If you are using just windows use windows console API. If you are using a linux\unix terminal, use escape codes. You can do a #if to choose between the two methods.

On linux\unix use the write function defined in in this way:

write(1,"\E[H\E[2J",7); // we use ANSI escape sequences here.

Here is the microsoft page that explain how to do that.

http://support.microsoft.com/kb/99261

The really bad console api microsoft use for the console always makes me angry :) why 100 lines of code to clear a screen? :)

Now the if... you should create a clearscreen.h file and a clearscreen.cpp file.

In clearscreen.h we just put our function.

 void clearconsole();

In clearscreen.cpp we put our code for both operative systems

#ifdef _WIN32 || _WIN64

    #include <windows.h>

    void clearconsole()
    {
        ...
        // 100 lines of codes copied from microsoft article
    }

#else

    #include <unistd.h>

    void clearconsole()
    {
        write(1,"\E[H\E[2J",7);
    }

#endif
Salvatore Previti
  • 8,956
  • 31
  • 37
  • Thanks for the answer! This is very valuable, though I will definitely have to look up what the ANSI escape codes stand for. At this point, I believe I'm using a number of Windows-specific methods as it is, so I may end up making the program Windows-only anyway. Still, may I ask for an elaboration or link on how to use the #if method, if it's not too much trouble? Thanks again! EDIT: Ah, there it is! Thank you! – Abluescarab Oct 27 '11 at 02:55
  • Yes, which I personally find tedious... it would be wonderful if all the operating systems in the world used the same methods, but we all know THAT won't happen. – Abluescarab Oct 27 '11 at 02:57
  • Thanks again and again, as I see that you keep updating your answer to be more and more specific! :D I will definitely check out that method, and very probably employ it. – Abluescarab Oct 27 '11 at 03:01
  • 1
    ncurses abstract the escape sequences so that it works in any terminal. – Martin York Oct 27 '11 at 04:40
  • If you are on a microsoft platform, why wouldn't you just use `system("cls")`. It gets the job done. – viraj Oct 27 '11 at 04:49
  • True for ncurses, but if there is just need to clear the screen why we should reference an external library if we have just to write one line of code? The problem then starts with windows OS. There are ports of ncurses for windows, but really, including a big and a complicated library, looking for the right 32 bit or 64 bit version, include the GPL license in my program just to clear the screen? – Salvatore Previti Oct 27 '11 at 06:21
  • About system("cls") is something i would never do. Executing a command from your program just to clean the screen is quite bad too :( – Salvatore Previti Oct 27 '11 at 06:22
  • So, you'd rather call 100 line's of code to clear the console than write one line ? What's wrong with executing a command from your program ? – viraj Oct 27 '11 at 14:38
  • Because these lines of codes still mantain the concept that your program is your program and doesn't rely on other processes\behaviour. system() is used to run the DOS commands from the C, C++. If the program is running in a windows environment why we should use old and unsupported code? systems("") comes from old DOS days in windows. Still, also if very boring, console API, is supported and in the same tune with windows OS development strategies, that is, call dll, not executables! – Salvatore Previti Oct 27 '11 at 17:38
  • I see a debate is going on here. Honestly, I agree with Mr. Previti over here: system calls are no good. – Abluescarab Oct 28 '11 at 00:05
1

I know this is a complete necro. But I figured out what I feel is a rather neat solution and thought I'd share it just in case someone has this problem in the future.

void clearConsole() {
#ifdef _WIN32
#include <iostream>
    static const char* CSI = "\33[";
    printf("%s%c%s%c", CSI, 'H', CSI, '2J');

#else
#include <unistd.h>
    write(1, "\E[H\E[2J", 7);
#endif
}
Pawn
  • 21
  • 5