gloopit gloopit - 4 months ago 20
C Question

Have I utilized pointers properly in the updateDate function?

I am working with a program that updates an inputted date and updates it. Taking into account days in the month and whether it's a leap year etc.

I'm attempting an exercise in the pointers chapter of 'Programming in C':

"Given the definition of a

date
structure as defined in this chapter, write a function called
dateUpdate()
that takes a pointer to a
date
structure as its argument and that updates the structure to the following day(see Program 8.4)."

Can you please tell me if I have done what was asked?

This is the original code:

#include <stdio.h>
#include <stdbool.h>

struct date
{
int month;
int day;
int year;
};


struct date dateUpdate (struct date today);
int numberOfDays (struct date d);
bool isLeapYear(struct date d);

int main (void)
{
struct date thisDay, nextDay;

printf("Enter today's date (mm dd yyyy) : ");
scanf("%i%i%i", &thisDay.month, &thisDay.day, &thisDay.year);

nextDay = dateUpdate(thisDay);

printf("Tomorrow's date is %i/%i/%.2i.\n", nextDay.month, nextDay.day, nextDay.year % 100);

return 0;
}


struct date dateUpdate (struct date today)
{
struct date tomorrow;
int numberOfDays (struct date d);

if(today.day != numberOfDays (today))
{
tomorrow = (struct date) {today.month, today.day + 1, today.year};
}
else if(today.month == 12)
{
tomorrow = (struct date) {1, 1, today.year + 1};
}
else
{
tomorrow = (struct date) {today.month + 1, 1, today.year};
}

return tomorrow;
}

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;
}

bool isLeapYear(struct date d)
{
bool leapYearFlag;

if ( (d.year % 4 == 0 && d.year % d.year % 100 != 0) || d.year % 400 == 0)
{
leapYearFlag = true;
}
else
{
leapYearFlag = false;
}

return leapYearFlag;
}


And here is my attempt to utilize pointers in the
updateFunction
:

#include <stdio.h>
#include <stdbool.h>

struct date
{
int month;
int day;
int year;
};


struct date dateUpdate (struct date* today);
int numberOfDays (struct date d);
bool isLeapYear(struct date d);

int main (void)
{
struct date thisDay, nextDay, *datePtr;

printf("Enter today's date (mm dd yyyy) : ");
scanf("%i%i%i", &thisDay.month, &thisDay.day, &thisDay.year);

datePtr = &thisDay;

nextDay = dateUpdate(datePtr);

printf("Tomorrow's date is %i/%i/%.2i.\n", nextDay.month, nextDay.day, nextDay.year % 100);

return 0;
}


struct date dateUpdate (struct date* today)
{
struct date tomorrow;
int numberOfDays (struct date d);

if(today->day != numberOfDays (*today))
{
tomorrow = (struct date) {today->month, today->day + 1, today->year};
}
else if(today->month == 12)
{
tomorrow = (struct date) {1, 1, today->year + 1};
}
else
{
tomorrow = (struct date) {today->month + 1, 1, today->year};
}

return tomorrow;
}

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;
}

bool isLeapYear(struct date d)
{
bool leapYearFlag;

if ( (d.year % 4 == 0 && d.year % d.year % 100 != 0) || d.year % 400 == 0)
{
leapYearFlag = true;
}
else
{
leapYearFlag = false;
}

return leapYearFlag;
}


Right now both programs compile and seem to run properly.

Answer

To expand on Omid CompSCI's comment: it is almost just as simple. Almost.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// ALL TESTS OMMITTED!

struct date {
  int month;
  int day;
  int year;
};
// add the pointer mark (asterix)
struct date *dateUpdate(struct date *today);
int numberOfDays(struct date *d);
bool isLeapYear(struct date *d);

int main(void)
{
  // again ,just add the pointer marks
  struct date *thisDay, *nextDay;
  // using a pointer means that all you have is a pointer
  // but you need some memory to store the content
  thisDay = malloc(sizeof(struct date));

  printf("Enter today's date (mm dd yyyy) : ");
  // use the "->" notation to get to the respective storages
  scanf("%i%i%i", &thisDay->month, &thisDay->day, &thisDay->year);

  // dateUpdate() has been changed to accept and return a pointer,
  // so no change in notations here 
  nextDay = dateUpdate(thisDay);
  // again: use the "->" notation to get to the respective storages
  printf("Tomorrow's date is %i/%i/%.2i.\n", nextDay->month, nextDay->day,
     nextDay->year % 100);

  // memory allocated by 'alloc() needs to be free'd, too
  free(nextDay);
  free(thisDay);

  return 0;
}

// just added pointer markings
struct date *dateUpdate(struct date *today)
{
  struct date *tomorrow;
  // again, we need to allocated some memory
  // not only to get storage but also to be able to return it
  tomorrow = malloc(sizeof(struct date));
  // again: use the "->" notation to get to the respective storages
  if (today->day != numberOfDays(today)) {
    // the notation of the cast does not change, the target does
    *tomorrow = (struct date) {
    today->month, today->day + 1, today->year};
  } else if (today->month == 12) {
    *tomorrow = (struct date) {
    1, 1, today->year + 1};
  } else {
    *tomorrow = (struct date) {
    today->month + 1, 1, today->year};
  }
  return tomorrow;
}

int numberOfDays(struct date *d)
{
  int days;
  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;
}

bool isLeapYear(struct date * d)
{
  bool leapYearFlag;
  // you have one "d.year %" too much in your code
  if ((d->year % 4 == 0 && d->year % 100 != 0) || d->year % 400 == 0) {
    leapYearFlag = true;
  } else {
    leapYearFlag = false;
  }

  return leapYearFlag;
}

I hope that makes it a bit clearer.