I'm programming some very simple stuff and I want to make a neat little "text box" at the beginning of my program in the command prompt with some basic info. An example of what I mean:
cout << "Creators: J. Adams & T. Jefferson" << endl;
cout << "Nicknames: Johnnny & Tommy" << endl;
cout << "Age: 20 & 21" << endl;
cout << "This program is for ..... << endl;
This is just an example, and one of the things I'd like is a simple way to align these things (so that "Johnny" is directly below "J. Adams", or at least directly enough so you know they belong together). I know of setw but you have to include for that, and I'd like a method where you don't have to use that.
Other than that, I'd like a simple way to put an outline around the text (that's what I mean by text "box"). Nothing to fancy, just something you can do with the first 128 normal characters. I've googled around for something similar to no avail.
Related
Im working on a school assignment in which i need to format a query of some dummy data. The specific query gathers data on a few fields in a set of two tables, and prints it out to the console in C++.
While this works as expected, the only issue is formatting output so that it appears correctly. In our example output in the assignment document, this is shown as being the proper output
<ID> <name> <email> <phone> <ext> <manager>
not the exact spacing but more or less what needs to be done. The initial output i get in the console is similar to this, and looks like:
1056 Tim Tomphson ttomph#fakeEmailService.com +1 800 555 1580 x5122 Tom Timsphon
Until about a few entries down when suddenly the data becomes completely unformatted.
Now im confused, cause I thought i had the formatting right, and dont know why its fallen to hell around that point specifically since everything else up to that was basically perfect. and i dont know how to format it right so that it can return to a proper tabular output.
the code im using for this output is
cout << left << setw(10) << temp.empNum << "\t" << temp.firstName << " " << temp.lastName << "\t\t" << temp.email << "\t\t" << temp.phone << "\t\t" << temp.extension << "\t\t" << temp.reportsTo << endl;
I've also tried using printf statements, but that had less luck and was nowhere as close to successful as this command itself...does anyone have any ideas that could help me out?
So i searched for it and i found many answers. I found that in c++ there's no standard cross-platform way to do that and that the operative system manages colors. For example i found that on windows you can use the system("color 1") statement to change color to the text ( or foreground) and the system("color A") to change color to the background, or both system("color 1A") to change both. But this will change the whole colors, and i was wondering if there was a way to change it like even for a single character. Like take the program that i just did as an example:
#include<iostream>
using namespace std; /* I prefer to use this because i think that's a huge time saver and it's also easier*/
void printRoad(int i) /* That's my function, so by this function it prints a number of times choosed by the user 4 pieces of road*/
{
int counter=1;
while (counter <= i)
{
system("color 2"); /*Here is what i was talking about. I used the system("color 2") statement to change the text color
from the default to green, but it changes the whole text.*/
cout << "** | **" << endl;
cout << "** | **" << endl;
cout << "** | **" << endl;
cout << "** | **" << endl;
counter++;
}
};
void main() /*I don't need any specific return value from either the main() and the function so i thought it was a good idea to
just use void.*/
{
cout << "How many piece of roads do you want to build?" << endl; /*Here it asks to the user what to do.*/
int pieces = 0;
cin >> pieces;
printRoad(pieces); //Here is the function call.
system("pause"); /* Because i'm using windows and i'm using Visual Studio Express 2013 I used system("pause") to pause
the program and let the user see the output.*/
}
So what if, for example, i'd like to change each piece of road color? Like the first cout<<"** | **"<
I also read many people complaining about the use of system("") statements. I understand it because by doing so your program lose the cross-platform ability. But if the thing is dependent on the system we're on, how should we do it by keeping the cross-platform ability? Thanks for any answer.
Actually you can use this instead of calling system():
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), ValueOfColour);
As far as I understood your problem, you only want a certain character to be in your choosen colour. Then you need to change it back to the default value white/grey after this character was printed.
As part of a bigger application I am working on a class for reading input from a text file for use in the initialization of the program. Now I am myself fairly new to programming, and I only started to learn C++ in December, so I would be very grateful for some hints and ideas on how to get started! I apologise in advance for a rather long wall of text.
The text file format is "keyword-driven" in the following way:
There are a rather small number of main/section keywords (currently 8) that need to be written in a given order. Some of them are optional, but if they are included they should adhere to the given ordering.
Example:
Suppose there are 3 potential keywords ordered like as follows:
"KEY1" (required)
"KEY2" (optional)
"KEY3" (required)
If the input file only includes the required ones, the ordering should be:
"KEY1"
"KEY3"
Otherwise it should be:
"KEY1"
"KEY2"
"KEY3"
If all the required keywords are present, and the total ordering is ok, the program should proceed by reading each section in the sequence given by the ordering.
Each section will include a (possibly large) amount of subkeywords, some of which are optional and some of which are not, but here the order does NOT matter.
Lines starting with characters '*' or '--' signify commented lines, and they should be ignored (as well as empty lines).
A line containing a keyword should (preferably) include nothing else than the keyword. At the very least, the keyword must be the first word appearing there.
I have already implemented parts of the framework, but I feel my approach so far has been rather ad-hoc. Currently I have manually created one method per section/main keyword , and the first task of the program is to scan the file for to locate these keywords and pass the necessary information on to the methods.
I first scan through the file using an std::ifstream object, removing empty and/or commented lines and storing the remaining lines in an object of type std::vector<std::string>.
Do you think this is an ok approach?
Moreover, I store the indices where each of the keywords start and stop (in two integer arrays) in this vector. This is the input to the above-mentioned methods, and it would look something like this:
bool readMAINKEY(int start, int stop);
Now I have already done this, and even though I do not find it very elegant, I guess I can keep it for the time being.
However, I feel that I need a better approach for handling the reading inside of each section, and my main issue is how should I store the keywords here? Should they be stored as arrays within a local namespace in the input class or maybe as static variables in the class? Or should they be defined locally inside relevant functions? Should I use enums? The questions are many!
Now I've started by defining the sub-keywords locally inside each readMAINKEY() method, but I found this to be less than optimal. Ideally I want to reuse as much code as possible inside each of these methods, calling upon a common readSECTION() method, and my current approach seems to lead to much code duplication and potential for error in programming. I guess the smartest thing to do would simply be to remove all the (currently 8) different readMAINKEY() methods, and use the same function for handling all kinds of keywords. There is also the possibility for having sub-sub-keywords etc. as well (i.e. a more general nested approach), so I think maybe this is the way to go, but I am unsure on how it would be best to implement it?
Once I've processed a keyword at the "bottom level", the program will expect a particular format of the following lines depending on the actual keyword. In principle each keyword will be handled differently, but here there is also potential for some code reuse by defining different "types" of keywords depending on what the program expects to do after triggering the reading of it. Common task include e.g. parsing an integer or a double array, but in principle it could be anything!
If a keyword for some reason cannot be correctly processed, the program should attempt as far as possible to use default values instead of terminating the program (if reasonable), but an error message should be written to a logfile. For optional keywords, default values will of course also be used.
In order to summarise, therefore, my main questions are the following:
1. Do you think think my approach of storing the relevant lines in a std::vector<std::string> to be reasonable?
This will of course require me to do a lot of "indexing work" to keep track of where in the vector the different keywords are located. Or should I work more "directly" with the original std::ifstream object? Or something else?
2. Given such a vector storing the lines of the text file, how I can I best go about detecting the keywords and start reading the information following them?
Here I will need to take account of possible ordering and whether a keyword is required or not. Also, I need to check if the lines following each "bottom level" keyword is in the format expected in each case.
One idea I've had is to store the keywords in different containers depending on whether they are optional or not (or maybe use object(s) of type std::map<std::string,bool>), and then remove them from the container(s) if correctly processed, but I am not sure exactly how I should go about it..
I guess there is really a thousand different ways one could answer these questions, but I would be grateful if someone more experienced could share some ideas on how to proceed. Is there e.g. a "standard" way of doing such things? Of course, a lot of details will also depend on the concrete application, but I think the general format indicated here can be used in a lot of different applications without a lot of tinkering if programmed in a good way!
UPDATE
Ok, so let my try to be more concrete. My current application is supposed to be a reservoir simulator, so as part of the input I need information about the grid/mesh, about rock and fluid properties, about wells/boundary conditions throughout the simulation and so on. At the moment I've been thinking about using (almost) the same set-up as the commercial Eclipse simulator when it comes to input, for details see
http://petrofaq.org/wiki/Eclipse_Input_Data.
However, I will probably change things a bit, so nothing is set in stone. Also, I am interested in making a more general "KeywordReader" class that with slight modifications can be adapted for use in other applications as well, at least it can be done in a reasonable amount of time.
As an example, I can post the current code that does the initial scan of the text file and locates the positions of the main keywords. As I said, I don't really like my solution very much, but it seems to work for what it needs to do.
At the top of the .cpp file I have the following namespace:
//Keywords used for reading input:
namespace KEYWORDS{
/*
* Main keywords and corresponding boolean values to signify whether or not they are required as input.
*/
enum MKEY{RUNSPEC = 0, GRID = 1, EDIT = 2, PROPS = 3, REGIONS = 4, SOLUTION = 5, SUMMARY =6, SCHEDULE = 7};
std::string mainKeywords[] = {std::string("RUNSPEC"), std::string("GRID"), std::string("EDIT"), std::string("PROPS"),
std::string("REGIONS"), std::string("SOLUTION"), std::string("SUMMARY"), std::string("SCHEDULE")};
bool required[] = {true,true,false,true,false,true,false,true};
const int n_key = 8;
}//end KEYWORDS namespace
Then further down I have the following function. I am not sure how understandable it is though..
bool InputReader::scanForMainKeywords(){
logfile << "Opening file.." << std::endl;
std::ifstream infile(filename);
//Test if file was opened. If not, write error message:
if(!infile.is_open()){
logfile << "ERROR: Could not open file! Unable to proceed!" << std::endl;
std::cout << "ERROR: Could not open file! Unable to proceed!" << std::endl;
return false;
}
else{
logfile << "Scanning for main keywords..." << std::endl;
int nkey = KEYWORDS::n_key;
//Initially no keywords have been found:
startIndex = std::vector<int>(nkey, -1);
stopIndex = std::vector<int>(nkey, -1);
//Variable used to control that the keywords are written in the correct order:
int foundIndex = -1;
//STATISTICS:
int lineCount = 0;//number of non-comment lines in text file
int commentCount = 0;//number of commented lines in text file
int emptyCount = 0;//number of empty lines in text file
//Create lines vector:
lines = std::vector<std::string>();
//Remove comments and empty lines from text file and store the result in the variable file_lines:
std::string str;
while(std::getline(infile,str)){
if(str.size()>=1 && str.at(0)=='*'){
commentCount++;
}
else if(str.size()>=2 && str.at(0)=='-' && str.at(1)=='-'){
commentCount++;
}
else if(str.size()==0){
emptyCount++;
}
else{
//Found a non-empty, non-comment line.
lines.push_back(str);//store in std::vector
//Start by checking if the first word of the line is one of the main keywords. If so, store the location of the keyword:
std::string fw = IO::getFirstWord(str);
for(int i=0;i<nkey;i++){
if(fw.compare(KEYWORDS::mainKeywords[i])==0){
if(i > foundIndex){
//Found a valid keyword!
foundIndex = i;
startIndex[i] = lineCount;//store where the keyword was found!
//logfile << "Keyword " << fw << " found at line " << lineCount << " in lines array!" << std::endl;
//std::cout << "Keyword " << fw << " found at line " << lineCount << " in lines array!" << std::endl;
break;//fw cannot equal several different keywords at the same time!
}
else{
//we have found a keyword, but in the wrong order... Terminate program:
std::cout << "ERROR: Keywords have been entered in the wrong order or been repeated! Cannot continue initialisation!" << std::endl;
logfile << "ERROR: Keywords have been entered in the wrong order or been repeated! Cannot continue initialisation!" << std::endl;
return false;
}
}
}//end for loop
lineCount++;
}//end else (found non-comment, non-empty line)
}//end while (reading ifstream)
logfile << "\n";
logfile << "FILE STATISTICS:" << std::endl;
logfile << "Number of commented lines: " << commentCount << std::endl;
logfile << "Number of non-commented lines: " << lineCount << std::endl;
logfile << "Number of empty lines: " << emptyCount << std::endl;
logfile << "\n";
/*
Print lines vector to screen:
for(int i=0;i<lines.size();i++){
std:: cout << "Line nr. " << i << " : " << lines[i] << std::endl;
}*/
/*
* So far, no keywords have been entered in the wrong order, but have all the necessary ones been found?
* Otherwise return false.
*/
for(int i=0;i<nkey;i++){
if(KEYWORDS::required[i] && startIndex[i] == -1){
logfile << "ERROR: Incorrect input of required keywords! At least " << KEYWORDS::mainKeywords[i] << " is missing!" << std::endl;;
logfile << "Cannot proceed with initialisation!" << std::endl;
std::cout << "ERROR: Incorrect input of required keywords! At least " << KEYWORDS::mainKeywords[i] << " is missing!" << std::endl;
std::cout << "Cannot proceed with initialisation!" << std::endl;
return false;
}
}
//If everything is in order, we also initialise the stopIndex array correctly:
int counter = 0;
//Find first existing keyword:
while(counter < nkey && startIndex[counter] == -1){
//Keyword doesn't exist. Leave stopindex at -1!
counter++;
}
//Store stop index of each keyword:
while(counter<nkey){
int offset = 1;
//Find next existing keyword:
while(counter+offset < nkey && startIndex[counter+offset] == -1){
offset++;
}
if(counter+offset < nkey){
stopIndex[counter] = startIndex[counter+offset]-1;
}
else{
//reached the end of array!
stopIndex[counter] = lines.size()-1;
}
counter += offset;
}//end while
/*
//Print out start/stop-index arrays to screen:
for(int i=0;i<nkey;i++){
std::cout << "Start index of " << KEYWORDS::mainKeywords[i] << " is : " << startIndex[i] << std::endl;
std::cout << "Stop index of " << KEYWORDS::mainKeywords[i] << " is : " << stopIndex[i] << std::endl;
}
*/
return true;
}//end else (file opened properly)
}//end scanForMainKeywords()
You say your purpose is to read initialization data from a text file.
Seems you need to parse (syntax analyze) this file and store the data under the right keys.
If the syntax is fixed and each construction starts with a keyword, you could write a recursive descent (LL1) parser creating a tree (each node is a stl vector of sub-branches) to store your data.
If the syntax is free, you might pick JSON or XML and use an existing parsing library.
I wrote a numerical simulation and, as a tweak, I wanted to add some basic progress bar.
In the main loop I wrote:
if(particles.t>=pr*maxtime){
cout << "|";
pr+=0.01;
}
Where pr starts at 0.01. So, basically it was supposed to cout one hundred "|" during the computation. Instead of that it couts these "|" at the end of the simulation, all at once.
And when I modify this code to:
if(particles.t>=pr*maxtime){
cout << pr << "\n";
pr+=0.01;
}
it works as it should.
I guess it have something to do with optimization, I am compiling my code using g++, with options -Wall and -lm. Code like this worked when I wrote it in C#, a while ago.
The problem is with the buffering of the output. Place cout.flush(); after each printing and the issue should be solved.
The writes to cout (and many other streams) are buffered. If you want to make them immediately visible, you need to flush the stream:
if(particles.t>=pr*maxtime){
cout << "|";
cout.flush();
pr+=0.01;
}
I feel pretty stupid, but I'm just starting to learn c++ after coming from other languagues, and I cannot for the life of me comprehend statements that use "<<" and ">>". I know it is simple, but it confuses me every time.
The book I'm using made a really good recommendation to read const declarations from right to left. Is there any similar method for "<<" and ">>"?
i like to say "gets".
cout << "some expression = " << expr << endl;
i'd say that as "cout gets some expression, gets expr, gets endull." similarly if you're reading from a stream, it's your variable that "gets" a value from the input...
On the phone, back when I was a consultant frequently needing to "read aloud" C++ code to clients' employees on the phone, I (explaining once or twice, then they got it) read "input" operator >> as "absorb" and "output" operator << as "emit". "get" and "put" would work just as well if they didn't conflict with alas-too-common other uses. But that doesn't seem to have much to do with right-to-left vs left-to-right, just with your Q's title about "reading aloud" -- "cin absorb x" or "essteedee cout emit blach emit essteedee endl" kinds of "reading code aloud" (e.g. on the phone)!-)
I typically read them from left to right, like so:
cout << setw(6) << val << endl;
"Send to cout, with a width of 6, the contents of val, and then end the line and flush."
or
cin >> val;
"Get from cin the contents of val."
It does take a little bit of special consideration in that you can't just say specific words for each token.
To understand C++, you have to understand that C++ has many of the most powerful tools to build abstractions. cout is nothing but a stream. So, it is very acceptable to mimic the concept of stream.
For example,
std::cout << "hey"; // '<<' is something like the direction of the `data`
throws things in the stream with the same syntax and conventions, infact there is only one syntax for all types.
Also,
std::cin >> number;
extracts the next value of the type specified by number and put it in number.
It just make sense when you think about streams in C++. You can see this in most modern C++ libraries, for example with Boost you can do this:
boost::filesystem::path mypath;
....
mypath = mypath/filename;
The division operator is replaced with '/' or '\' depending on the system you are targeting :)
I never thought too much about it but I suppose you could say "Streams to" or "Streams from" eg.
cout << mysting << endl;
"cout streams from mystring streams from endline"
cin >> myvalue;
"cin streams to myvalue"
I just made that up but it makes sense to me.
This is easy enough the object that the symbol is pointing to on the receiving end. So:
cout << "Enter First Name: ";
cin >> FirstName;
in this code, cout in usually stdout and is "receiving" the characters "Enter First Name", FirstName which is presumably a variable is "receiving" the data from cin which is probably stdin.
A simple way to distinguish the two is like so.
cout << "Some fancy string...";
In this example your are taking a string and sending it to the world (monitor).
cin >> x;
In that one you take an value from the world (keyboard) and save the it into x.
Hence the direction Value >> X.