2

我的计划旨在实现这一目标

(A)编写一个名为的 C 函数larger(),返回传递给它的任意两个日期的较晚日期。例如,如果将日期 10/9/2001 和 11/3/2001 传递给larger(),则将返回第二个日期。

(B)在一个完整的单元中创建为 (A) 编写的 large() 函数。将 large() 返回的日期结构存储在单独的日期结构中,并显示返回数据结构的成员值。

我正在为我的 C 语言课程解决这个问题。我一切都很顺利(我想),除了我不断收到“较大的日期是:0/0/0”,无论我输入什么。所以我开始修修补补,现在我无法摆脱语法错误,或者找出我的 0/0/0 问题。显然,日期并没有回来。我在这方面还是很新的(在结构方面也很新),所以任何帮助都会很棒!

给我语法错误的行在 main() 的底部附近:

DATES result[NUM] = larger(DATES user[NUM]);

完整代码:

#include <stdio.h>
#define NUM 2
struct Dates
{
       int month;
       int day;
       int year;
};
typedef struct Dates DATES;
DATES larger(DATES[NUM]);
DATES more;
int main()
{
    DATES user[NUM];

    printf("You will enter two dates, and the program will return the larger.\n");
    while (user[0].month < 1 || user[0].month > 12)
         {printf("\nPlease enter the first month, 1-12: ");
         scanf("%d", &user[0].month);}
    while (user[0].day < 1 || user[0].day > 31)
          {printf("\nPlease enter the first day, 1-31: ");
          scanf("%d", &user[0].day);}
    while (user[0].year < 1)
          {printf("\nPlease enter the first year: ");
          scanf("%d)", &user[0].year);}
    printf("\nDate entered: %d/%d/%d.\n", user[0].month, user[0].day, user[0].year);

    while (user[1].month < 1 || user[1].month > 12)
         {printf("\nPlease enter the first month, 1-12: ");
         scanf("%d", &user[1].month);}
    while (user[1].day < 1 || user[1].day > 31)
          {printf("\nPlease enter the first day, 1-31: ");
          scanf("%d", &user[1].day);}
    while (user[1].year < 1)
          {printf("\nPlease enter the first year: ");
          scanf("%d)", &user[1].year);}
    printf("\nDate entered: %d/%d/%d.\n\n", user[1].month, user[1].day, user[1].year);

    DATES result[NUM] = larger(DATES user[NUM]);  /* Problem here */

    printf("The larger date is %d/%d/%d.\n\n", result[0].month, result[0].day, result[0].year);
    system("pause");
    return 0;
}

DATES larger(DATES more[NUM])
{        
      int days0;
      int days1;

      days0 = (more[0].month*31)+(more[0].day)+(more[0].year*365);
      days1 = (more[1].month*31)+(more[1].day)+(more[1].year*365);

      if (days1 > days0)
         {more[0] = more[1];}

return (more[0]);
}
4

5 回答 5

1
DATES result[NUM] = larger(DATES user[NUM]);

这是为了什么?DATES result[NUM]声明一个数组DATES。(但每个DATES只包含一个日期,这令人困惑。)但尽管它是一个数组,但它是用一个对象初始化的,返回值来自larger. larger,的参数DATES user[NUM]似乎在声明user, 一个已经存在的变量。看起来您正试图向编译器澄清user一个日期数组,但DATES没有去那里并且[NUM]似乎正在索引到您不想要的数组中。

可能你想要的是

DATES result = larger( user );

还有一些严重的风格问题会在以后引起麻烦:

  • 函数参数的数组类型如 inDATES larger(DATES[NUM]);被转换为指针。在那一行,NUM什么都不做,声明与DATES larger( DATES * );. 尽管有些老师可能会说,指针和数组不是一回事。当区分很重要时,这种风格会引起混乱。改为使用DATES larger( DATES * )

  • 大写没有意义DATES。大写通常表示预处理器宏。

  • 预处理器宏就像一把大锤。将它们用于简单的数字常量不如const int num = 2;or之类的结构优雅enum { num = 2 };

  • 描述性变量名称,例如input_limitanduser_input会比numand更好user

  • 不要依赖未初始化的数据。在定义但未初始化user[0].month之后可能是 6 。user在读取之前始终写入一个值。

  • 大括号应保持可见。将大括号与循环的第一个词和最后一个词紧密组合会隐藏它们,如果您认为它们很难看,这很好,但是很容易错误地将一行添加到循环中,从而产生难以调试的流控制错误。

