C, printing a month chosen by user - c

I'm doing a school project where I need to ask for a year and a month to be printed like a calendar. The problem is that when I debug it shows the whole year and not just the chosen month.
What changes do I have to do? Hope you can help me!
This is my code:
int SetFirstDay(int year)
{
int d;
int d1, d2, d3;
d1 = (year - 1.) / 4.0;
d2 = (year - 1.) / 100.;
d3 = (year - 1.) / 400.;
d = (year + d1 - d2 + d3) % 7;
return d;
}
int main()
{
int day, month, year, ndays, DayWeek = 0, FirstDay;
do
{
printf("\nEnter the desired year [2000 - 2099]\n");
scanf_s(" %d", &year);
} while (year < 2000 || year > 2100);
do
{
printf("\nEnter the desired month [1 - 12]\n");
scanf_s(" %d", &month);
} while (month < 1 || month > 12);
char *months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
int DayMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
DayMonth[1] = 29;
FirstDay = SetFirstDay(year);
for (month = 0; month < 12; month++)
{
ndays = DayMonth[month];
printf("\n\n--------------%s-----------------\n", months[month]);
printf("\n Sun Mon Tue Wed Thu Fri Sat\n");
for (DayWeek = 0; DayWeek < FirstDay; DayWeek++)
{
printf(" ");
}
for (day = 1; day <= ndays; day++)
{
printf("%5d", day);
if (++DayWeek > 6)
{
printf("\n");
DayWeek = 0;
}
FirstDay = DayWeek;
}
}
printf("\n\n\n");
system("pause");
return 0;
}

