How to take input on same line in c++? - c++

i want to input Date in this format 2/11/2015. how can i do this using
C++ ? Thanks The following method isn't working.
cin>>day >>month >>year ;
and also user don't have to press enter .
my Code is
#include <iostream>
using namespace std;
class Date
{
private :
int day,month,year;
char slash;
public :
void inputdate(void)
{
cout<<"Enter Date in Formate (day/month/year)"<<endl;
cin >> day >> slash >> month >> slash >> year;
}
void checkdate(void)
{
if (day<=0 || day>=32)
{
cout<<"Day is Wrong ! "<<endl;
}
if (month==2 && day>=29)
{
cout<<"February can have max 28 days !"<<endl;
}
if (month<=0 || month>=13)
{
cout<<"Month is wrong !"<<endl;
}
if (year<=1799 || year>=3000)
{
cout<<"Year is Wrong !"<<endl;
}
if ((month==4 || month==6 || month==9 || month==11)&&(day>30))
{
cout<<"Day is wrong ! September ,April ,June and November can have maximum 30 days ."<<endl;
}
}
void showdate(void)
{
checkdate();
cout<<"Date is : "<<day<<"/"<<month<<"/"<<year<<endl;
}
};

C++ does not inherently understand text dates; you will need to either use a library which provides this functionality, or create a function yourself to convert between the text format and the internal integer format (which is generally the number of seconds or milliseconds, depending on platform, since the "Epoch" (00:00 1st January 1970)).
To do this you will need to:
Collect the date as a single string or character array
Separate the date into its constituent day/month/year
Calculate this date as a number of seconds since the Epoch
Having said all this, the first option of using a Library is probably best as it will also contain functions to switch between string and internal date format; which library you choose is up to you and will largely depend on the platform you're coding for.

You can use a dummy char variable to read past the / separator:
int day, month, year;
char slash; // dummy to skip past the '/'
cin >> day >> slash >> month >> slash >> year;

Related

Reading a date from a file

