Printing a calendar for a given year and month - c

I'm trying to build a program that will print out the month and year that the user inputs. What I have so far ends up with the year having 5 digits and inputting "2020 2" results in 28 days for the month of February.
The code I have so far in this assignment:
#include <stdio.h>
#include<stdlib.h>
int is_leapyear(int y)
{
if ((y % 100 == 0 && y % 100 != 0) || y % 400 == 0)
return 1;
else
return 0;
}
int main()
{
int i, j, year, month;
printf("Please enter the year and month:");
scanf("%d", &year);
scanf("%d", &month);
int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int la[13] = { 0,31,29,31,30,31,30,31,31,30,31,30,31 };
int c = 1;
int flag = 0;
if (is_leapyear(year))
flag = 1;
for (i = 0; i<month; i++)
{
if (flag == 1)
c += la[i];
else
c += a[i];
}
int s = (year - 1) + ((year - 1) / 4) + ((year - 1) / 400) - ((year - 1) / 100) + c;
int week = s % 7;
printf("Calendar " );
printf("%-d", year);
if (month < 10)
printf("0");
printf(" %d\n", month);
printf("----------------------\n");
printf("Su Mo Tu We Th Fr Sa \n");
printf("----------------------\n");
if (flag == 1) {
for (j = 0; j < week; j++)
{
printf(" ");
}
for (i = 1; i <= la[month]; i++)
{
if ((week + i - 1) % 7 == 0)
{
printf("\n");
}
if (i < 10)
{
printf(" ");
}
printf("%d", i);
printf(" ");
}
}
else {
for (j = 0; j < week; j++)
{
printf(" ");
}
for (i = 1; i <= a[month]; i++)
{
if ((week + i - 1) % 7 == 0)
{
printf("\n");
}
if (i < 10)
{
printf(" ");
}
printf("%d", i);
printf(" ");
}
}
printf("\n");
printf("---------------------\n");
}
The output:
Any help would be greatly appreciated.
Edit: It seems like I was too careless in reviewing my code, minor mistakes observed and problem solved!

The century check on your isleapyear()
if ((y % 100 == 0 && y % 100 != 0) || y % 400 == 0)
is flawed. It checked if the year is divisible by 100 and not divisible by 100, which is a logical impossibility. I think you actually mean
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
So check if the year is divisible by 4 and not divisible by 100.
As for the 20200, it's because your leading zero for the month is printed before the space is printed. Just change it to
printf("%-d", year);
printf(" "); //put space right away
if (month < 10)
printf("0");
printf("%d\n", month); //no need to print space here
or even better as pointed out by #JonathanLeffler in the comment
printf(" %.2d\n", month);
It deals with space, the leading zero, and the new line in just one call, or just
printf("Calendar %.4d %.2d\n", year, month);
to handle those three parts at once

OP's is_leapyear(int y) fails with various multiples of 4.
Instead:
// Alternative for Gregorian calendar
int is_leapyear(int y) {
if (y % 4 == 0) {
if (y % 100 == 0) { // A century year?
return (y % 400 == 0);
}
return 1;
}
return 0;
}
Deeper: Leap year.

Related

for loop repeats until value is less than three

