我的计划打算实现这个目标
(A)编写一个名为larger()
的C函数,它返回传递给它的任何两个日期的较晚日期。例如,如果将日期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]);
}
答案 0 :(得分: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 );
还有一些严重的风格问题会在以后引起麻烦:
DATES larger(DATES[NUM]);
中函数参数的数组类型转换为指针。在该行上,NUM
不执行任何操作,声明与DATES larger( DATES * );
相同。尽管有些教师可能会说,指针和数组并不是一回事。当区别很重要时,这种风格会引起混淆。请改用DATES larger( DATES * )
。
将DATES
大写是没有意义的。 Caps通常表示预处理器宏。
预处理器宏就像一把大锤。将它们用于简单的数字常量不如const int num = 2;
或enum { num = 2 };
input_limit
和user_input
等描述性变量名称将优于num
和user
。
不要依赖未初始化的数据。 user[0].month
定义user
但未初始化后{1}}可能为6。在阅读之前总是写一个值。
大括号应该保持可见。用循环的第一个和最后一个字紧密地分组括号隐藏它们,如果你觉得它们很难看,这很好,但是然后很容易错误地在循环中添加一行,产生难以调试的流控制错误。
答案 1 :(得分:0)
这个程序需要几个小的修正,但你的主要问题是while和while循环之间的区别。
while(<condition>)
{
//Something
}
和
do
{
//Something
}
while(<condition>)
不同之处在于,在进入循环至少一次然后检查要满足的条件时。但另一方面,如果条件不满足,则永远不会进入循环。因此,简而言之,您不会进入while循环,因此不会从用户那里读取任何内容。
答案 2 :(得分: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
循环自动化每个日期的输入。没有必要为每个日期重复相同的代码。如果日期数量增加,那将是乏味的。此外,{ {1}}循环询问用户指定范围内的日期。如果该混蛋发生错误,则他被大喊并且该循环的条件确保该混蛋必须再次输入。两个日期存储在一个数组中do-while
并将类型user[]
的基址作为参数传递给函数DATE*
,该函数比较两个日期并将类型为larger()
的指针返回到较大的日期。这用于将更大的日期存储在名为DATE*
的新数据结构中,然后打印出来。
largerdate
答案 3 :(得分: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;
}
答案 4 :(得分:0)
一半承诺,修改Rüppell's Vulture的answer。这段代码努力避免在另一个答案中重复 - 与问题中的代码相比,这已经减少了。
有多处变化。由于类型仅存储单个日期,因此会重命名为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
我注意到,对于Date
和unsigned char
组件使用uint8_t
(或day
)可以缩小month
结构的大小,以及unsigned short
组件的uint16_t
(或year
)。但是,您必须稍微修改read_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日(但记得曾经有一次30th of February - 在瑞典,在1712年;或者在那里,也许你不需要记住这一点)。