【问题标题】:Have I utilized pointers properly in the updateDate function?我是否在 updateDate 函数中正确使用了指针?
【发布时间】:2016-07-28 21:39:04
【问题描述】:

我正在使用一个程序来更新输入的日期并更新它。考虑到当月的天数以及是否是闰年等。

我正在尝试在“C 语言编程”的指针章节中进行练习:

“给定本章中定义的date 结构的定义,编写一个名为dateUpdate() 的函数,该函数将指向date 结构的指针作为其参数,并将结构更新到第二天(参见程序 8.4)。”

你能告诉我我是否按照要求完成了吗?

这是原始代码:

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

这是我在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;
}

现在两个程序都可以编译并且运行正常。

【问题讨论】:

  • 我不完全理解你的问题。但是要创建一个指向结构的指针,你明天会做 struct data* ;在任何你有点运算符的地方,只要把它变成箭头运算符->。示例:不要让明天.day 让它成为明天-> 天;
  • 我的错,让我重写这个车祸的一个问题。
  • 你试过了吗?

标签: c pointers data-structures


【解决方案1】:

扩展 Omid CompSCI 的评论:它几乎一样简单。差不多了。

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

我希望这能让它更清楚一点。

【讨论】:

  • 非常感谢!如果先声明非指针结构,连同它们的大小,然后分配一个指针,我可以避免使用 malloc,对吧?
  • Malloc 不是我尚未涉及的内容,在我正在学习的书中进一步介绍。
  • 如果您在上面看到我的尝试,我没有对其他函数使用指针语法,例如 isLeapYearnumberOfDays。将其更改为指针有什么好处吗?看到唯一改变的是添加* 并切换.-&gt; 我承认我喜欢你的统一性:)
  • dateUpdate() 中的 malloc 是必要的,因为您返回了结构。你可以把它留在那里,让其他的保持不变,但是你有一个不健康的和容易出错的组合。而且,好吧,你想要它带有指针,这就是我所做的。
  • 好的,谢谢!最后两件事,拜托。在 dateUpdate 的 if/else 语句中,需要 *tomorrow 的星号的原因是什么。因为它已经在上面声明和初始化了。另外,在声明函数时:struct date *dateUpdate(struct date *today) 为什么星号在dateUpdate 旁边而不是struct date* 旁边?我看起来很困惑。
【解决方案2】:

此代码可以轻松转换为使用指针。指针很有用,因为它们提供了每次调用函数时复制结构数据的替代方法。您仍然可以在其他地方使用正常的按值传递机制。重写代码非常简单,只需要很少的改动。例如,您的 struct date dateUpdate(); 函数可以通过在类型后添加 * 符号重新用于接受指针,例如intint *。 函数struct date dateUpdate 的定义将更改为struct date *dateUpdate (struct date *today);,这意味着正在传递日期结构的指针或内存地址。您的代码也必须在声明中更改。例如,bool isLeapYear() 中的代码行 if ( (d.year % 4 == 0 &amp;&amp; d.year % d.year % 100 != 0) || d.year % 400 == 0) 将不得不更改为 if ( (d-&gt;year % 4 == 0 &amp;&amp; d-&gt;year % d-&gt;year % 100 != 0) || d-&gt;year % 400 == 0)-&gt; 运算符是 (*pointer).variable 的简写,因为必须告知编译器在 address 处获取结构的成员,而不是指针的实际位置。 现在传递的类型已经改变,调用也不同了。现在调用bool isLeapYear() 不是bool isLeapYear (d);,而是 bool isLeapYear (&amp;d);,因为&amp; 运算符获取struct 的地址。 使用此信息,这是您的程序的转换版本:link. 然而,一个大问题是您的大部分代码都不起作用,但这超出了您的问题范围。 编辑:这个答案是在您编辑问题之前做出的,但仍然有帮助。

【讨论】:

    【解决方案3】:

    这是我对这个练习的看法,我认为该练习旨在使用指针将单个日期结构更新为第二天的日期。

    /* Exercise 10.11
    
       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.
    */
    
    #include <stdio.h>
    #include <stdbool.h>
    
    struct date
    {
        int month;
        int day;
        int year;
    };
    
    void dateUpdate (struct date *ptr)
    {
        int numberOfDays (struct date d);
    
        if ( ptr->day != numberOfDays (*ptr) )
            ++ptr->day;
        else if ( ptr->month == 12 ) {                  // end of year
            ptr->day = 1;
            ptr->month = 1;
            ++ptr->year;
        }
        else {                                          // end of month
            ptr->day = 1;
            ++ptr->month;
        }
    }
    
    int numberOfDays (struct date d)
    {
        bool isLeapYear (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;
    
        if ( (d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0 )
            leapYearFlag = true;                        // leap year
        else
            leapYearFlag = false;                       // not a leap year
    
        return leapYearFlag;        
    }
    
    int main (void)
    {
        void dateUpdate (struct date *ptr);
    
        struct date calendar;
    
        printf ("Enter a day's date (mm dd yyyy): ");
        scanf ("%i%i%i", &calendar.month, &calendar.day, &calendar.year);
    
        dateUpdate (&calendar);
    
        printf ("The next day's date is %i/%i/%.2i.\n", calendar.month,
                 calendar.day, calendar.year % 100);
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多