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;
}
}
Related
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":
I am new to C++, trying to import dates into a program, adding up digits of day, month, year resp and writing back to txt.
input data
sl.no name day month year
1 Rob 15 05 2019
2 Tim 12 06 2002
Desired output data in txt
sl.no name day month year
1 Rob 6 5 3
2 Tim 3 6 4
I have been able to import data from a txt file and also add the digits in day but it does not repeat forward. what am i doing wrong ?
sample code
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream theFile("data.txt");
int id,day,month,year,daysum=0,monthsum=0, yearsum=0;
string name;
while (theFile >> id >> name >> day >> month >> year)
{
cout << id << ", "<< name <<", "<< day<<", "<<month <<", "<< year<<","<< endl;
}
while (day > 0)
{
daysum = daysum + (day % 10);
day = day / 10;
cout << daysum << endl;
}
I am no expert . but have been in your spot a few months ago.. break down the problem into smaller steps..
My approach..
Pseudo Code:
Ditch the header
Create a function for adding the digits
Read data from file
Use a loop to run through each element of the every column and use the function created
Store results in a variable
Output variable to a new text file
comment if there is a specific area where you are stuck..
Try this to reduce it to single digits.. knit to other parts of your code..
#include <iostream>
using namespace std;
int main()
{
long long num;
cout << "Enter a number: ";
cin >> num;
int sum = 0;
while (1)
{
sum += (num % 10);
num /= 10;
if (0 == num)
{
if (sum > 9)
{
num = sum;
sum = 0;
}
else
{
cout << "Answer: ";
cout << sum << endl;
return 0;
}
}
};
return 0;
}
you are reading the file and data wrong,
you need to discard the header (sl.no name day month year)
and then accumulate the daysum while reading the file progressively one row after the other until the end...
So the program should ask a day as an input then it should represent it as an integer value (eg.
0 = Sunday or 1 = Monday and etc) then the user enters n number of days (like say 10 days) and the program has to find what day(from Sunday to Saturday) is after 10 days. (I know I can solve it using loop pretty easily but I am preferring not to use it, thanks.)
#include <iostream>
#include <string>
int main() {
std::string today;
std::cout <<"What day is today: " << std::endl;
std::getline (std::cin, today);
int d_ay;
std::cout << "How many days to add ";
std::cin >> d_ay;
if (today == "Monday" or 1){
today = 1 or "Monday";
}
if (today == "Tuesday"){
today = 2;
}
if (today == "Wednesday"){
today = 3;
}
if (today == "Thursday"){
today = 4;
}
if (today == "Friday"){
today = 5;
}
if (today == "saturday"){
today = 6;
}
if (today == "Sunday"){
today = 0;
}
int meet;
if(d_ay > 6){
if (d_ay > 20){
meet = (today + d_ay)/6;
}
}
return 0;
}
This is how far I have got.
Since the cycle of "Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday" repeats every 7 days, you only need 7 cases for d_ay.
However, this process can be made even more elegant by using the concept of modulo. Mods are represented by the % symbol in C++, and they are defined such that:
a % b = the remainder when a is divided by b.
For example, 4 % 3 = 1 and 4 % 2 = 0.
Now, we can write a revised program:
#include <iostream>
#include <string>
using namespace std;
int main(){
vector <string> days = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
// Input
string today;
cout << "Enter today: ";
cin >> today;
int increment;
cout << "Enter the increment: ";
cin >> increment;
cout << days[(i + increment)%7] << endl;
return 0;
}
If I were you I would just make an array of strings for each day of the week and create a placement unit variable like an int to keep track of where u are. So for example monday would be unit 1 because the week starts on sunday. Just add how ever many days to the index and if the new day is over 7 than just find the remainder after you divide it by seven. Then just print out the day of the week with the index number showing which day of the week it is in the array.
I am trying to get numbers into a string in a loop but convert them immediately and convert it to a double so the 3 numbers can be added and used to get an average. This is my code:
string name;
double num = 0, many = 0, total = 0, value = 0;
inputFile.open("Rainfall.txt");
for (int count = 1; count <= 6; count++)
{
inputFile >> name;
if (count == 1 || count == 3 || count == 5)
{
continue;
}
num = stod(name);
num += total;
}
cout << total << endl;
While this gives me a simple one line output of 0 i now need to convert the string to a double. The input file looks like:
january 1.2
feruary 2.3
march 2.4
August 2.3 September 2.4
Here is a slightly better way assuming your input file structure stays intact (does not sanitize inputs) and std::stod will fail badly on input that cannot be converted to double. You can simply read your given month and monthly rainfall total into their appropriate variable type at the same time. If you put the whole thing in a while loop, it will keep reading your input until it either reaches the end of the file or the stream has an error.
#include <iostream>
#include <fstream>
int main()
{
double total(0.0);
std::ifstream inputFile("Rainfall.txt");
if (inputFile.is_open())
{
std::string month;
double rain(0.0);
while(inputFile >> month >> rain)
{
total += rain;
}
inputFile.close(); ///< technically not necessary
}
std::cout << "total rainfall " << total << std::endl;
return 0;
}
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;