于 2013-05-03T02:56:43.957 回答
0

正如半信半疑的那样,对Rüppell 的 Vulture回答进行了修订。这段代码努力避免在另一个答案中出现重复——与问题中的代码相比,这已经减少了。

有多种变化。由于该类型仅存储单个日期,因此将其重命名为Date. 有一个通用函数read_validate_number()用于处理日期的每个组成部分的输入(带有单独的提示)。该函数返回错误/非错误状态并通过指针参数返回值。它为提示用户输入数字的次数设置了上限。它避免了侮辱用户,但确实报告了错误的值。代码使用while循环而不是do ... while循环;通常,应避免后者。在读取数字失败后可以读取换行符,而不是简单地返回错误。

有了这个功能,写作read_date()变得微不足道。并且read_date()在手边,main()功能简化了。

我仍然不热衷于该功能的界面larger();总的来说,我更喜欢later_date(). 但是,代码显示了larger()接口的一个优点;它可以按数组中的位置识别两个日期中较大的一个,而later_date()按值识别。

其他函数main()都是静态的,因为它们不在此文件之外使用;我使用的编译器选项需要static函数或extern声明。

总的来说,我更喜欢一个不那么冗长的界面来输入日期。我也更喜欢 ISO 8601 格式的日期,因为它们是明确的;但是,这将是完全国际化(和本地化)代码中的用户偏好项。

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

#define NUM 2
typedef struct Date
{
       int month;
       int day;
       int year;
} Date;

enum { MAX_ERRORS = 3 };

static int read_validate_number(const char *tag, int min, int max, int *value)
{
    int errors = 0;
    assert(min <= max);
    while (errors++ < MAX_ERRORS)
    {
        printf("Please enter the %s number (%d-%d): ", tag, min, max);
        if (scanf("%d", value) != 1)
        {
            printf("Failed to read number\n");
            return EOF;
        }
        if (*value >= min && *value <= max)
            return 0;
        printf("The value entered (%d) is outside the range %d-%d\n", *value, min, max);
    }
    printf("Too many errors entering %s\n", tag);
    return EOF;
}

static int read_date(Date *date)
{
    if (read_validate_number("month", 1,   12, &date->month) != 0 ||
        read_validate_number("day",   1,   31, &date->day  ) != 0 ||
        read_validate_number("year",  1, 9999, &date->year ) != 0)
        return EOF;
    return 0;
}

static Date *larger(Date *more)
{
    int days0 = (more[0].month*31)+(more[0].day)+(more[0].year*365);
    int days1 = (more[1].month*31)+(more[1].day)+(more[1].year*365);

    // Resist the temptation to write: return more + (days1 > days0);
    if (days1 > days0)
        return more+1;
    else
        return more+0;
}

static Date later_date(Date d1, Date d2)
{
    int days1 = d1.day + d1.month * 31 + d1.year * 365;
    int days2 = d2.day + d2.month * 31 + d2.year * 365;

    if (days1 > days2)
        return d1;
    else
        return d2;
}

int main(void)
{
    Date user[NUM];

    printf("Enter two dates, and the program will return the larger.\n");
    if (read_date(&user[0]) == 0 && read_date(&user[1]) == 0)
    {
        putchar('\n');
        printf("Date 1: %.4d-%.2d-%.2d\n", user[0].year, user[0].month, user[0].day);
        printf("Date 2: %.4d-%.2d-%.2d\n", user[1].year, user[1].month, user[1].day);
        Date *p_later = larger(user);
        Date  v_later = later_date(user[0], user[1]);
        printf("\nThe later date is the %s (%d/%d/%d)\n",
               (p_later == &user[0]) ? "first" : "second",
               p_later->month, p_later->day, p_later->year);
        printf("Later Date: %.4d-%.2d-%.2d\n", v_later.year, v_later.month, v_later.day);
    }

    return 0;
}

