我的程序以(月日)的格式列出日期列表。然后它按照最近事件的时间顺序对其进行排序。它应该将年份从90到99,然后从00到12排序。例如,它应该对此列表进行排序。
1月1日
1月1日
99年2月28日
7月17日12日
9月10日12日
7月1日
1960年6月30日
2006年8月25日
2008年5月27日
10月1日
进入这个。
9月10日12日
7月17日12日
2008年5月27日
2006年8月25日
10月1日
1月1日
7月1日
1月1日
99年2月28日
1960年6月30日
但是我似乎无法正常工作。
#include <stdio.h>
#include <stdlib.h>
/* constants for max chars, max day, max year, max size */
enum { MAXC = 12, MAX_DAY = 31, MAX_YEAR = 2017, MAX_SIZE = 1000 };
typedef struct {
char month[MAXC]; /* either make static or allocate separately */
unsigned day;
unsigned year;
} date;
/* empty character remaining in stdin */
void empty_stdin ()
{
int c;
while ((c = getchar ()) != '\n' && c != EOF) {}
}
/* sort struct date on year */
int sort (const void *a, const void *b)
{
date *date1 = (date *) a;
date *date2 = (date *) b;
if (date2->year != date1->year)
return (date1->year < date2->year) - (date1->year > date2->year);
return (date1->year < date2->year) - (date1->year > date2->year);
return 0;
}
/* output n elements of array of struct date */
void output (date *ar, int n)
{
int i;
printf ("\nOutput sorted by year:\n\n");
for (i = 0; i < n; i++)
printf (" %s %d %d\n", ar[i].month, ar[i].day, ar[i].year);
}
int main (void) {
int i, n;
date *ar = NULL;
while (1) { /* obtain valid 'n', compare with using fgets below */
int rtn; /* varaible to save return of scanf -- always validate */
//printf ("Enter number of dates to be entered (between 1 & 1000): ");
if ((rtn = scanf ("%d", &n)) != 1) { /* if conversion failed */
if (rtn == EOF) { /* test for user cancelation of input */
fprintf (stderr, "note: user canceled input, exiting.\n");
return 0;
} /* otherwise simply an invalid input */
fprintf (stderr, "error: invalid input.\n");
goto tryagain;
}
if (n < 0) { /* invalid input < 0 */
fprintf (stderr, "error: invalid input (n < 0).\n");
goto tryagain;
}
if (n > MAX_SIZE) { /* invalid input > MAX_SIZE */
fprintf (stderr, "error: invalid input (n > %d).\n", MAX_SIZE);
goto tryagain;
}
break; /* if we are here - we have a good value, break */
tryagain:; /* label for goto to jump over break */
empty_stdin (); /* empty characters that remain in input buffer */
}
empty_stdin (); /* empty characters that remain in input buffer */
/* allocate array of struct ar, n elements */
if ((ar = malloc (sizeof *ar * n)) == NULL) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
/* provide format instructions */
//printf ("Enter the date month day year\n"
// " format, e.g.: Jan 18 2017\n\n");
for (i = 0; i < n;) { /* loop until all elements filled */
char buf[MAX_DAY + 1] = "", ans[MAXC] = "";
//printf (" date[%2d] : ", i + 1); /* prompt for input */
/* if fgets return is NULL, EOF encountered */
if (fgets (buf, MAX_DAY + 1, stdin) == NULL) {
fprintf (stderr, "note: user canceled input, exiting.\n");
return 0;
}
if (*buf == '\n') { /* if first char is '\n', user just hit enter */
printf ("no input provided, quit (y/n)? ");
if (fgets (ans, MAXC, stdin) && (*ans == 'y' || *ans == 'Y'))
return 0;
else if (!*ans) { /* if ans NULL, EOF encountered */
fprintf (stderr, "note: user canceled input, exiting.\n");
return 0;
}
}
/* parse with sscanf, validate 3 conversion took place */
if (sscanf (buf, "%11s %u %u", ar[i].month, &ar[i].day, &ar[i].year) != 3)
{
fprintf (stderr, "error: invalid input.\n");
continue;
}
i++; /* only increment if valid sscanf conversion took place */
}
qsort (ar, n, sizeof (date), sort); /* sort by year */
output (ar, n); /* output results */
free (ar); /* free ar - you allocate it, you free it */
return 0;
}
答案 0 :(得分:1)
最简单的解决方案可能是在您阅读之后修复一年(然后在打印时将其转换为易于出现Y2K的代码,如有必要)。
unsigned yy;
... sscanf (buf, "%11s %u %u", ar[i].month, &ar[i].day, &yy) ...
ar[i].year = yy >= 90 ? 1900 + yy : 2000 + yy
您必须根据您打算使用的实际截止值调整90
。
您可以类似地将月份转换为整数。或者你甚至可以将输入翻译成类似朱利安日的东西,从而使得排序变得微不足道,但输出稍微复杂一些。如果您有很多日期可以排序,那么简化排序是一种胜利。
答案 1 :(得分:-1)
就像Chrono Kitsune所说的那样,大概在1900年代的日期似乎比你在sort
函数中的日期要大于2000年代的日期。
e.g。 1999年1月1日似乎大于2017年1月1日,当时是99年1月1日和1月17日
最简单的修复IMO是告诉用户输入(并且只接受)整年,而不仅仅是最后两位数。
编辑(根据OP的评论):测试年份是否在90到99或00和12之间,然后相应地添加。
这基本上只是里奇所回答的一个更详细的版本。
...
/* parse with sscanf, validate 3 conversion took place */
if (sscanf (buf, "%11s %u %u", ar[i].month, &ar[i].day, &ar[i].year) != 3)
{
fprintf (stderr, "error: invalid input.\n");
continue;
}
else
{
// add 1900 if the year is 90 or greater
if(ar[i].year >= 90)
ar[i].year += 1900;
// add 2000 if the year is 12 or less
else if(ar[i].year <= 12)
ar[i].year += 2000;
}
...