Reputation: 13
I am creating my first program to display the date of someone's birthday. This is really a beginners thing.
I just wanted to know, how would I display it with the format of MM/DD/YY?
Here is my programming code below. For some reason, when it displays the birthday, it shows a random number. Why is this?
#include <iostream>
using namespace std;
int main() {
int m,d,y;
cout << "Please enter your birthday in the format of MM/DD/YY ";
cin >> m >> d >> y;
cout << "Your birthday is: " << m << d << y << endl;
return 0;
}
Upvotes: 0
Views: 3920
Reputation: 4339
In addition to manually filtering the separator out as done in Abdul's answer, there are a few other ways we can parse a MM/DD/YY
string to obtain a date from it. I'll look at two of them, to give you other things to explore as you learn.
The first is to extract the raw data for each part of the date string, and then convert it to int
. There are multiple ways to do this, but the simplest is to just use std::string
and its associated std::getline()
.
#include <iostream> // std::cin, std::cout
#include <string> // std::string, std::stoi(), std::getline(istream, string).
using namespace std;
int main() {
// Constants. Could also use const instead of constexpr.
constexpr char Sep = '/'; // Field separator.
constexpr int Fields = 3; // Storing field count as a constant for clarity.
//int m,d,y;
int mdy[Fields]; // Storing in an array to simplify code.
cout << "Please enter your birthday in the format of MM/DD/YY ";
//cin >> m >> d >> y;
// Extract & parse. Will be executed 3 times.
for (int i = 0; i < Fields; i++) {
string parser;
getline(cin, parser, Sep); // Pull out everything up to the next Sep or end of stream, then throw away Sep (if present).
mdy[i] = stoi(parser); // Convert string to int.
}
//cout << "Your birthday is: " << m << d << y << endl;
cout << "Your birthday is: ";
// Output data. Will be executed 3 times.
for (int i = 0; i < Fields; i++) {
cout << mdy[i] // Output field.
<< (i < (Fields - 1) ? Sep : '\n'); // Output Sep after all but last field, or newline after last field.
}
return 0;
}
This will take each part of the date out of std::cin
as a set of characters, stopping whenever it reaches a /
or the end of the input. It then treats the characters as a string containing a number, and takes the number out of it for later use. It does so using a loop, which will execute 3 (Fields
) times. [This is a bit worse than your original code, but makes up for it by cleanly handling the garbage data for you, and being easier to read once you know how it works. It's also easier to expand later on, if you want to also store, say, hours/minutes/seconds.]
Note that the loops are strictly unnecessary; you could also do this:
int m, d, y;
string parser;
// ...
// Extract & parse.
getline(cin, parser, Sep); m = stoi(parser);
getline(cin, parser, Sep); d = stoi(parser);
getline(cin, parser, Sep); y = stoi(parser);
// ...
// Output data.
cout << m << Sep
<< d << Sep
<< y << '\n';
It also replaces std::endl
with newline literal '\n'
, which is usually preferred over std::endl
. [Specifically, std::endl
outputs '\n'
and then immediately flushes the stream (actually outputs the data). If you just use '\n'
, then it'll wait for you to specifically tell it to flush the data, so it can do as much work as possible with a single output operation. There's no actual difference in this case, but it's a good practice to develop... provided you can tell when you actually do want to flush immediately.]
The second option is to use facilities intended specifically for handling date and time; this will do your desired task more cleanly, but may not be as good a learning experience.
#include <iostream> // std::cin, std::cout
#include <iomanip> // std::get_time(), std::put_time()
#include <ctime> // std::tm
using namespace std;
int main() {
constexpr char Format[] = "%D";
// Date/time format string, indicating "Date in form MM/DD/YY."
// Note: Could also use "%m/%d/%y" for same results.
//int m,d,y;
tm date;
cout << "Please enter your birthday in the format of MM/DD/YY ";
//cin >> m >> d >> y;
cin >> get_time(&date, Format);
//cout << "Your birthday is: " << m << d << y << endl;
cout << "Your birthday is: " << std::put_time(&date, Format) << '\n';
return 0;
}
In this case, we use std::tm
, a simple struct
holding date & time information. Helper functions std::get_time()
and std::put_time()
extract and output the stored data, taking a pointer to the tm
to store data in and a formatting string to indicate what data to get.
Note that tm
isn't a black box, just a convenient collection of relevant fields. We can do this manually, but it won't be as clean.
cout << "Your birthday is: "
// Month: Stored as 00..11, so add one.
<< std::setfill('0') << std::setw(2) << date.tm_mon + 1 << '/'
// Day of the month: Stored as 01..31, so no adjustment.
<< std::setfill('0') << std::setw(2) << date.tm_mday << '/'
// Year: Stored as years since 1900, so subtract 100 if it's over 99.
<< std::setfill('0') << std::setw(2) << (date.tm_year < 100 ? date.tm_year : date.tm_year - 100) << '\n';
There isn't really as much room to experiment here, so it's not the best to use while learning. It's convenient once you know how input and output work, though, since it handles extraction, processing, and insertion for you.
Upvotes: 0
Reputation: 73
By entering '/' into d which is expecting int, you are making cin to go into failed state and it ignores any furthur calls to it hence your d and y being auto variables are having garbage value, try to include a char variable seperator in your code to input the field seperating m,d and y.
int main() {
int m, d, y;
char seperator;
cout << "Please enter your birthday in the format of MM/DD/YY ";
cin >> m >> seperator >> d>> seperator >> y;
cout << "Your birthday is: " << m << seperator << d<< seperator << y << endl;
system("pause");
}
Upvotes: 2