This question already has answers here:
Clearing terminal in Linux with C++ code
(4 answers)
Closed 6 years ago.
I am currently trying to print some thing on the console. Similar to loading in same line using "\r" but instead I have endl included.
#include <iostream>
int main(int argc, char **argv)
{
int x = 3;
// first part
std::cout << " x = " << x <<"\n";
std::cout << " y = " << x <<"\n";
std::cout << " z = " << x << "\n";
std::cin >> x ;
std::cout << "\r" << std::flush;
// second part
std::cout << " x = " << x <<"\n";
std::cout << " y = " << x <<"\n";
std::cout << " z = " << x <<"\n";
return 0;
}
The above code prints the first part and prints again the second part in different place. So the total column is eight. What I actually want is to print the first part take input from user and then replace the first part with second part. This way total column is 3.
You can write the backspace character '\b' to move backwards on your line. This only moves your cursor so you'll have to hen write your content after you have backed up.
To move up you can use '\e[A' and '\e[B' to move down.
Note: This solution is not very portable, but if it works for your situation go for it!
You may also want to look into system specific functions if you want to move multiple lines or clear the entire screen.
Related
I am playing around with classes in C++. Currently I am working on a class for complex numbers and want to be able to print them in the following format: -2+3i, 1-4i. That means, that I want the real part to have only a sign if it is negative. In contrast the imaginary part should have always a sign whether it is positive or negative.
I tried the following which did not work as expected:
inline void Complex::print() const {
std::cout << x;
std::cout << std::showpos << y << "i" << std::endl;
}
This method prints also for the real part the sign if it is positive. Why does std::showpos affect the first line?
Is there any better way to do that?
showpos is "sticky", and applies to every following number until it's changed back with noshowpos.
You can use showpos with a local stream to avoid messing with std::cout:
inline void Complex::print() const {
std::ostringstream y_stream;
y_stream << showpos << y;
std::cout << x
<< y_stream.str() << 'i'
<< std::endl;
}
When the showpos format flag is set, a plus sign (+) precedes every non-negative numerical value inserted into the stream (including zeros). This flag can be unset with the noshowpos manipulator.
Minor change in your code:
inline void Complex::print() const {
std::cout << std::noshowpos << x;
std::cout << std::showpos << y << "i" << std::endl;
}
That's because the std::showpos flag affects every number inserted into the stream. (http://www.cplusplus.com/reference/ios/showpos/)
Have you tried using if statements?
if (x > 0)
{
std::cout << "+";
}
If you never use std::noshowpos, std::cout will keep the showpos flag, so that next time you call print() it affects x (and any other number you ever print with std::cout in your program).
So either use std::noshowpos directly after printing y:
std::cout << std::showpos << y << std::noshowpos << "i" << std::endl;
or directly before printing x:
std::cout << std::noshowpos << x;
This question already has answers here:
Why is address of char data not displayed?
(8 answers)
Closed 6 years ago.
After printing a pointer to an int, I print a pointer to a char:
#include <iostream>
using namespace std;
int main() {
int i;
cout << "&i: " << &i << endl;
char q = 'q';
cout << "&q: " << &q << endl;
return 0;
}
I get the following output as expected:
&i: 0xffffcc0c
&q: q
However, if I comment out cout << "&i: " << &i << endl;, and run the program again, I get the following unexplained output:
&q: q����
Does anyone know why this is happening?
If it has to do with operator<< inserting into the stream until it finds a null character, then why do I get the expected output when I include cout << "&i: " << &i << endl;?
NOTE: I am not expecting to get the address of q from cout. I am expecting to get the C string pointed to by &q. What bugs me is how the output just prints the 'q' if I include the line cout << "&i: " << &i << endl; beforehand. However, if I comment that line out, there is garbage data in the output. Why is there not garbage data in my output when I include the line cout << "&i: " << &i << endl;?
The bit &q thinks it is a string.
Therefore will print up to the null character. hence the extra output
I have an existing program that contains a loop over files. It does various things, providing lots of terminal output. I want to have an overall progress bar that remains stationary on the same line at the bottom of the terminal while all of the output from the file operations is printed above it. How should I try to do something like this?
EDIT: So, just to be clear, I'm trying to address the display problems inherent in something a bit like the following:
#include <unistd.h>
#include <iostream>
#include <string>
using namespace std;
int main(){
for (int i = 0; i <= 100; ++i){
std::cout << "processing file number " << i << "\n";
string progress = "[" + string(i, '*') + string(100-i, ' ') + "]";
cout << "\r" << progress << flush;
usleep(10000);
}
}
The only portable way of moving the cursor around that I know of is using \r to move to the beginning of the line. You mention that you would like to output stuff above the progress. Fortunately, you are in luck since you're on Linux and you can use the terminal escape codes to move around the terminal freely. Look at this example:
#include <unistd.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << endl;
for (int i=0; i <= 100; ++i)
{
string progress = "[" + string(i, '*') + string(100-i, ' ') + "]";
cout << "\r\033[F" << i << "\n" << progress << flush;
usleep(10000);
}
}
Here, I added the ability to print the progress value above the progress bar by moving to the beginning of the line using \r and one line up using escape code \033[F before printing. Then, printed one line, moved down one line with \n
and re-printed the progress.
You can go even further and move your cursor to any X,Y position in the terminal before printing. For that use the escape code \033[Y;Xf before your output.
For a good list of escape codes, check out Wikipedia: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes
So, it is possible to achive that behavior without using additional libs like ncurses, but maybe it is actually what you want if you intend to create a more gui-like experience.
Fixing your attempt:
void print_progress_bar(int percentage){
string progress = "[" + string(percentage, '*') + string(100 - percentage, ' ') + "]";
cout << progress << "\r\033[F\033[F\033[F" << flush;
}
int main(){
cout << endl;
for (int i=0; i <= 100; ++i){
std::cout << "processing file number " << i << "\n";
std::cout << " doing thing to file number " << i << "\n";
std::cout << " doing another thing to file number " << i << "\n";
print_progress_bar(i);
usleep(10000);
}
cout << endl;
cout << endl;
cout << endl;
cout << endl;
}
I am sure someone somewhere has had this same issue but I have looked far and wide (including here on the stackoverflow) to find out how to properly align my columns in an output file. The following is the complete code I am using (for an event generator called Pythia 8 of which C++ is the primary language):
using namespace Pythia8;
int main()
{
Pythia pythia;
pythia.readString("Top:gg2ttbar = 1");
pythia.init(2212, 2212, 14000.);
ofstream myfile;
myfile.open("ttbar.txt");
for (int iEvent = 0; iEvent < 1; ++iEvent)
{
if (!pythia.next()) continue;
vector<double> part;
for (int i = 0; i < pythia.event.size(); ++i)
{
if (pythia.event[i].status() == 91) part.push_back(i);
}
myfile << "N = " << part.size() << endl;
for (int j = 0; j < (int(part.size()) - 1); ++j)
{
myfile << left << setw(4) << int(part[j]);
myfile << setw(4) << left << pythia.event[part[j]].name() << " "
<< right << pythia.event[part[j]].id() << " "
<< pythia.event[part[j]].px() << " " << pythia.event[part[j]].py()
<< " " << pythia.event[part[j]].pz() << " "
<< pythia.event[part[j]].m() << " " << pythia.event[part[j]].pT() << endl;
}
}
pythia.stat();
myfile.close();
return 0;
}
The issue occurs near the bottom where the loop that writes out the text file starts, as it is currently written in the above code, the first two columns are mashed together:
N = 665
1777pi- -211 1.19978 0.715507 32.7878 0.13957 1.39694
1779pi+ 211 -8.24173 6.07047 -31.6818 0.13957 10.2361
That is the first couple lines of the output (the program shows the line number where a certain particle is produced and relevant information about it like the name, mass...etc.). I cannot seem to format it so I don't have to use the inserted spaces that I put in by hand.
as it is currently written in the above code, the first two columns are mashed together
well, yes, you explicitly wrote the first two columns with no whitespace between them:
myfile << left << setw(4) << int(part[j]);
myfile << setw(4) << left << pythia.event[part[j]].name() << ...
If you want a general way to format this without worrying adding manual whitespace, split it into two steps:
create a vector<string> containing the columns for each line (you can just use an ostringstream to format each column individually)
write a function to take that vector and write it to an ostream, with spaces between.
std::copy(begin, end, std::ostream_iterator(myfile, " "));
will be sufficient if you just want a fixed number of spaces between each column
I've been trying to format the output to the console for the longest time and nothing is really happening. I've been trying to use as much of iomanip as I can and the ofstream& out functions.
void list::displayByName(ostream& out) const
{
node *current_node = headByName;
// I have these outside the loop so I don't write it every time.
out << "Name\t\t" << "\tLocation" << "\tRating " << "Acre" << endl;
out << "----\t\t" << "\t--------" << "\t------ " << "----" << endl;
while (current_node)
{
out << current_node->item.getName() // Equivalent tabs don't work?
<< current_node->item.getLocation()
<< current_node->item.getAcres()
<< current_node->item.getRating()
<< endl;
current_node = current_node->nextByName;
}
// The equivalent tabs do not work because I am writing names,
// each of different length to the console. That explains why they
// are not all evenly spaced apart.
}
Is their anything that I can use to get it all properly aligned with each other?
The functions that I'm calling are self-explanatory and all of different lengths, so that don't align very well with each other.
I've tried just about everything in iomanip.
Think of it like using Microsoft Excel :)
You think of your stream as fields. So you set the width of the field first then you insert your text in that field. For example:
#include <iostream>
#include <iomanip>
#include <string>
int main()
{
using namespace std;
string firstName = "firstName",
secondName = "SecondName",
n = "Just stupid Text";
size_t fieldWidth = n.size(); // length of longest text
cout << setw(fieldWidth) << left << firstName << endl // left padding
<< setw(fieldWidth) << left << secondName << endl
<< setw(fieldWidth) << left << n << endl;
cout << setw(fieldWidth) << right << firstName << endl // right padding
<< setw(fieldWidth) << right << secondName << endl
<< setw(fieldWidth) << right << n << endl;
}
......
......
The field width means nothing but the width of the text + spaces. You could fill anything other than spaces:
string name = "My first name";
cout << setfill('_') << setw(name.size() + 10) << left << name;
.....
output::
My first name__________
......
I think the best way is to figure out your format then, write a new formatter that does all what you want:
#include <iostream>
#include <iomanip>
#include <string>
std::ostream& field(std::ostream& o)
{
// usually the console is 80-character wide.
// divide the line into four fields.
return o << std::setw(20) << std::right;
}
int main()
{
using namespace std;
string firstName = "firstName",
secondName = "SecondName",
n = "Just stupid Text";
size_t fieldWidth = n.size();
cout << field << firstName << endl
<< field << secondName << endl
<< field << n << endl;
}
If you started thinking about parametrized manipulators, only that accept one int or long parameter are easy to implement, other types are really obscure if you are not familiar with streams in C++.
Boost has a format library that allows you to easily format the ourput like the old C printf() but with type safety of C++.
Remember that the old C printf() allowed you to specify a field width. This space fills the field if the output is undersized (note it does not cope with over-sized fields).
#include <iostream>
#include <iomanip>
#include <boost/format.hpp>
struct X
{ // this structure reverse engineered from
// example provided by 'Mikael Jansson' in order to make this a running example
char* name;
double mean;
int sample_count;
};
int main()
{
X stats[] = {{"Plop",5.6,2}};
// nonsense output, just to exemplify
// stdio version
fprintf(stderr, "at %p/%s: mean value %.3f of %4d samples\n",
stats, stats->name, stats->mean, stats->sample_count);
// iostream
std::cerr << "at " << (void*)stats << "/" << stats->name
<< ": mean value " << std::fixed << std::setprecision(3) << stats->mean
<< " of " << std::setw(4) << std::setfill(' ') << stats->sample_count
<< " samples\n";
// iostream with boost::format
std::cerr << boost::format("at %p/%s: mean value %.3f of %4d samples\n")
% stats % stats->name % stats->mean % stats->sample_count;
}
Give up on the tabs. You should be able to use io manipulators to set the field width, the fill character, and the format flag (to get left or right justification). Use the same values for the headings as you do for the data, and everything should come out nicely.
Also beware that you've switched Rating and Acres in your example.
You can write a procedure that always print the same number of characters to standard output.
Something like:
string StringPadding(string original, size_t charCount)
{
original.resize(charCount, ' ');
return original;
}
And then use like this in your program:
void list::displayByName(ostream& out) const
{
node *current_node = headByName;
out << StringPadding("Name", 30)
<< StringPadding("Location", 10)
<< StringPadding("Rating", 10)
<< StringPadding("Acre", 10) << endl;
out << StringPadding("----", 30)
<< StringPadding("--------", 10)
<< StringPadding("------", 10)
<< StringPadding("----", 10) << endl;
while ( current_node)
{
out << StringPadding(current_node->item.getName(), 30)
<< StringPadding(current_node->item.getLocation(), 10)
<< StringPadding(current_node->item.getRating(), 10)
<< StringPadding(current_node->item.getAcres(), 10)
<< endl;
current_node = current_node->nextByName;
}
}