C++ cleaning the console window - c++

IS there a way to delete or rewrite a symbol on the console window? Something like System("cls") but for a single symbol.
Thanks

First of all, you are usually working with standard output stream with C++, not with console itself. And you are not able to navigate through it.
From the other hand, you can use specific platform dependent console libraries (like ncurses or Windows console functions) to handle console.
However, if you are actually printing to the console you can use some symbols to control the last line:
You can send '\b' (Backspace) to move one character left on the current line.
You can send '\r' to move to the beginning of the current line.
Don't forget also, that stdout usually line-buffered and you may have to flush by hands.
int main()
{
std::cout << "Hi\r" << std::flush;
Sleep(1000); //or whatever to delay
std::cout << "hellq" << std::flush; // flushing by hands
Sleep(1000);
std::cout << "\bo";
}

Related

C++ ignoring cout redirect for some outputs

I'm launching my program using the command line and the redirect symbol like so
program > out.txt
Is there a way some cout calls can ignore the > operator and still be displayed in the console?
What I want is to have a console menu that will appear in the console, but the rest will get redirected to the file.
Thank you.
No, there isn't.
> redirects the whole stdout stream to a file, not particular writes to that stream. If you want to write to multiple locations, you are to use multiple streams. For example, you could use stderr:
cout << "redirected" << endl;
cerr << "not redirected" << endl;
You could reformat what you are doing and use std::cout when you want to go to stdout, and a Log function that writes to a file you specify as the input to the progam.
It might be neater still to have a Menu function which displays to std::cout, and the Log file able to be configured as to where it ends up.

WriteFile function with assembly debugging (syncing)

First of all, this question is based on my last question here: Reading Console Buffer / Output C++
I have a compiled executable binary file. It has some outputs, what I would like to redirect it to an other program, that handles the lines. I successfully found where the output is sent, and I modified it to STDOUT. The problem is that, when I use it like:
./jampDed.exe | stdout.exe
then the output is not synced. I got the content after every 1000-2000 bytes.
stdout.cpp
#include <iostream>
int main() {
std::string s;
while (std::getline(std::cin, s, '\n')) {
std::cout << s << std::endl;
}
return 0;
}
I also created a picture about assembly modification, where Kernel32.WriteFile function was used by default.
So the question is that, how can I make it synced? How to get every line as soon as it happens on the dedicated server?
Somewhere in the executable where it establishes stdout is an option bit for unbuffered output. Just set (or clear) that bit. Then every call to write is transferred without delay. This adds significant execution time and i/o system effort to that program but is probably okay for this.
The program which processes that output (as input) should buffer full lines because the program is unlikely to do full line output itself.
Why don't you try:
std::cout << s << std::endl << std::flush;
^^^^^^^^^^

when can std::cout buffer be non-empty?