I am going to pipe in an input such as 2021/10/7 (Year/Month/Day). I wont be asking the user for input and I need the code to be able to read the input properly. I don't understand how to get input (a date) from Linux and how my program will transverse that input into its proper places inside of my code.
We've gone over <fstream> briefly and ifstream inData; ofstream outData; .open and .close but for my last assignment in the sample solution that was posted freopen was used which I am completely unfamiliar with. I have asked for help from my professor specifically but encourages using outside means like the compute science discord and tutoring which are not that much help.
What I'm looking for is a way to learn how to be able to input the data so that it can be read from the data stream and how I should structure something like this for getting input from Linux instead of the user.
Write a program that reads a date from the standard input stream.
If the date is valid, the program should write the weekday number followed by the English weekday name (e.g., "Monday", "Tuesday", "Wednesday", ..., "Sunday"). Function main returns 0.
If the date read from the standard input stream is invalid, the program should write "Error: invalid date". Function main returns 1.
Sample Interactions
$ echo "2021/03/01" | ./pa04
0 Monday
$ echo $?
0
$ echo " 2022/3/1" | ./pa04
1 Tuesday
$ echo $?
0
$ echo "3/1/2022" | ./pa04
Error: invalid date
$ echo $?
1
$ echo "abracadabra" | ./pa04
Error: invalid date
$ echo $?
1
#include iostream
#include string
#include iomanip
#include cmath
using namespace std;
int main() {
int day, month, year, w;
// When I get here I feel there needs to be a cin.ignore() for the '/' in 2021/10/07.
// But I'm also concerned that if someone puts in 7 instead of 07 like in the sample interactions that it will jack up the results.
cin >> year >> month >> day;
w = (day + (13 * (month + 1) / 5) + (year) + (year / 4) - (year / 100) + (year / 400)) % 7;
switch (w) {
case 1:
cout << "Sunday \n";
break;
case 2:
cout << "Monday \n";
break;
case 3:
cout << "Tuesday \n";
break;
case 4:
cout << "Wednesday \n";
break;
case 5:
cout << "Thursday \n";
break;
case 6:
cout << "Friday \n";
break;
case 7:
cout << "Saturday \n";
break;
}
return 0;
}
You are not handling the / characters at all.
You can use additional >> calls and variables for that:
int day, month, year;
char slash1, slash2;
if ((cin >> year >> slash1 >> month >> slash2 >> day) &&
(slash1 == '/') &&
(slash2 == '/'))
{
// use values as needed...
}
else
{
// invalid format...
}
Or, you can use istream::ignore() to skip the / characters:
int day, month, year;
if (cin >> year &&
cin.ignore(numeric_limits<streamsize>::max(), '/') &&
cin >> month &&
cin.ignore(numeric_limits<streamsize>::max(), '/') &&
cin >> day)
{
// use values as needed...
}
else
{
// invalid format...
}
Or, in C++11 and later, you can use std::get_time() to let the standard library read in and parse the date components for you:
#include <iomanip>
tm date;
if (cin >> get_time(&date, "%Y/%m/%d"))
{
int day = date.tm_mday;
int month = date.tm_mon + 1;
int year = date.tm_year + 1900;
int w = date.tm_wday + 1;
// use values as needed...
}
else
{
// invalid format...
}
Using std::get_time() has the added benefit that std::tm has a tm_wday member for the day of the week, as you can see above, so you don't have to calculate it manually.
You can use C++20's std::chrono for this as well. It lets you:
Parse an input string, in accord to a format specification, into a time object (e.g. days in a system clock).
Get the week day for that time object.
I've found however that the std::chrono's parse method:
Is not very flexible. AFAIK, it doesn't let you use regular expressions (for example, for matching whitespaces at the beginning of the input string, as in one of your input samples,
2022/4/2; this, in particular, would be easily fixed trimming the string before parsing it).
Can lead to some parsing surprises. For example, for another one of your input samples, 5/3/2023, it will interpret the date as the 20th of March of the year 5. That is, it will match the day to the first 2 digits, 20, of what should be the day in your input string, 2023.
So I would go for a mixed solution here:
a manual parsing of the input string into a time object.
then using std::chrono for geting the week day corresponding to that time object.
The code below implements both solutions in two different functions, using_just_chrono and using_regex_and_chrono, just to show the issues I mentioned above if we just use std::chrono. I have used regular expressions for the manual parsing but you could just capture the year, month, and day of each date with a string stream after doing some trimming.
#include <chrono> // parse, sys_days, weekday
#include <iostream> // cout
#include <regex> // regex_match, smatch
#include <sstream> // istringstream
namespace ch = std::chrono;
void using_just_chrono(const std::string& date)
{
ch::year_month_day ymd{};
std::istringstream iss{ date };
if (iss >> ch::parse(std::string{ "%Y/%m/%d" }, ymd) and ymd.ok())
{
std::cout << "\t\tusing just chrono: " << ch::weekday{ ch::sys_days{ ymd } } << "\n";
}
}
void using_regex_and_chrono(const std::string& date)
{
// Probably more portable using [[:space:]] and [[:digit:]] here
std::regex pattern{ R"(^\s*(\d{1,4})/(\d{1,2})/(\d{1,2})\s*$)" };
std::smatch matches{};
if (std::regex_match(date, matches, pattern))
{
ch::year_month_day ymd(
ch::year{ std::stoi(matches[1]) },
ch::month{ std::stoul(matches[2]) },
ch::day{ std::stoul(matches[3]) });
if (ymd.ok())
{
std::cout << "\t\tusing rgx and chr: " << ch::weekday{ ch::sys_days{ ymd } } << "\n";
}
}
}
int main()
{
std::cout << "Parsing dates:\n";
for (const std::string& date : {
"2021/03/01", // OK
" 2022/4/2", // OK: needs trimming white spaces at the front
"5/3/2023", // wrong: day is 2023
"abracadabra", // wrong format
"2020/12/32", // wrong: day is 32
"2019/13/20", // wrong: month is 13
"2021/2/29" }) // wrong: non existing date
{
std::cout << "\t\"" << date << "\":\n";
using_just_chrono(date);
using_regex_and_chrono(date);
}
std::cout << "\n";
}
// Outputs:
//
// Parsing dates:
// "2021/03/01":
// using just chrono: Mon
// using rgx and chr: Mon
// " 2022/4/2":
// using rgx and chr: Sat
// "5/3/2023":
// using just chrono: Sun
// "abracadabra":
// "2020/12/32":
// "2019/13/20":
// "2021/2/29":