Save the month value which comes from user input to an additional variable:
int monthTmp = month;
Then prefix all printf invokations with the following statement withing the "month" for loop:
for (month = 0; month < 12; month++)
{
// ...
if (monthTmp==month) printf(.........
It is not an optimized solution, but it is very straightforward.

Related

Index out of bound, java

I have a problem regarding index out of bound error in arrays.
I want to create a method that takes month and day as parameter and returns day of the year.If any of the parameters are incorrect, the method should return 0.
for example if the method receives 2 and 3, meaning the third of February it must return 34. If it receives 12 and 31, it must return 365.
but I am getting this problem of index out of bound and can't solv it any tips.
this is my code.
public class CalendarMethods {
public static int dayInYear(int month, int day){
int[] daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int yearCalculation = 0;
int monthCalculation = 0;
for (int j = 0; j < month-1; j++) {
monthCalculation = monthCalculation + daysInMonth[j];
}
yearCalculation = monthCalculation + day;
if (month <= 0 ) {
yearCalculation = 0;
}
if (month >= 13){
yearCalculation = 0;
}
return yearCalculation;
}
}
You should do the boundary checks on month before the loop. A fix for that would be:
public class CalendarMethods {
public static int dayInYear(int month, int day){
int[] daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int yearCalculation = 0;
int monthCalculation = 0;
if (month > 0 && month < 13) {
if (day > 0 && day <= daysInMonth[month - 1]) { // extra: check if entered day makes sense
for (int j = 0; j < month-1; j++) {
monthCalculation = monthCalculation + daysInMonth[j];
}
yearCalculation = monthCalculation + day;
}
}
return yearCalculation;
}
}
For functions, always do sanity checks first to ensure the inputs you are getting align with your expections, in this this case we expect months to be values between 1 and 12 so same implementation as you had but check inputs before processing the rest of the code. This saves you from exceptions from unexpected/bad inputs.
public static int dayInYear(int month, int day){
if (month <= 0||month >= 13 ) {
return 0;
}
int[] daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int yearCalculation = 0;
int monthCalculation = 0;
for (int j = 0; j < month-1; j++) {
monthCalculation = monthCalculation + daysInMonth[j];
}
yearCalculation = monthCalculation + day;
return yearCalculation;
}

Military time and standard time logic works but time indicator string is not working

The goal of my code was to be able to switch between standard and military time if there was a tag when executing it.
When in military time, it has to have "24" at the end, and when in standard it has to have "am" or "pm" at the end.
It seems I am able to get the ampm logic, but it shows 24 and not am or pm - only 24. Is there something wrong with the modestring in my bigger else block?
void show(struct tm *dateinfo, int ampm)
{
char timestring[9];
char modestring[3];
int hour;
hour = dateinfo->tm_hour;
if ( ampm == 0 )
{
sprintf(timestring,
"%02d:%02d:%02d",
hour,
dateinfo->tm_min,
dateinfo->tm_sec);
sprintf(modestring, "24");
}
else
{
if ( hour < 12 )
{
if ( hour == 0 )
{
hour = 12;
}
sprintf(modestring, "am");
}
else
{
if ( hour == 12 )
{
hour = 12;
}
else
{
hour = hour % 12;
}
sprintf(modestring, "pm");
}
}
printf("\r%s %s", timestring, modestring);
fflush(stdout);
}
You're only setting timestring in the if ( ampm == 0 ) block. Move it to after the if block after setting hour.
if ( ampm == 0 )
{
sprintf(modestring, "24");
}
else if ( hour < 12 )
{
if ( hour == 0 )
{
hour = 12;
}
sprintf(modestring, "am");
}
else
{
if ( hour > 12 )
{
hour = hour % 12;
}
sprintf(modestring, "pm");
}
sprintf(timestring,
"%02d:%02d:%02d",
hour,
dateinfo->tm_min,
dateinfo->tm_sec);

I am trying to figure out a way to convert month name to integer

So basically I need to find a way to make the month of my date Convert to number as well as my time to go from military time to standard time.
I am getting issues running my code and can't figure out why. It's probably a simple mistake but if you guys figure out please let me know.
from Monday, June 2, 2012, 22:12:12 to 6/2/2012, 10:12 PM format.
#include <stdio.h>
#include <string.h>
/*This code will take user input of date and use 2-d array to store strings
using delimeter as well. It will list all
the date in descending order seperating:
"Month", "Day", "Year", "Hour", "Minute", "Second"
from:
"Saturday, July 8, 2017, 22:14:10"
*/
int findMonthNum(const char *key);
int main(void){
char *check[] = {
"Saturday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Sunday", "Friday",
#if 1
NULL
#endif
};
char *monthString[] = {
"January", "February", "March", "April", "May", "June", "July", "August", "September",
"October", "November", "December",
#if 1
NULL
#endif
};
char **day;
char **month;
// creates 2 day array
char date[8][20];
// creates order of time
char *order[] = { "Month", "Day", "Year", "Hour", "Minute", "Second" };
printf("Enter date separated by commas in following format:\n");
printf(" Example: Saturday, July 8, 2017, 22:14:10\n");
// array to store string initially
char text[64];
// reads strings
fgets(text, 64, stdin);
// this is the delimeter that will be helpful for seperating it to
// different tokens
char *delims = " ,:";
char *token = strtok(text, delims);
char **label = order;
int r = 0;
while (token) {
// look for match on day of the week
for (day = check; *day != NULL; ++day) {
if (strcmp(token,*day) == 0)
break;
}
// if _not_ day of the week, store the value
if (*day == NULL) {
strcpy(date[r], token);
printf("%-8s: %s\n ", *label, date[r]);
label++;
r++;
}
// this is so that it will find null values at the end and leave off
// where it was.
token = strtok(NULL, delims);
}
// Convert the above date to 7/8/2017, 10:14 PM format
int findMonthNum(const char *key){
static const char *monthStrings[] = {
"January", "February", "March", "April", "May", "June", "July", "August", "September",
"October", "November", "December", NULL
};
for( int i = 0; monthStrings[i] != NULL; i++ ) {
if( strcmp(monthStrings[i], key) == 0 ) {
return i+1;
}
}
return -1;
}
printf("%d/%s/%s, %s:%s", findMonthNum(date[0]), date[1], date[2], date[4], date[5]);
return 0;
}
It keeps saying expected expression before consts.
You can iterate through monthString until you match, then return the index + 1, or -1 if it isn't found.
int findMonthNum(const char *key) {
// This is declared `static` so it's only ever allocated once.
//
// It's declared inside the function so long as the function is
// the only thing using it.
//
// It's declared `const char *monthStrings[]` because
// it is an array of `const char *`. "Strings like this" are
// constants and cannot be modified.
//
// The NULL at the end lets us known when to stop iterating
// without knowing the length of the array.
static const char *monthStrings[] = {
"January", "February", "March", "April", "May", "June", "July", "August", "September",
"October", "November", "December", NULL
};
// Iterate from monthStrings[0] until you hit a NULL value.
for( int i = 0; monthStrings[i] != NULL; i++ ) {
if( strcmp(monthStrings[i], key) == 0 ) {
return i+1;
}
}
// Return -1 if you don't find a matching month.
return -1;
}
int monthNum = findMonthNum("June"); // 6
monthNum = findMonthNum("Septembuary"); // -1
However, C has built in functions strptime to parse datetimes and strftime to format them. They both use the same sprintf-like specification to parse and format.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
char date[] = "Monday, June 2, 2012, 22:12:12";
struct tm parsed;
// Parse the string into a struct tm.
strptime(date, "%A, %B %e, %Y, %T", &parsed);
// Print it to check it parsed correctly.
printf("parsed: %s\n", asctime(&parsed));
// Format the struct tm to a new string.
char formatted[40];
strftime(
formatted,
sizeof(formatted),
"%D %I:%M %p",
&parsed
);
printf("formatted: %s\n", formatted);
}
Alternative to checking the name up to 12 times
In mapping a month name to an index, we can have some hash fun.
Let us assume month names remain as there are in English.
Notice that the 2nd & 3rd characters are enough to distinguish all 12.
Hash by adding those 2 characters and look at the 5 LSbits to form an index into a map.
Compare if the mapped value matches.
Very fast - only 1 string compare.
Of course this is not directly applicable if code used a different set on month names.
#include <ctype.h>
#include <string.h>
static const char *monthString[] = { //
"January", "February", "March", "April", //
"May", "June", "July", "August", //
"September", "October", "November", "December" };
int month_to_index(const char *month_name) {
size_t len = strlen(month_name);
if (len >= 3) {
unsigned sum = (tolower(month_name[1]) + tolower(month_name[2])) %32;
static const unsigned char table[32] = {
[1] = 7, [2] = 4, [3] = 6, [5] = 11, //
[7] = 2, [8] = 12, [15] = 1, [19] = 3, //
[21] = 9, [23] = 10, [26] = 5, [28] = 8 //
};
unsigned index = table[sum];
if (index && strncasecmp(month_name, monthString[index-1], len) == 0) {
return index;
}
}
return 0;
}
Sample use
#include <stdlib.h>
#include <stdio.h>
int main() {
for (int mm = 0; mm<12; mm++) {
char buf[20];
strcpy(buf, monthString[mm]);
int len = strlen(buf);
if (len > 3) {
int offset = rand() % (len-3) + 3;
buf[offset] = '\0';
}
for (int i=0; buf[i]; i++) {
if (rand()%2) {
buf[i] ^= 'A' ^ 'a'; // toggle case
}
}
unsigned index = month_to_index(monthString[mm]);
if (index > 0) {
printf("%2i %2u <%10s> <%s>\n", mm, index, monthString[mm], buf);
}
}
return 0;
}
Output
0 1 < January> <jaNu>
1 2 < February> <FebRUA>
2 3 < March> <maRc>
3 4 < April> <apR>
4 5 < May> <may>
5 6 < June> <jUn>
6 7 < July> <jUL>
7 8 < August> <AUgu>
8 9 < September> <SePTe>
9 10 < October> <OCT>
10 11 < November> <nOvem>
11 12 < December> <deC>
Here you have it without any stdlib functions .
#include <stdio.h>
#include <stdint.h>
typedef struct
{
int year, month, day;
int hour, min, sec;
int am;
}mytime_t;
unsigned mystrtou(const char *str)
{
unsigned result = 0;
while(*str)
{
result *= 10;
result += *str++ - '0';
}
return result;
}
char *skipspaces(char *str)
{
while(*str && (*str == ' ' || *str == ',')) str++;
return str;
}
int streq(const char *str1, const char *str2)
{
int result = 0;
while(*str1 || *str2)
{
if(*str1++ != *str2++)
{
result = 1;
break;
}
}
return result;
}
int slice(char *mil, char **argv)
{
int argc = 0;
mil = skipspaces(mil);
if(*mil)
{
argc++;
*argv = mil;
argv++;
}
while(*mil)
{
if(*mil == ',' || *mil == ' ' || *mil == ':')
{
*mil++ = 0;
mil = skipspaces(mil);
if(*mil)
{
argc++;
*argv = mil;
argv++;
}
}
mil++;
}
return argc;
}
const char *monthNames[] = {
"January", "February", "March", "April", "May", "June", "July", "August", "September",
"October", "November", "December",
};
int getMonth(const char *month)
{
int result = -1;
for(int index = 0; index < sizeof(monthNames) / sizeof(monthNames[0]); index++)
{
if(!streq(month, monthNames[index]))
{
result = index + 1;
break;
}
}
return result;
}
int convert(char *data, mytime_t *time)
{
int result = -1;
char *argv[10];
int argc = slice(data, argv);
if(argc == 7)
{
result = 0;
time -> am = 1;
time -> year = mystrtou(argv[3]);
time -> month = getMonth(argv[1]);
time -> day = mystrtou(argv[2]);
time -> hour = mystrtou(argv[4]);
time -> min = mystrtou(argv[5]);
time -> sec = mystrtou(argv[6]);
if(time -> hour > 12)
{
time -> am = 0;
time -> hour -= 12;
}
}
return result;
}
int main()
{
char str[] = "Monday, June 2, 2012, 22:12:12";
mytime_t time;
convert(str, &time);
printf("%d/%d/%d %d:%d %s\n", time.month, time.day, time.year, time.hour, time.min, time.am ? "am" : "pm");
}
https://godbolt.org/z/qSFh8p

Pointers: Expression is not assignable

I'm writing a function whose purpose is to change the value of struct variables. I'm getting error messages that say the expressions toward the end of my first function are not assignable. How, then, do I have the function change the values of the daate structure?
Here's my code:
#include <stdio.h>
#include <stdbool.h>
struct date
{
int month;
int day;
int year;
};
struct date dateUpdate (struct date *dait) {
struct date tomorrow;
int numberOfDays (struct date d);
if (dait->day != numberOfDays (*dait) ) {
tomorrow.day = dait->day + 1;
tomorrow.month = dait->month;
tomorrow.year = dait->year;
}
else if ( dait->month == 12 ) { //end of year
tomorrow.day = 1;
tomorrow.month = 1;
tomorrow.year = dait->year + 1;
}
else { //end of month
tomorrow.day = 1;
tomorrow.month = dait->month + 1;
tomorrow.year = dait->year;
}
&dait->day = tomorrow.day;
&dait->month = tomorrow.month;
&dait->year = tomorrow.year;
return *dait;
}
//Function to find the number of days in a month;
int numberOfDays (struct date d)
{
int days;
bool isLeapYear (struct date d);
const int daysPerMonth[12] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if ( isLeapYear (d) && d.month == 2 )
days = 29;
else
days = daysPerMonth[d.month - 1];
return days;
}
}
int main (void) {
struct date daate;
daate.day = 21;
daate.month = 6;
daate.year = 2013;
dateUpdate(&daate);
printf("%d", daate.day);
}
The correct syntax (which you already used in the function) is the following
dait->day = tomorrow.day;
dait->month = tomorrow.month;
dait->year = tomorrow.year;
Take into account that instead of these three statements you could write simply
*dait = tomorrow;
dait is already a pointer, so &dait is a pointer to a pointer, and thus it has no fields to de-reference.
Solution: lose the & before dait.