I have seen cout.rdbuf() in for example here. This implies, the stream cout have a stream buffer associated with it, which is non empty before we flush it.
But, how can I ever peek into cout's stream buffer for cout before it's flushed?
Ie
cout << "I want to read this before this get flushed";
cout.UnknownFunction(); //this would save the buffer into a string variable
cout << flush;
But in current form of the code, everything will be flushed onto the screen after the first line..
So, what kind of construct allows me to peek inside the cout buffer?
PS. im running VC++ 2010 on windows7
I think that this doesn't flush after the first line, but I'm absolutely NOT sure.
I experienced that endl flushes, but the others don't, it's possible that too much character automatically flushes, but I don't know.
I created (accidentally) a program like this (in short):
cout << "x";
while (true) {}
The program ran this, and the output would be debug, but it haven't written anything for me, so I thought the program doesn't get there...
Following link is closely related to this topic
C++ buffered stream IO
(But I'm still not sure how/when to get cout.rdbuf() onto a string.)

Code works only with endl - very strange

I encountered a strange problem earlier. I was working at insertion in B-trees and I wrote a simple display function. I ran it and it didn't show anything in the console even though I inserted some values.
I entered in the debug mode, I followed the flow of the program and the debugger showed me that the tree had values in it. Then I wanted to display only the first node's elements and I had the same problem: an empty console.
I asked my teacher what would be the mistake and he told me to put an endl after cout, like this:
cout << node->keys[i] << endl;
It worked!
He told me then that probably I addressed a NULL pointer in my program and Eclipse doesn't say anything about that but nothing about how endl could help.
Does anybody know what could be the problem and how that endl solves it? I'm very very confused.
I didn't understand what flushing the buffer has to do with my display function.
I'm a bit late to answer and how to flush has been explained by the other answers already so I wanna answer your comment on Johnsy's answer at least.
First the reason that output is buffered is that writing the data to some output stream and not in the memory is usually a really slow operation (this ofc depends if you wanna write to a file on a ssd or hdd or just to the display but they all are way slower than the ram).
So c++ writes it to an internal buffer first and only actually writes to the output when the buffer is full or you flush the stream. It does so to avoid the slow operation of writing on most output streams.
So now why do you need to flush the buffer before it gets displayed...
Like already said it only actually writes it out for you to see when the buffer is full or it gets explicitly flushed. Now when the program ends normally all streams get flushed automatically so what happens prolly is a crash of the Program (a crash won't flush the buffer) so your program quits w/o it ever displaying.
Since your program displays everything correctly when you add the endl I guess you're trying to output a node with a nullptrat the very end and crash just before returning from main. You could easily test that by adding std::cout << "end of the program" << std::endl; just before your returnin main and testing if it gets displayed.
std::endl flushes output stream....
cout is buffered, output will not be displayed immediately, they will be buffered, until the buffer overflows, then all buffered data will be displayed. If you want display the ouput sooner, flush it.
Inserts a endline character into the output sequence os and flushes it
as if by calling os.put(os.widen('\n')) followed by os.flush().[1]
You can use std::cout.flush(); too.
std::endl inserts a endline character into the output sequence (os, in your case cout) and flushes it as if by calling os.put(os.widen('\n')) followed by os.flush().
std::cout controls output to a stream buffer of implementation-defined type (derived from std::streambuf), associated with the standard C output stream stdout. This output is buffered (unlike std::cerr)
Before you put endl into your source code, your buffer was not being flushed and the output was not appearing on your screen.
std::endl not only appends a newline character to the output stream, but also causes it to be flushed. I'm not quite sure how large the buffer on std::cout is, but it is possible that you're not seeing anything because the buffer is not full and thus does not get flushed. You could try to call cout.flush(); after appending your data (without appending std::endl) and see if that solves the problem.
As M M has mentioned in his answer as have others above, the std::endl flushes output stream. What it means is to display or put the results/output to the standard output source immediately/real time.
Using '\n' instead of std::endl will also result in similar output but may not be displayed immediately if some operation is still going on.
The common down side of std::endl is considered to be degradation of performance, though it may not be of significance if the output is streamed to a display instead of a file - where the '\n' is the preferred method.
Hope this helps.

Rewinding std::cout to go back to the beginning of a line

I'm writing a command-line tool for Mac OS X that processes a bunch of files. I would like to show the user the current file being processed, but do not want a bazillion files polluting the terminal window.
Instead I would like to use a single line to output the file path, then reuse that line for the next file. Is there a character (or some other code) to output to std::cout to accomplish this?
Also, if I wanted to re-target this tool for Windows, would the solution be the same for both platforms?
"\r" should work for both windows and Mac OS X.
Something like:
std::cout << "will not see this\rwill see this" << std::flush;
std::cout << std::endl; // all done
I don't have access to a mac, but from a pure console standpoint, this is going to be largely dependent on how it treats the carriage return and line-feed characters. If you can literally send one or the other to the console, you want to send just a carriage return.
I'm pretty sure Mac treats both carriage returns and line-feeds differently than *nix & windows.
If you're looking for in-place updates (e.g. overwrite the current line), I'd recommend looking at the curses lib. This should provide a platform independent means of doing what you're looking for. (because, even using standard C++, there is no platform independent means of what you're asking for).
As Nathan Ernst's answer says, if you want a robust, proper way to do this, use curses - specifically ncurses.
If you want a low-effort hackish way that tends to work, carry on...
Command-line terminals for Linux, UNIX, MacOS, Windows etc. tend to support a small set of basic ASCII control characters, including character 13 decimal - known as a Carriage Return and encoded in C++ as '\r' or equivalently in octal '\015' or hex '\x0D' - instructing the terminal to return to the start of the line.
What you generally want to do is...
int line_width = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 80;
std::string spaces{line_width - 1, ' '};
for (const auto& filename : filenames) {
std::cout << '\r' << spaces << '\r' << filename << std::flush;
process_file(filename);
}
std::cout << std::endl; // move past last filename...
This uses a string of spaces to overwrite the old filename before writing the next one, so if you have a shorter filename you don't see trailing characters from the earlier longer filename(s).
The std::flush ensures the C++ program calls the OS write() function to send the text to the terminal before starting to process the file. Without that, the text needed for the update - \r, spaces, \r and a filename - will be appended to a buffer and only written to the OS - in e.g. 4k chunks - when the buffer is full, so the filename displayed would lag dozens of files behind the actual file being processing. Further, say the buffer is 4k - 4096 bytes - and at some point you have 4080 bytes buffered, then output text for the next filename: you'll end up with \r and 15 spaces fitting in the buffer, which when auto-flushed will end up wiping out the first 15 characters on the line on-screen and leaving the rest of the previous filename (if it was longer than 15 characters), then waiting until the buffer is full again before updating the screen (still haphazardly).
The final std::endl just moves the cursor on from the line where you've been printing filenames so you can write "all done", or just leave main() and have the shell prompt display on a nice clean line, instead of potentially overwriting part of your last filename (great shells like zsh check for this).