How to read in values in C++ without a space? [duplicate]

Yes, this is for an assignment. I do not mind working to get an answer and I do not want the exact answer! :) This is my first C++ class. I've come into this class with prior knowledge of VBA, MySql, CSS, and HTML.
We are required to write a program with several different functions. One of them is required to receive the date input in a "MM/DD/YYYY" format.
While that in of itself is easy enough; as a beginner I would just put
cin >> month >> day >> year;
And insert the "/" afterwards when displaying back to the user.
However, I believe our professor would like the user to input the date by exactly typing "12/5/2013", or any other date.
Per his instructions:
The '/' can be read by cin. So read the '/' character and ignore it. Set day to equal the 3rd input, month to the first input, and year to the fifth input. Discard the 2nd and 4th input.
^ That is where I am thrown off course.
So far we have only experienced cin when the user hits enter after each input. So I don't know if he wants the user to hit enter after 12, then again after '/', then after 5, after '/', and lastly after '2013' (using the prior example of 12/5/2013 for December 5th, 2013).
Does anyone more experienced have any possible insight as to what I should be doing?
We have only been taught how to use "cin" to receive inputs (so we know no other methods for receiving input), and I have no idea how to go about "ignoring a character" when entered as a string such as '12/5/2013' exactly.
I would greatly appreciate any help with this!
edit: I have looked for answers on here but all of the ones that I have come across are beyond the scope of what we have been taught and are therefore not allowed in the assignment.
While I can go about understanding the logic of more advance coding easily enough, I am frustrated at my lack of ability to solve these simpler problems with any amount of ease. Hence my posting on here. I have spent several hours scanning our textbook for possible answers or clues to 'ignoring' characters in an input string but have come up short.
It's actually pretty easy! The thing is: you can input more than just one thing. That means, if you write int d; std::cin >> d;, it's perfectly fine to input 30/06/2014. The value of d becomes 30 and the rest of the input is not yet read. If you write the next std::cin statement, the content that is available is /06/2014.
You then need to consume the /, read the month, consume again and finally read the year.
#include <iostream>
int main()
{
int d;
int m;
int y;
std::cin >> d; // read the day
if ( std::cin.get() != '/' ) // make sure there is a slash between DD and MM
{
std::cout << "expected /\n";
return 1;
}
std::cin >> m; // read the month
if ( std::cin.get() != '/' ) // make sure there is a slash between MM and YYYY
{
std::cout << "expected /\n";
return 1;
}
std::cin >> y; // read the year
std::cout << "input date: " << d << "/" << m << "/" << y << "\n";
}
If you have the guarantee that the input format will be correct, it's OK to just write
std::cin >> d;
std::cin.get();
std::cin >> m;
std::cin.get();
std::cin >> y;
Alternatively, If you're not comfortable with using std::cin.get(), it's just as good as reading a character:
char slash_dummy;
int d;
int m;
int y;
std::cin >> d >> slash_dummy >> m >> slash_dummy >> y;
Here are some demos:
code with error checks
ignoring errors
without std::cin.get()
follow this pseudo code:
declare a char pointer to accept input
declare int to use as day, month and year
initialize day, month and year to 0
declare a int count to know what number you are up to
read `cin` operation into your input
increment through the input, stop if the current input position is NULL
read out character
if character != "/"
if count == 0
if month == 0
month = (int)character
else
month = month * 10 + (int)character
endif
else
if count == 1
if day == 0
day = (int)character
else
day = day * 10 + (int)character
endif
else
if year < 1000
year = year * 10 + (int)character
endif
endif
endif
else count += 1 endif
and voilĂ  you have your day, month and year from input.
Why not use stringstreams?
string input;
int year, month, day;
cin >> input; // input can be 2005:03:09 or 2005/04/02 or whatever
stringstream ss(input);
char ch;
ss >> year >> ch >> month >> ch >> day;

EOF loop repeats lines 3 times before finally ending