Can't figure out why strcpy isn't copying string effectively?

I'm trying to construct a program that has the user input the date in this format '01'14'2013', and outputs it into this format 'january 14, 2013'. I am trying to copy the string that holds the input from the user onto a different string, to later concatenate it onto the original string without the first and second index of the strings, so that I only have '/14/2013', from the original string, and then replace the '/' with ' ' so that it reads the month, day and the year....but for some reason, when I try to copy the original string from input onto another string( the one I plan to concatenate later), it doesn't copy effectively, am i missing something..?
#include <stdio.h>
#include <string.h>
int main()
{
char date[100];
char month[100];
char array[12][100] ={"January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
char month2[100];
printf(" Please enter a date ");
fgets( date, 100, stdin);
strcpy(month2, month);
if( date[0] == '0' && date[1] == '1')
{
strcpy(month, array[0]);
}
else if( date[0] =='0' && date[1] == '2')
{
strcpy(month, array[1]);
}
else if( date[0] =='0' && date[1] == '3')
{
strcpy(month, array[2]);
}
else if( date[0] =='0' && date[1] == '4')
{
strcpy(month, array[3]);
}
else if( date[0] =='0' && date[1] == '5')
{
strcpy(month, array[4]);
}
else if( date[0] == '0' && date[1] == '6')
{
strcpy(month, array[5]);
}
else if( date[0] =='0' && date[1] == '7')
{
strcpy(month, array[6]);
}
else if( date[0] =='0' && date[1] == '8')
{
strcpy(month, array[7]);
}
else if( date[0] =='0' && date[1] == '9')
{
strcpy(month, array[8]);
}
else if( date[0] =='1' && date[1] == '0')
{
strcpy(month, array[9]);
}
else if( date[0] =='1' && date[1] == '1')
{
strcpy(month, array[10]);
}
else if( date[0] =='1' && date[1] == '2')
{
strcpy(month, array[11]);
}
printf("%s \n", month);
printf("%s \n", month2);
return 0;
}
strcpy(month2, month);
Neither month nor month2 have been initialized to anything useful at this point. Their contents are indeterminate and calling strcpy with something other than a properly terminated C-string invokes undefined behavior.
Looks like a typo to me.
Lesser code, But without some validations.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char date[100];
char month[100];
char array[12][100] = {"January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
printf(" Please enter a date ");
fgets( date, 100, stdin);
char month2[100];
strcpy(month2, date);
month2[2] = '\0';
strcpy(month, array[atoi(month2) - 1]);
printf("%s \n", month);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
typedef struct mon {
const char *name;
const int len;
} Month;
#define M(x){ x " ", sizeof(x)}
Month month[] = { {"", 0}, //dummy
M("January"), M("Febuary"), M("March"), M("April"),
M("May"), M("June"), M("July"), M("August"),
M("September"), M("October"), M("November"), M("December")
};
int main(){
char in_date[128];
char out_date[128] = "";
int m = 0, pos;
printf(" Please enter a date E.g MM/DD/YYYY\n");
fgets( in_date, sizeof(in_date), stdin);
if(in_date[0] == '0'){
if(isdigit(in_date[1]) && in_date[1] != '0'){
m = in_date[1] - '0';
pos = month[m].len;
memcpy(out_date, month[m].name, pos);
}
} else if(in_date[0] == '1'){
if('0' <= in_date[1] && in_date[1] <= '2'){
m = 10 + in_date[1] - '0';
pos = month[m].len;
memcpy(out_date, month[m].name, pos);
}
}
if(m){
memcpy(out_date + pos, in_date + 3, 7);
out_date[pos + 2] = ',';
out_date[pos + 7] = '\0';
printf("%s\n", out_date);
} else {
printf("invalid month\n");
}
return 0;
}

Resources