I dont know why my for loop is not working. I have been trying for so long. It just runs for the do / while and gives return. Everything in the do / while loop. I have declared a macro outside the main function and I am using it as loop condition. I can't add more details, all I have is code.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MIN_YEAR 2012
#define MAX_YEAR 2022
#define LOG_DAYS 3
int main(void)
{
const int JAN = 1;
const int DEC = 12;
int year = 0;
int month = 0;
char day1 = 01;
char day2 = 02;
char day3 = 03;
float ratingMorning = 0;
float ratingEvening = 0;
printf("General Well-being Log\n"
"======================\n");
do
{
printf("Set the year and month for the well-being log (YYYY MM): ");
scanf(" %d %d", &year, &month);
if ((MIN_YEAR > year || year > MAX_YEAR))
{
printf(" ERROR: The year must be between 2012 and 2022 inclusive\n");
}
if ((JAN > month || month > DEC))
{
printf(" ERROR: Jan.(1) - Dec.(12)\n");
}
if ((JAN <= month && month <= DEC) && (MIN_YEAR <= year && year <= MAX_YEAR))
{
printf("\n*** Log date set! ***\n\n");
break;
}
} while ((MIN_YEAR <= year || year <= MAX_YEAR) && (JAN <= month || month <= DEC));
for (int i = 0; i < LOG_DAYS; i++)
{
printf(" %d", year);
printf("-");
printf(" %d", month);
printf("-");
printf(" %d",day1);
printf(" Morning rating (0.0-5.0): ");
scanf(" %d", &ratingMorning);
if (ratingMorning < 0 || ratingMorning > 5)
{
printf(" ERROR: Rating must be between 0.0 and 5.0 inclusive!");
}
printf(" Evening rating (0.0-5.0): ");
scanf(" %d", &ratingEvening);
if (ratingEvening < 0 || ratingEvening > 5)
{
printf(" ERROR: Rating must be between 0.0 and 5.0 inclusive!");
}
}
return 0;
}
The test in the while part of the do / while loop is incorrect. It is much simpler to use a for(;;) loop and break when the input is correct, avoiding redundant and sometime inconsistent tests.
The scanf() conversion specifier for float is %f, not %d.
Here is a modified version:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MIN_YEAR 2012
#define MAX_YEAR 2022
#define LOG_DAYS 3
int main(void) {
const int JAN = 1;
const int DEC = 12;
int year = 0;
int month = 0;
char day1 = 1;
char day2 = 2;
char day3 = 3;
float ratingMorning = 0;
float ratingEvening = 0;
printf("General Well-being Log\n"
"======================\n");
for (;;) {
printf("Set the year and month for the well-being log (YYYY MM): ");
if (scanf(" %d %d", &year, &month) != 2) {
printf("invalid input\n");
return 1;
}
if (year < MIN_YEAR || year > MAX_YEAR) {
printf(" ERROR: The year must be between 2012 and 2022 inclusive\n");
} else
if (month < JAN || month > DEC)) {
printf(" ERROR: Jan.(1) - Dec.(12)\n");
} else {
printf("\n*** Log date set! ***\n\n");
break;
}
}
for (int i = 0; i < LOG_DAYS; i++) {
printf(" %d- %d- %d", year, month, day1);
printf(" Morning rating (0.0-5.0): ");
if (scanf("%f", &ratingMorning) != 1) {
printf("invalid input\n");
return 1;
}
if (ratingMorning < 0 || ratingMorning > 5) {
printf(" ERROR: Rating must be between 0.0 and 5.0 inclusive!");
continue;
}
printf(" Evening rating (0.0-5.0): ");
if (scanf("%f", &ratingEvening) != 1) {
printf("invalid input\n");
return 1;
}
if (ratingEvening < 0 || ratingEvening > 5) {
printf(" ERROR: Rating must be between 0.0 and 5.0 inclusive!");
continue;
}
// ... handle the ratings and report success
}
return 0;
}
If the problem is that:
if (ratingMorning < 0 || ratingMorning > 5) is not working
i.e. the error line ERROR: Rating must be between 0.0 and 5.0 inclusive!" is never printed, then when you change the %d to %f in the scanf(" %d", &ratingMorning); lines, the errors are printed because now ratingMorning and ratingEvening contain valid values, whereas when they were input as integers, the values were invalid.

Check if one person is 100 days older than the other in C