I have an assignment where I'm given a file containing dates in numbered format and I have to have a program read the file and spit out days of the week for each date give. Each line of the file is a separate date. My go-to method was an eof loop. However, my file has 10 dates, and my output has 30. Here is my main for context.
int main()
{
ifstream inFile;
inFile.open("/Users/holdentatlow/Desktop/date 2");
const char *Names[] = {"Sunday","Monday", "Tuesday","Wednesday", "Thursday", "Friday", "Saturday"};
int day = 0;
int date;
inFile >> date;
cout << "Day : " << Names[day] << endl;
while (!inFile.eof()){
inFile >> date;
day = getWeekDay(date, date, date);
cout<< "Day : "<< Names[day] <<endl;
}
inFile.close();
return 0;
}
also, I get the impression that the dates it does report aren't entirely accurate. I don't have the resolve to check each one individually but the results seem erratic enough to not be simply repeated.
here's the file I'm taking dates from
0 10 1900
2 16 1900
1 2 1944
0 1 2004
1 29 2004
11 24 2002
6 2 2050
2 23 2004
0 6 1812
1 3 1800
You seem to be trying to use date to mean three things at once.
int date;
inFile >> date;
Here you read one number. One. Not three; one.
while (!inFile.eof()){
Here you commit a cardinal sin; that is not how to loop over input.
inFile >> date;
day = getWeekDay(date, date, date);
Here you read another one number, and pass it to getWeekDay three times.
Your loop continues until there are no more numbers to read (sort of: see note above about that eof usage), which in your case will take three times as long as you expected (i.e. 30 not 10) because you read a third as many numbers as you thought (again, see above).
You'll want an >> operation for each number you want to read.
Here's an improved version of your program:
#include <fstream>
#include <istream>
#include <iostream>
// Assumed defined elsewhere
int getWeekDay(int date, int month, int year);
int main()
{
std::ifstream inFile("/Users/holdentatlow/Desktop/date 2");
static const char* Names[] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
int date, month, year;
while (inFile >> date >> month >> year) {
const int day = getWeekDay(date, month, year);
std::cout << "Day : " << Names[day] << std::endl;
}
}

Prompt for and receive a date "MM/DD/YYYY" using CIN, ignoring the "/" characters? (in C++)

Yes, this is for an assignment. I do not mind working to get an answer and I do not want the exact answer! :) This is my first C++ class. I've come into this class with prior knowledge of VBA, MySql, CSS, and HTML.
We are required to write a program with several different functions. One of them is required to receive the date input in a "MM/DD/YYYY" format.
While that in of itself is easy enough; as a beginner I would just put
cin >> month >> day >> year;
And insert the "/" afterwards when displaying back to the user.
However, I believe our professor would like the user to input the date by exactly typing "12/5/2013", or any other date.
Per his instructions:
The '/' can be read by cin. So read the '/' character and ignore it. Set day to equal the 3rd input, month to the first input, and year to the fifth input. Discard the 2nd and 4th input.
^ That is where I am thrown off course.
So far we have only experienced cin when the user hits enter after each input. So I don't know if he wants the user to hit enter after 12, then again after '/', then after 5, after '/', and lastly after '2013' (using the prior example of 12/5/2013 for December 5th, 2013).
Does anyone more experienced have any possible insight as to what I should be doing?
We have only been taught how to use "cin" to receive inputs (so we know no other methods for receiving input), and I have no idea how to go about "ignoring a character" when entered as a string such as '12/5/2013' exactly.
I would greatly appreciate any help with this!
edit: I have looked for answers on here but all of the ones that I have come across are beyond the scope of what we have been taught and are therefore not allowed in the assignment.
While I can go about understanding the logic of more advance coding easily enough, I am frustrated at my lack of ability to solve these simpler problems with any amount of ease. Hence my posting on here. I have spent several hours scanning our textbook for possible answers or clues to 'ignoring' characters in an input string but have come up short.
It's actually pretty easy! The thing is: you can input more than just one thing. That means, if you write int d; std::cin >> d;, it's perfectly fine to input 30/06/2014. The value of d becomes 30 and the rest of the input is not yet read. If you write the next std::cin statement, the content that is available is /06/2014.
You then need to consume the /, read the month, consume again and finally read the year.
#include <iostream>
int main()
{
int d;
int m;
int y;
std::cin >> d; // read the day
if ( std::cin.get() != '/' ) // make sure there is a slash between DD and MM
{
std::cout << "expected /\n";
return 1;
}
std::cin >> m; // read the month
if ( std::cin.get() != '/' ) // make sure there is a slash between MM and YYYY
{
std::cout << "expected /\n";
return 1;
}
std::cin >> y; // read the year
std::cout << "input date: " << d << "/" << m << "/" << y << "\n";
}
If you have the guarantee that the input format will be correct, it's OK to just write
std::cin >> d;
std::cin.get();
std::cin >> m;
std::cin.get();
std::cin >> y;
Alternatively, If you're not comfortable with using std::cin.get(), it's just as good as reading a character:
char slash_dummy;
int d;
int m;
int y;
std::cin >> d >> slash_dummy >> m >> slash_dummy >> y;
Here are some demos:
code with error checks
ignoring errors
without std::cin.get()
follow this pseudo code:
declare a char pointer to accept input
declare int to use as day, month and year
initialize day, month and year to 0
declare a int count to know what number you are up to
read `cin` operation into your input
increment through the input, stop if the current input position is NULL
read out character
if character != "/"
if count == 0
if month == 0
month = (int)character
else
month = month * 10 + (int)character
endif
else
if count == 1
if day == 0
day = (int)character
else
day = day * 10 + (int)character
endif
else
if year < 1000
year = year * 10 + (int)character
endif
endif
endif
else count += 1 endif
and voilĂ  you have your day, month and year from input.
Why not use stringstreams?
string input;
int year, month, day;
cin >> input; // input can be 2005:03:09 or 2005/04/02 or whatever
stringstream ss(input);
char ch;
ss >> year >> ch >> month >> ch >> day;