样本输出:

Enter two dates, and the program will return the larger.
Please enter the month number (1-12): 12
Please enter the day number (1-31): 25
Please enter the year number (1-9999): 2013
Please enter the month number (1-12): 1
Please enter the day number (1-31): 1
Please enter the year number (1-9999): 2012

Date 1: 2013-12-25
Date 2: 2012-01-01

The later date is the first (12/25/2013)
Later Date: 2013-12-25

我注意到您可以通过对and组件使用 ( or ) 以及对组件Date使用unsigned char(or ) 来减小结构的大小。但是,您必须稍微修改函数才能这样做:uint8_tdaymonthunsigned shortuint16_tyearread_date()

#include <stdint.h>

typedef struct Date
{
       uint8_t  month;
       uint8_t  day;
       uint16_t year;
} Date;

static int read_date(Date *date)
{
    int mm, dd, yyyy;
    if (read_validate_number("month", 1,   12, &mm  ) != 0 ||
        read_validate_number("day",   1,   31, &dd  ) != 0 ||
        read_validate_number("year",  1, 9999, &yyyy) != 0)
        return EOF;
    date->month = mm;
    date->day   = dd;
    date->year  = yyyy;
    return 0;
}

在某些时候,您可能想要阻止某人进入 2 月 31 日(但请记住,2 月 30 日曾经是2 月 30 日——在 1712 年的瑞典;或者再次出现,也许您不需要记住这一点)。

于 2013-05-04T07:48:28.890 回答
0

@Rüppell'sVulture 您突出显示了他的错误,但代码太错误了。我已经研究了一个更简单的解决方案。看一看。

@iMPose27 请查看以下代码,如果您遇到困难,请告诉我

// includes
#include <stdio.h>
#include <string.h>

// macros
#define NUM 2

// structure Definitions
struct Dates
{
       int month;
       int day;
       int year;
};

// typedefs
typedef struct Dates DATES;

// function declarations
DATES* larger(DATES[NUM]);

// function definitions
int main(int argc, char* argv[])
{
    DATES user[NUM];    // array of NUM DATES
    DATES *result=NULL;
    int i=0;
    printf("\nPlease Enter Two Dates, The program will evaluate and return the later date of the two dates passed to it\n\n");
    for(;i<NUM;i++)   
    {    
        printf("For Date %d\n",i+1);

        do{
             printf("Please enter the month, 1-12:\t");
             scanf("%d", &user[i].month);
        }while (user[i].month < 1 || user[i].month > 12);

        do{
              printf("Please enter the day, 1-31:\t");
              scanf("%d", &user[i].day);
        }while (user[i].day < 1 || user[i].day > 31);

        do{           
              printf("Please enter the year: \t");
              scanf("%d)", &user[i].year);
        }while (user[i].year < 1);

        printf("\nDate %d entered: %d/%d/%d.\n\n", i+1, user[i].month, user[i].day, user[i].year);

    } 

    if((result=larger(user))==NULL)
        printf("The two dates passed, date1: %d/%d/%d and date2: %d/%d/%d are the same.\n",user[0].month, user[0].day, user[0].year, user[1].month, user[1].day, user[1].year); 
    else
        printf("%d/%d/%d is the later date of the two dates passed\n",result->month, result->day, result->year); 

    return 0;
}

DATES* larger(DATES more[NUM])
{        
      int days0, days1;

      days0 = (more[0].month*31)+(more[0].day)+(more[0].year*365);
      days1 = (more[1].month*31)+(more[1].day)+(more[1].year*365);

      if (days0 > days1)
        return more;        
      else if (days1 > days0)
        return more+1;
      else
        return 0;       
}
于 2013-05-03T04:51:58.633 回答
0