My task is to check if one student in the group is 100 days older than the other one. The maximum number of students is 1000. When calculating, leap years and other characteristics such as the number of days in month should be taken in account. I don't know why my code doesn't work.If I enter the wrong date(32/33/2000), I have an infinite loop with 'Wrong input'.If the date is correct,the code doesn't print anything even if the difference is 100 days. I am beginner, and I hope you could help.
#include <stdio.h>
int main() {
int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int daysleap[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int s, month, year, day, i, j = 0, totaldays, a[1000];
do {
printf("Number of students: ");
scanf("%d", & s);
if (s < 1 || s > 100)
printf("Incorrect input");
} while (s < 1 || s > 1000);
for (i = 0; i < s; i++) {
scanf("%d,%d,%d", & day, & month, & year);
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
if (day < 1 || day > daysleap[month]) {
printf("Incorrect input");
i = i - 1;
continue;
} else if (month < 1 || month > 12) {
printf("Incorrect input");
i = i - 1;
continue;
} else {
for (i = 1; i < year; i++) {
totaldays = 0;
totaldays += 366;
}
for (i = 1; i < month; i++)
totaldays += daysleap[i];
totaldays += day;
a[j] = totaldays;
j++;
}
} else {
if (day < 1 || day > days[month]) {
printf("Incorrect input");
i = i - 1;
continue;
} else if (month < 1 || month > 12) {
printf("Incorrect input");
i = i - 1;
continue;
} else {
for (i = 1; i < year; i++) {
totaldays = 0;
totaldays += 365;
}
for (i = 1; i < month; i++)
totaldays += days[i];
totaldays += day;
a[j] = totaldays;
j++;
}
}
}
for (i = 0; i < s; i++) {
for (j = i; j < s; j++) {
while (i < s && j < s) {
if (i != j && (a[j] - a[i] == 100))
printf("Student %d is 100 days older from Student %d", j + 1, i + 1);
if (i != j && (a[j] - a[i] == -100))
printf("Student %d is 100 days older from Student %d", i + 1, j + 1);
}
}
}
}
This
for (i = 1; i < year; i++) {
totaldays = 0;
totaldays += 366;
}
Is equivalent to this
totaldays = 366;
You probably wanted to do this
totaldays = 0;
for (i = 1; i < year; i++) {
totaldays += 366;
}
However the logic is incorrect. Let's say that the year is 2000. It is a leap year, but 1999 is not. You should add 366 for leap years and 365 fon non-leap years.
I don't know if fixing it is enough for the program to work. Anyway I was eager to code and I made a program that relies on the difference between the dates as they are rather than on the difference between the dates as distance from the 1st January of the year 0. Check this approach.
#include <stdio.h>
#define N 50
int main() {
int m[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
int p[N][3]; // person: day, month, year
int n; // number of people
// if the date is in a leap year, then one of the two subscripts gets a value of 1
// if the date is before the 29th February leap[][0] = 1, otherwise leap[][1] = 1
int leap[N][2] = {};
int tot[N]; // sum of days in the birth year
int dif; // difference in days between two dates
puts("How many people?");
do {
scanf("%d", &n);
}
while( (n < 2 || n > N) && puts("Try again...") );
puts("Enter their birth days please.");
for(int i = 0; i < n; i++) {
if( scanf("%d%*c%d%*c%d", &p[i][0], &p[i][1], &p[i][2]) == 3 && p[i][0] > 0 && p[i][1] > 0 && p[i][1] < 13 ) {
if( (!(p[i][2]%4) && p[i][2]%100) || !(p[i][2]%400) ) {
if( p[i][1] == 0 || (p[i][1] == 2 && p[i][0] < 29) ) leap[i][0] = 1;
else leap[i][1] = 1;
}
if( ( leap[i][1] && ((p[i][1] == 1 && p[i][0] > 29) || (p[i][1] != 1 && p[i][0] > m[p[i][0]-1])) ) || (!leap[i][1] && p[i][0] > m[p[i][0]-1]) ) {
puts("Wrong input, try again");
--i;
}
}
else {
puts("Wrong input, try again");
--i;
}
}
for(int i = 0; i < n; i++) {
tot[i] = p[i][0];
for(int j = 0; j < p[i][1]-1; j++ ) {
tot[i] += m[j];
}
}
for(int i = 0; i < n-1; i++) {
if( p[i][2] - p[i+1][2] < - 1 ) dif = 999;
else if( p[i][2] - p[i+1][2] > 1 ) dif = -999;
else {
dif = tot[i+1] - tot[i];
if( leap[i][0] && leap[i+1][1] ) ++dif;
else if( leap[i+1][0] && leap[i][1] ) --dif;
if( p[i][2] - p[i+1][2] == - 1 ) dif += 365;
else if( p[i][2] - p[i+1][2] == 1 ) dif -= 365;
}
if( dif > 100) printf("Student #%d is 100 days older than student #%d", i+1, i+2);
else if( dif < 100) printf("Student #%d is 100 days older than student #%d", i+2, i+1);
}
return 0;
}
Yes it would be more readable using day[], month[] and year[] istead of p[][0], p[][1] and p[][2].
It would be even better to use an array of structures, like Date dates[N] with the type Date defined as follows
typedef struct {
int day, month, year;
int leapPre = 0, leapPost = 0;
int tot;
} Date;
With leapPre and leapPost being what leap[][0] and leap[][1] were.

Wrong calculations

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
int letters = 0;
int words = 0;
int sentences = 0;
int main(void)
{
string text = get_string("Text: ");
printf("\n");
for(int j = 0; j < strlen(text); j++)
{
if((text[j] >= 'a' && text[j] <= 'z') || (text[j] >= 'A' && text[j] <= 'Z'))
{
letters++;
}
if(text[j] == ' ')
{
words++;
}
if(text[j] == '.' || text[j] == '?' || text[j] == '!')
{
sentences++;
}
}
printf("Letters: %i\n", letters);
printf("Words: %i\n", words + 1);
printf("Sentences: %i\n", sentences);
float L = ((float)letters / (float)words) * 100;
float S = ((float)sentences / (float)words) * 100;
float result = round(0.0588 * L - 0.296 * S - 15.8);
printf("%f\n", L);
printf("%f\n", S);
printf("%f\n", result);
if(result < 1)
{
printf("Before Grade 1");
}
if(result == 1)
{
printf("Grade 1");
}
if(result == 2)
{
printf("Grade 2");
}
if(result == 3)
{
printf("Grade 3");
}
if(result == 4)
{
printf("Grade 4");
}
if(result == 5)
{
printf("Grade 5");
}
if(result == 6)
{
printf("Grade 6");
}
if(result == 7)
{
printf("Grade 7");
}
if(result == 8)
{
printf("Grade 8");
}
if(result == 9)
{
printf("Grade 9");
}
if(result == 10)
{
printf("Grade 10");
}
if(result == 11)
{
printf("Grade 11");
}
if(result == 12)
{
printf("Grade 12");
}
if(result == 13)
{
printf("Grade 13");
}
if(result == 14)
{
printf("Grade 14");
}
if(result == 15)
{
printf("Grade 15");
}
if(result >= 16)
{
printf("Grade 16+");
}
printf("\n");
}
Text:
Congratulations! Today is your day. You're off to Great Places! You're off and away!
Result:
Letters: 65
Words: 14
Sentences: 4
500.000000
30.769232
4.000000
Grade 4
I need to calculate the '0.0588 * L - 0.296 * S - 15.8' formula in my code, but for some reason, it is giving me the wrong answer for some text and right for some text. in this particular example, it should give me 'Grade 3' but it is giving me 'Grade 4' instead and if I put a text for grade 10 it will give me 'Grade 10'. And the calculations for 'L' and 'S' are wrong, in this example, they should be L = 464.29 and S = 28.57. I really don't know where I am going wrong, can someone please help me?
The problem is that you count words by counting spaces, so you don't count the last word. You could solve the problem by initialising words to 1.
Also I saw you noticed that problem since you wrote printf("Words: %i\n", words + 1); so why in your calculations didn't you added 1? You print 14 as word count, but then you use 13 to calculate the average length of the words.
Anyway you should absolutely change the final prints with that
if(result < 16) {
printf("Grade %d\n", result);
}
else {
puts("Grade 16+");
}
Or even just
result < 16 ? printf("Grade %d\n", result) : puts("Grade 16+");
It appears you have counted words inadequately. You counted the number of spaces between words, which gives a number that is one fewer than the number of words. This is adjusted for when printing the number, in printf("Words: %i\n", words + 1);, and when calculating S, in printf("Words: %i\n", words + 1);, but not when calculating L, in float L = ((float)letters / (float)words) * 100;.
Changing that last line to float L = ((float)letters / (float)(words+1)) * 100; results in the answer you expect, “Grade 3”.
However, a better solution is likely to initialize words with int words = 1; instead of int words = 0; and change the printf and the calculation of S to use words instead of words + 1.
(Further, a more sophisticated program would consider what happens if spaces appear before any words, after the last word, or multiple times between words.)

Why does this code result in an infinite loop? Also, how can I completely restart my number baseball game?(How can I re-generate random numbers?)

I'm new to C, and is trying to make a number baseball game. The functions I wish to include are, when I press x, the game ends, and when I press m, a series of instructions are printed. Finally, I've added a re-game function, so that when I press the number 1 after the game ends, one could play it again. The number baseball game itself works fine, but whenever I press x or m, the program goes into an infinite loop. I can't figure out what's wrong. Also, when I use the re-game function, my program works, but it doesn't generate a new set of numbers, and just uses the set it used before. Could you please help??
#include <stdio.h>
#include <time.h>
#include <windows.h>
int main (void) {
int computerBall[4];
int X = 0;
int i, j = 1;
int userBall[4];
int x, m;
int o, q;
int flag = 1;
q = 1;
x = 2;
m = 3;
srand (time (NULL));
computerBall[0] = rand () % 31;
while (computerBall[0] == 0)
computerBall[0] = rand () % 31;
for (i = 1; i < 4; i++) {
computerBall[i] = rand () % 31;
while (q == 1) {
flag = 0;
for (j = 0; j < i; j++) {
if (computerBall[j] == computerBall[i]) {
computerBall[i] = rand () % 31;
flag = 1;
break;
}
}
if (flag == 0)
break;
}
} // Code to Generate Random Numbers
while (q == 1) {
printf ("Choose 4 numbers between 1 and 30\n");
printf ("Press x to exit, and press m for help\n");
while (q == 1) {
printf ("Input numbers:");
scanf_s ("%d %d %d %d\n", &userBall[0], &userBall[1],
&userBall[2], &userBall[3]);
//To prevent numbers outside of range
if (userBall[0] < 1 || userBall[0] > 30 || userBall[1] < 1 ||
userBall[1] > 30 || userBall[2] < 1 || userBall[2] > 30 ||
userBall[3] < 1 || userBall[3] > 30) {
printf ("You cannot input numbers outside the range.\n");
continue;
} //To prevent repeating numbers
else if (userBall[0] == userBall[1] || userBall[0] == userBall[2] ||
userBall[0] == userBall[3] || userBall[1] == userBall[2] ||
userBall[1] == userBall[3] || userBall[2] == userBall[3]) {
printf ("You cannot input same numbers at once.\n");
continue;
}
else if (userBall[0] == m) { //Doesn't work
printf ("Help\n\n");
continue;
}
else if (userBall[0] == x) { //Doesn't work
printf ("\n Game Over\n");
printf ("Answer : ");
printf ("%d ", X);
printf ("Press 1 to restart");
scanf_s ("%d", &o);
if (o == 1)
continue;
else
q = 0;
}
break;
}
}
return 0;
}
Try using return 1 in the particular line of your code when you want to exit to close the program if that's your problem

Solving for the date and days passed via functions

I'm getting better in my C coding but I'm still unsure how to solve several problems in my code. The professor wants us to write a code where we input the day (mm/dd/yyyy) and spits out the number of days that have passed. For choice 2, input number of days in a certain year and spits out the corresponding date. The problem is (since our prof likes to mess with us) solving for errors like 4/31/2001 where April doesn't have 31 days and inputing 366 days in a non-leap year.
int leap(int x)
{
if ((x % 4 == 0 && x % 100 != 0)|| x % 400 == 0)
return 1;
else
return 0;
}
int monthFun(int d, int y)
{
int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
int i;
if (leap(y))
days[1] = 29;
for (i = 0; ; i++)
if (d > days[i])
d = d - days[i];
else
return i + 1;
return i + 1;
}
int dateFun(int d, int y)
{
int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
int i, m;
if (leap(y))
days[1] = 29;
for (i = 0; i < m - 1; i++)
if (d > days[i]) {
d = d - days[i];
}
else {
d = d;
m = i;
}
return d;
}
int daysPast(int m, int d, int y)
{
int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
int i, past = 0;
if (leap(y))
days[1] = 29;
for (i = 0; i < m - 1; i++)
past = past + days[i];
return past + d;
}
int main()
{
int mm, dd, yy, choice;
char more;
do {
printf ("\n\t\tThis program will find days passed or date in the year");
printf ("\n\t\t\t\t1) Input date (mm/dd/yyyy) to find the days passed");
printf ("\n\t\t\t\t2) Input passed days to find date in the year");
printf ("\n\n\t\t\t\tYour choice (1/2): ");
scanf ("%d", &choice);
if (choice == 1) {
printf ("\n\t\tPlease input date (mm/dd/yyyy): ");
scanf ("%d/%d/%d", &mm, &dd, &yy);
printf ("\n\t\tThere are %d days passed in the year %d", daysPast(mm, dd, yy), yy);
}
else
if (choice == 2){
printf ("\n\t\tInput days: ");
scanf ("%d", &dd);
printf ("\n\t\tInput year: ");
scanf ("%d", &yy);
printf ("\n\t\tThe date is %d/%d/%d", monthFun(dd, yy), dateFun(dd,yy), yy);
}
else
printf ("\n\t\tPlease choose 1 or 2");
printf ("\n\n\t\tDo more (Y/N)? ");
scanf ("%s", &more);
} while (more == 'y' || more == 'Y');
}
The code for my dateFun() is a little sloppy (or at least seems like it to me). I figured that if one of the aforementioned problems is entered, the program says something like "invalid input" and takes you back to "do more". Any tips are appreciated and thanks in advance!
Your dateFun tests an uninitialized m.
dateFun() and monthFun() are looking very similar, I've added a sample combined version.
int leap(int x)
{
return ((x % 4 == 0 && x % 100 != 0)|| x % 400 == 0);
}
int monthFun(int d, int y)
{
int i, days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
days[1] += leap(y);
for (i=0 ; d>days[i] ; i++)
d -= days[i];
return i+1;
}
int dateFun(int d, int y)
{
int i, days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
days[1] += leap(y);
for (i=0 ; d>days[i] ; i++)
d -= days[i];
return d;
}
int datemonthFun(int d, int y)
{
int i, days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
days[1] += leap(y);
for (i=0 ; d>days[i] ; i++)
d -= days[i];
return (i+1)*100+d;
}

Resources