time format hh:mm:ss input

I am in a case when i am given two time formats hh:mm:ss to input.
I know that int variables exctract from cin until a non-integer is reached. This means that i can extract the hours easily, but then the character ":" would still be in the stream, which would cause a problem for the extraction of minutes.
I know i can use cin.ignore() but since i have to input two time formats, the code just for the input would result very long and not seem too good.
Just to give you an idea:
int h,m,s, h2,m2,s2;
cin>>h;
cin.ignore();
cin>>m;
cin.ignore();
cin>>s;
cin>>h2;
cin.ignore();
cin>>m2;
cin.ignore();
cin>>s2;
I know that cin automatically ignores whitespaces. Is there a way to make it automatically ignore a specific character (in this case, the character ":")?
An easy approach is create a colon() manipulator:
std::istream& colon(std::istream& in) {
if ((in >> std::ws).peek() == ':') {
in.ignore();
}
else {
in.setstate(std::ios_base::failbit));
}
return in;
}
You can then just extract the ':' characters:
in >> h >> colon >> m >> colon >> s;
Obviously, I'd create an input operator for times so I could then read the two objects using
in >> time1 >> time2;
For my case also I need time input in HH:MM:SS format. I solved that ':' input by using it as a delimiter for getline()function. I have attached that portion of code here.
const char delim = ':';
string hr_s, min_s, sec_s;
int hr, min, sec;
cout << "Enter HH:MM:SS : " << endl;
std::getline(cin, hr_s, delim);
std::getline(cin, min_s, delim);
std::getline(cin, sec_s);
hr = stoi(hr_s);
min = stoi(min_s);
sec = stoi(sec_s);
if ((hr_s.length() == 2) && (min_s.length() == 2) && (sec_s.length() == 2)&& (isValidTime(hr, min, sec)))
{
cout << "Good Time Format" << endl;
}
else
{
cout << "Bad Time format input"<< endl;
}
The method to check the validity of the numbers input:
bool isValidTime(int hr, int min, int sec)
{return (((hr >= 0) && (hr < 24)) &&
((min >= 0) && (min < 60)) &&
((sec >= 0) && (sec< 60)));}
Note: this code has no effect unless the user input some other character instead of ':'. For other case it should be fine. I am not sure if I answered your question or not but I hope this is helpful.