该程序需要进行一些小的更正,但您的主要问题是 while 和 do while 循环之间的区别。

while(<condition>)
{
  //Something
}

do
{
  //Something
}
while(<condition>)

不同之处在于 do while 至少进入循环一次,然后检查是否满足条件。但是另一方面,如果不满足条件,则永远不会进入循环。因此,简而言之,您没有进入 while 循环,因此没有从用户那里读取任何内容。

于 2013-05-03T02:52:41.017 回答
0

你的程序有很多逻辑和句法错误。我纠正了所有的句法部分,必须指出循环逻辑中的主要缺陷。while你似乎很困惑><在以下情况:

while (user[0].month < 1 || user[0].month > 12);  //Wrong

while (user[0].month > 1 || user[0].month < 12);  //Correct

几个月比火星少1或多12,但在地球上,由于污染,它们介于1和之间12。我已经纠正了这些并在评论中指出了这一点。你应该使用for循环而不是对每个元素重复相同的事情数组的DATES

AAAAAGHHH 它充满了错误。这是工作版本。它实现了您在问题中提到的 2 个目标 - 向用户询问 2 个日期,然后找出哪个更大/更晚。我不包括BC,只有AD年。没关系,除非您想知道某个尼安德特人是比我们任何人出生早还是晚。并且​​该函数larger返回一个指向答案的指针,该指针存储在一个新的数据结构中largerdate并打印出来。

以下是修改后的代码的简要说明:

外部for循环自动输入每个日期。没有必要像你一样为每个日期重复相同的代码。如果日期数量增加,这将是乏味的。此外,do-while循环询问用户在指定范围。如果那个混蛋犯了错误,他会被大喊大叫,并且该循环的条件确保混蛋必须再次进入。两个日期存储在一个数组user[]中,类型的基地址DATE*作为参数传递给larger()比较两个日期并返回一个指向较大日期类型的指针的函数。这DATE*用于将较大的日期存储在一个新的数据结构中largerdate,然后打印出来。

#include <stdio.h>
#define NUM 2
struct Dates
{
       int month;
       int day;
       int year;
};
typedef struct Dates DATES;
DATES  *larger(DATES*);
//DATES more;     //Not needed as you are doing the same in function definition

int main(void)
{
    DATES user[NUM],largerdate;
    int i;
     printf("You will enter two dates, and the program will return the larger.\n");
    for(i=0;i<NUM;i++)   //for loop is handy when NUM increases.
       {
           do
           {
        printf("\nPlease enter the month number %d, 1-12:\n ",i);
         scanf("%d", &user[i].month);
         if(user[i].month<1||user[i].month>12)
         printf("I told you enter a number between 1-12 JERK!!\n");
           }while(user[i].month<1||user[i].month>12);
          do
           {
        printf("\nPlease enter the day number %d, 1-31:\n ",i);
         scanf("%d", &user[i].day);
         if(user[i].day<1||user[i].day>31)
         printf("I told you enter a number between 1-31 JERK!!\n");
           }while(user[i].day<1||user[i].day>31);
           do
           {
        printf("\nPlease enter the year number %d,greater than one:\n ",i);
         scanf("%d", &user[i].year);
         if(user[i].year<1)
         printf("I told you enter a number greater than 1 JERK!!\n");
           }while(user[i].year<1);
    printf("\nDate number %d entered is: %d/%d/%d.\n", i+1,user[i].month, user[i].day, user[i].year);

   } //for loop ends.It avoids repeating the same thing for DATES[1]


   largerdate=*larger(user);
   printf("\n\nThe larger/later date is %d/%d/%d\n",largerdate.month,largerdate.day,\
   largerdate.year);


    system("pause");
    return 0;
}

DATES *larger(DATES *more)
{
      int days0;
      int days1;

      days0 = (more[0].month*31)+(more[0].day)+(more[0].year*365);
      days1 = (more[1].month*31)+(more[1].day)+(more[1].year*365);

      if (days1 > days0)
     return more+1;
      else
      return more;
}
于 2013-05-03T03:03:19.147 回答