无法使用struct对日期进行排序

时间:2017-03-19 07:47:46

标签: c struct

我试图制作一个程序,对日期列表进行排序,格式为(月份年份,年份是一年中的最后两位数。我的程序应该将年份的日期排序在90到99之间,然后从00到12.我无法正确排序。

例如,如果输入是这样的:

  

1月1日

     

1960年6月30日

     

10月1日

应将其排序为

  

10月1日

     

1月1日

     

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 = 12, 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 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;
}

1 个答案:

答案 0 :(得分:2)

你可能理解这一点:

if (date2->year != date1->year)
    return (date1->year > date2->year) - (date1->year < date2->year);

没有任何意义。

这是你想要的:

int year1 = fix_year( date1->year );
int year2 = fix_year( date2->year );
return year1 - year2;

其中fix_year()如下:

int fix_year( int year )
{
    return (year >= 90? 2000 : 1900) + year;
}

这是另一种说法

int fix_year( int year )
{
    if( year >= 90 )
        return 1900 + year;
    return 2000 + year;
}

请注意,稍后您还必须删除char month[MAXC];成员并将其替换为int month;,因为这些月份的英文名称(以及任何语言的字典顺序排序)地球我愿意猜测)与月份的编号完全没有关系。