Jose Luis
Jose Luis

Reputation: 3

How to sort dates from an array in c

I'm trying to sort dates from an array i've got the following code (without including the array and the file that i'm trying to read and the other with the sorted dates that i'm trying to write.

int aniomayor=tot[0].anio;
int diamayor=tot[0].dia;
int mesmayor=tot[0].mes;

while (i<nf) {
  if (tot[i].anio > aniomayor) {
    int aniomayor=tot[i].anio;
    int diamayor=tot[i].dia;
    int mesmayor=tot[i].mes;
  }
  else if (tot[i].anio == aniomayor && tot[i].mes > mesmayor) {
    int aniomayor=tot[i].anio;
    int diamayor=tot[i].dia;
    int mesmayor=tot[i].mes;
  }
  else if (tot[i].anio == aniomayor && tot[i].mes == mesmayor &&  tot[i].dia > diamayor) {
    int aniomayor=tot[i].anio;
    int diamayor=tot[i].dia;
    int mesmayor=tot[i].mes;
  }

  i++;
}

fprintf(f, "%s ", diamayor);
fprintf(f, "%s ", mesmayor);
fprintf(f, "%s \n", aniomayor);

I think it would work but in the 2,3,4.. line it will print always the same date and i don't know how to do for it to ignore the dates that already had been sorted. Thanks in advance.

Upvotes: 0

Views: 1389

Answers (2)

Neil
Neil

Reputation: 1922

As has been mentioned in the comments, it is preferable to use qsort, (if one doesn't care about stability.) One needs a function pointer, which is compare_dates in the code below.

#include <stdlib.h> /* EXIT*, rand, qsort */
#include <stdio.h>  /* *printf */
#include <time.h>   /* clock */
#include <assert.h> /* assert */

struct Date { int anio, mes, dia; };

/** Random [i, j]. https://stackoverflow.com/a/6852396/2472827
 This is just used for test purposes. */
static int rand_range(const int i, const int j) {
    const unsigned long max = (unsigned long)j - i,
        num_bins = max + 1l,
        num_rand = (unsigned long)RAND_MAX + 1,
        bin_size = num_rand / num_bins,
        defect   = num_rand % num_bins;
    unsigned long x;
    assert(i <= j && num_bins <= RAND_MAX);
    do { x = 1l * rand(); } while (num_rand - defect <= x);
    return i + x / bin_size;
}

/** Initiaises the date with random. */
static void init_date(struct Date *const date) {
    assert(date);
    date->anio = rand_range(1950, 2050);
    date->mes  = rand_range(1, 12);
    date->dia  = rand_range(1, 30); /* Approximately. */
}

/** Prints the date in a static string.
 Assumes the date is sanitised, or else this presents a risk of overflow. */
static const char *print_date(const struct Date *const date) {
    static char print[128]; /* Should be 11 if -999 <= year < 9999. */
    assert(date);
    sprintf(print, "%4.4d-%2.2d-%2.2d", date->anio, date->mes, date->dia);
    return print;
}

/** The arguments must be const struct Date *.
 @return -, =, + */
static int compare_dates(const void *p, const void *q) {
    const struct Date *x = (const struct Date *)p, *y = (const struct Date *)q;
    assert(p && q);
    if(x->anio > y->anio) return 1;
    if(x->anio < y->anio) return -1;
    if(x->mes  > y->mes)  return 1;
    if(x->mes  < y->mes)  return -1;
    if(x->dia  > y->dia)  return 1;
    if(x->dia  < y->dia)  return -1;
    return 0;
}

int main(void) {
    struct Date dates[64];
    const size_t dates_size = sizeof dates / sizeof *dates;
    size_t i;

    /* Generate dates. */
    srand((unsigned)clock());
    for(i = 0; i < dates_size; i++) init_date(dates + i);
    /* Sort it using compare_dates. */
    qsort(dates, dates_size, sizeof *dates, &compare_dates);
    /* Print. */
    for(i = 0; i < dates_size; i++) printf("%s.\n", print_date(dates + i));

    return EXIT_SUCCESS;
}

See How to generate a random integer number from within a range.

Upvotes: 0

tadman
tadman

Reputation: 211580

The original int declaration establishes variables. The subsequent ones create "shadow" variables that have the same name but are not the same variable.

Here's a demonstration:

#include <stdio.h>

int main() {
  int x = 1;

  if (x == 1) {
    int x = 2;
    printf("x=%d\n", x);
  }

  printf("x=%d\n", x);

  return 0;
}

This prints:

x=2
x=1

The top-level x never gets modified, so it appears to revert to the original value.

You should remove the int prefix from those, just assign to the existing variable.

When you say int x = y; in C you are declaring a variable and assigning a value. To assign to an existing variable x = y; is sufficient.

The int prefix is only necessary on the first instance of the variable so the compiler knows what type to use for that and all subsequent references inside the same scope.

Now normally the compiler would complain about creating another variable with the same name if it's done in the same scope. In your case because you're doing it inside an if, technically that's a different scope so you can have duplicates.

Upvotes: 5

Related Questions