setw not working as expected - c++

I'm trying to print time in hh:mm format but when the time is like 01:01 it prints as 1:1. Here's my code:
void output(int hour, int min, char ampm){
cout << setw(2) << setfill('0') << "The time is: " << hour << ":" << min << " ";
if(ampm == 'P'){
cout << "PM";
}
else if (ampm == 'A'){
cout << "AM";
}
}
As I understand it, this should work. I include iomanip. Can you see anything wrong with it?

The width is a special formatting setting: While all other formatting flags are stick, the width() will be reset by each output operator (well, you can have user-defined output operators which don't reset the width() but doing so would not follow the normal style). That is, you need to set the width immediately prior to the output that should be affected:
std::cout << std::setfill('0')
<< std::setw(2) << hour << ':'
<< std::setw(2) << min << ' ';

Following is correct way:
cout<<""The time is: ";
cout << setfill('0') <<setw(2) << hour << ":" <<setw(2) << min << " ";
Ref :-this

Related

How can I change the values of the system clock using C++?

I've been trying to figure out how to use the system clock for a class project. The goal is to display the system's current time, then through inputs of 1-4 add one hour, minute, or second, then display the clock again. I think I have the basic framework down but I cannot figure out how to display the system time correctly as well as change the time itself. I have researched a few of the libraries to use and it gets pretty confusing with the pointers and the way it also always prints the date as well. I'm still new to C++ so my code is not the best especially when formatting the functions for the displays. Any help is appreciated.
When I run the program I want to print the local time from the PC it is running on, then receive input from the user (keystroke 1 - 4), then print the new time again. I don't want to actually change the time on my PC. For example say the current local time of my computer is 08:22:14, which will print to the screen. I wait any amount of time before I input selection 2. The new time will print 08:23:14.
#define _CRT_SECURE_NO_WARNINGS
#include <time.h> /* time_t, struct tm, time, localtime */
#include <iostream> // std::cout, std::endl
#include <iomanip> // std::setfill, std::setw
#include <stdlib.h> // system(CLS);
#include <Windows.h>
#include <ctime>
using namespace std;
int DisplayClocks(int time) { // Function to write both clocks to screen
std::cout << std::setfill('*') << std::setw(26) << " " << std::setfill('*') << std::setw(26) << " " << endl; // First line of "*"
std::cout << "*" << std::setfill(' ') << std::setw(16) << "12 Hour Clock" << std::setfill(' ') << std::setw(4) << " *" << " "
<< "*" << std::setfill(' ') << std::setw(18) << "24 Hour Clock" << std::setfill(' ') << std::setw(6) << " *" << endl;
// 12 hour clock
std::cout << "*" << std::setfill(' ') << std::setw(6) << " " << time << std::setfill(' ') << std::setw(6) << " *" << " "
// 24 hour clock
<< "*" << std::setfill(' ') << std::setw(8) << " " << std::setfill(' ') << std::setw(8) << " *" << endl;
std::cout << std::setfill('*') << std::setw(26) << " " << std::setfill('*') << std::setw(26) << " " << endl; // Last line of "*"
return 0;
}
void DisplaySelection() { // Function to display selection menu for user
std::cout << std::setfill('*') << std::setw(26) << " " << endl;
std::cout << "*" << std::setfill(' ') << std::setw(19) << "1 - Add One Hour" << std::setfill(' ') << std::setw(5) << " *" << endl;
std::cout << "*" << std::setfill(' ') << std::setw(20) << "2 - Add One Minute" << std::setfill(' ') << std::setw(4) << " *" << endl;
std::cout << "*" << std::setfill(' ') << std::setw(20) << "3 - Add One Second" << std::setfill(' ') << std::setw(4) << " *" << endl;
std::cout << "*" << std::setfill(' ') << std::setw(19) << "4 - Exit Program" << std::setfill(' ') << std::setw(5) << " *" << endl;
std::cout << std::setfill('*') << std::setw(26) << " " << endl;
}
void main()
{
time_t now = time(0);
system("CLS");
string userVal;
DisplayClocks(now); // Call displayClocks on program start
DisplaySelection(); // Call DisplaySelection after display clocks
cin >> userVal; // Take user input to modify clock display
while (!( userVal == "Exit")) {
// FIX ME: Add functionality to clear screen every second
// FIX ME: Add displayClock to relevant if statements
if (userVal == "1") {
// Add One Hour to Clocks
// FIX ME: Functionality for Displaying 12 and 24 hour clocks
system("CLS"); // Clear screen test... working...
DisplayClocks(now); // Call displayClocks on program start
DisplaySelection(); // Call DisplaySelection after display clocks
cout << "1" << endl;
cin >> userVal;
}
else if (userVal == "2") {
// Add One Minute to Clocks
// FIX ME: Functionality for Displaying 12 and 24 hour clocks
system("CLS"); // Clear screen test... working...
DisplayClocks(now); // Call displayClocks on program start
DisplaySelection(); // Call DisplaySelection after display clocks
cout << "2" << endl;
cin >> userVal;
}
else if (userVal == "3") {
// Add One Second to Clocks
// FIX ME: Functionality for Displaying 12 and 24 hour clocks
system("CLS"); // Clear screen test... working...
DisplayClocks(now); // Call displayClocks on program start
DisplaySelection(); // Call DisplaySelection after display clocks
cout << "3" << endl;
cin >> userVal;
}
else if (userVal == "4") {
// Exit Program
// FIX ME: Functionality for Displaying 12 and 24 hour clocks
cout << "Program Ended" << endl;
break;
}
else{
// Prompt user to input correct selection when not userVal ! (1-4)
system("CLS"); // Clear screen test... working...
DisplayClocks(now);
DisplaySelection();
cout << "Error: Enter a selection 1 - 4." << endl;
cin >> userVal;
}
}
}
When you ask "How can I change SYSTEM <anything> in C++?", the keyword is "system".
It means that it's platform-dependent, so it needs a SYSTEM call - and I'm not speaking about the system function, but a call to your operating system's API, Win32 in your case. And a lot of these functions will requires elevation to work, on both Windows and Linux...
Unfortunately for you, changing system date and time is such a function, on both OS, and it isn't allowed to call it with a standard account.
Also, it has nothing related with C++, in fact. On Windows, you'll need to call SetSystemTime, and it's not a C++ feature but a function of kernel32.dll imported through sysinfoapi.h header (found in Windows SDK).
You'll get exactly the same answer in near any programming language: "Do a system call to SetSystemTime".

Alphabetically Sort Structure Array

so I have a structure array with various variables.
struct Data
{
char name[11];
int ID;
int life;
int date;
float avgWindSpeed;
float avgRainFall;
int tornadoes;
int stormCategory;
};
I am looking to sort all the information based on char name[11]. The data that is stored in struct Data comes from a file named storms.txt. Currently, I have everything to make up perfectly but still struggling with sorting everything alphabetically. Also, I named my ofstream outfile and counter contains the total number of storms inside the file.
My current code is:
//--------------------------------------------------------------------------------------------------------------------------------------------------
//Start of Hurricane Level 1
int totalLevel1 = 0; //Will hold the number of storms that are level 1
//This is just setting the top part of the chart
outfile << setw(70) << "Hurricane Level 1" << endl << endl;
outfile << "Name" << setw(10) << "ID" << setw(20) << " Life " << setw(20) << " Average " << setw(20) << " Average " << setw(20) << "Tornadoes" << setw(19) << " Date " << endl;
outfile << " " << setw(10) << " " << setw(20) << "in days" << setw(20) << "wind speed" << setw(20) << "rain fall" << setw(20) << " spawned " << setw(20) << " " << endl;
outfile << endl << endl;
float avgLifeSpan, avgRainFall, avgTornadoes, avgWindSpeed, life = 0, rain= 0, tornado= 0, wind= 0;
//Starting to process the information and printing it in its proper location
for(int i = 0; i < counter; i++)
if(hurricanes[i].stormCategory == 1)
{
totalLevel1++;
life = life + hurricanes[i].life;
rain = rain + hurricanes[i].avgRainFall;
tornado = tornado + hurricanes[i].tornadoes;
wind = wind + hurricanes[i].avgWindSpeed;
outfile << hurricanes[i].name << setw(5) << hurricanes[i].ID << setw(15) << hurricanes[i].life << setw(21) << hurricanes[i].avgWindSpeed
<< setw(20) << hurricanes[i].avgRainFall << setw(19) << hurricanes[i].tornadoes << setw(21) << hurricanes[i].date << endl;
}
//Printing the extra information for HURRICANE LEVEL 1
outfile << endl << endl << "Total number of Level 1 hurricanes is " << totalLevel1 << "." << endl;
outfile << "Average Life span in days of Level 1 hurricanes is " << life / float(totalLevel1) << "." << endl;
outfile << "Average rain fall for Level 1 hurricanes is " << rain / float(totalLevel1) << "." << endl;
outfile << "Average tornadoes spawned for Level 1 hurricanes is " << tornado / float(totalLevel1) << "." << endl;
outfile << "Average wind speed for Level 1 hurricanes is " << wind / float(totalLevel1) << "." << endl;
outfile << endl << endl;
//End of the Hurricane Level 1
//--------------------------------------------------------------------------------------------------------------------------------------------------
How to do I make so that everything that gets printed out on the output file is sorted alphabetically with its correct information? Could someone give me some suggestions?
It depends on how you've defined hurricanes. If it is a C array, then you'll be wanting something like this:
std::sort(hurricanes, hurricanes + counter,
[](const Data& a, const Data& b) { return std::strcmp(a.name, b.name) < 0; });
If however it is a std::vector or std::array, then...
std::sort(hurricanes.begin(), hurricanes.end(),
[](const Data& a, const Data& b) { return std::strcmp(a.name, b.name) < 0; });
I don't see what type of container you use ( I suggest to use std::vector), but you may do couple of nice things to make you life easier in this code.
First overload operators in Data structure like:
ostream& operator<<(ostream& os, const Data& a_data) for easily sending your struct to ostream (without need of encapsulating all it's members).
bool T::operator <(const T2 &b) const; , bool T::operator >(const T2 &b) const; : for comparison in standard algorithms.
Take look at reference : link You will write it only once but could use it in every part of program.
Second suggestion is to use std::sort algorithm to sort your data structure.
std::sort(hurricanes.begin(), hurricanes.end(), greater<Data>());
Syntax of your code will be much easier to understand and read for you wen you come back to project in 6 (or so) months.

How can I display a $ sign with a value while using setw and setprecision in c++

I want to display the dollar sign next to its value in the second column, but if I convert the value into a string, the setprecision doesn't work and it displayed more decimals than I would like. Currently the formatting doesn't look good.
My current code:
string unit = "m";
double width = 30.123;
double length = 40.123;
double perimeter = 2 * width + 2 * length;
double area = width * length;
double rate = (area <= 3000) ? 0.03 : 0.02;
double cost = area * rate;
const int COLFMT = 20;
cout << fixed << setprecision(2);
cout << setw(COLFMT) << left << "Length:"
<< setw(COLFMT) << right << length << " " << unit << endl;
cout << setw(COLFMT) << left << "Width:"
<< setw(COLFMT) << right << width << " " << unit << endl;
cout << setw(COLFMT) << left << "Area:"
<< setw(COLFMT) << right << area << " square" << unit << endl;
cout << setw(COLFMT) << left << "Perimeter:"
<< setw(COLFMT) << right << perimeter << " " << unit << endl;
cout << setw(COLFMT) << left << "Rate:"
<< setw(COLFMT) << right << rate << "/sqaure" << unit << endl;
cout << setw(COLFMT) << left << "Cost:"
<< setw(COLFMT) << right << "$" << cost << endl;
Produces this poorly formatted output:
Length: 40.12 m
Width: 30.12 m
Area: 1208.63 square m
Perimeter: 140.49 m
Rate: 0.03/square m
Cost: $36.26
"Currently the formatting doesn't look good."
That's because std::right pertains to what follows it, in your case "$". So the dollar sign is right-aligned and not the value that follows on afterwards.
What you want is the fully formatted monetary value "$36.26" to be right aligned. So build that up as a string first with stringstream.
stringstream ss;
ss << fixed << setprecision(2) << "$" << cost;
cout << left << "Cost:" << setw(COLFMT) << right << ss.str() << endl;

C to C++ printf

How would I change this code, preserving formatting to C++ using cout?
printf(" %5lu %3d %+1.2f ", nodes, depth, best_score / 100.0);
To be honest, I've never liked the ostream formatting mechanism. I've tended to use boost::format when I need to do something like this.
std::cout << boost::format(" %5lu %3d %+1.2f ") % nodes % depth % (best_score / 100.0);
#include <iostream>
#include <iomanip>
void func(unsigned long nodes, int depth, float best_score) {
//store old format
streamsize pre = std::cout.precision();
ios_base::fmtflags flags = std::cout.flags();
std::cout << setw(5) << nodes << setw(3) << depth;
std::cout << showpos << setw(4) << setprecision(2) << showpos (best_score/100.);
//restore old format
std::cout.precision(pre);
std::cout.flags(flags);
}
Use cout.width(n) and cout.precision(n);
So, for example:
cout.width(5);
cout << nodes << " ";
cout.width(3);
cout << depth << " ";
cout.setiosflags(ios::fixed);
cout.precision(2);
cout.width(4);
cout << best_score/100.0 << " " << endl;
You can chain things together:
cout << width(5) << nodes << " " << width(3) << depth << " "
<< setiosflags(ios::fixed) << precision(2) << best_score/100.0 << " "
<< endl;

C++ - How to reset the output stream manipulator flags [duplicate]

This question already has answers here:
Restore the state of std::cout after manipulating it
(9 answers)
Closed 4 years ago.
I've got a line of code that sets the fill value to a '-' character in my output, but need to reset the setfill flag to its default whitespace character. How do I do that?
cout << setw(14) << " CHARGE/ROOM" << endl;
cout << setfill('-') << setw(11) << '-' << " " << setw(15) << '-' << " " << setw(11) << '-' << endl;
I thought this might work:
cout.unsetf(ios::manipulatorname) // Howerver I dont see a manipulator called setfill
Am I on the wrong track?
Have a look at the Boost.IO_State_Savers, providing RAII-style scope guards for the flags of an iostream.
Example:
#include <boost/io/ios_state.hpp>
{
boost::io::ios_all_saver guard(cout); // Saves current flags and format
cout << setw(14) << " CHARGE/ROOM" << endl;
cout << setfill('-') << setw(11) << '-' << " " << setw(15) << '-' << " " << setw(11) << '-' << endl;
// dtor of guard here restores flags and formats
}
More specialized guards (for only fill, or width, or precision, etc... are also in the library. See the docs for details.
You can use copyfmt to save cout's initial formatting. Once finished with formatted output you can use it again to restore the default settings (including fill character).
{
// save default formatting
ios init(NULL);
init.copyfmt(cout);
// change formatting...
cout << setfill('-') << setw(11) << '-' << " ";
cout << setw(15) << '-' << " ";
cout << setw(11) << '-' << endl;
// restore default formatting
cout.copyfmt(init);
}
You can use the ios::fill() function to set and restore the fill character instead.
http://www.cplusplus.com/reference/iostream/ios/fill/
#include <iostream>
using namespace std;
int main () {
char prev;
cout.width (10);
cout << 40 << endl;
prev = cout.fill ('x');
cout.width (10);
cout << 40 << endl;
cout.fill(prev);
return 0;
}
You can manually change the setfill flag to whatever you need it to be:
float number = 4.5;
cout << setfill('-');
cout << setw(11) << number << endl; // --------4.5
cout << setfill(' ');
cout << setw(11) << number << endl; // 4.5
The null character will reset it back to the original state:
setfill('\0')