// Übung für Strukturen: Sortierte Klassenliste
//
// Aufruf: struct
//
// Klaus Kusche, 2012

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

// Arraygröße des Struct-Arrays = max. Anzahl von Schülern
#define MAX_SCHUELER  50
// Max. Länge des Namens in der Struct
#define MAX_NAMELEN 31

struct schueler {
  char name[MAX_NAMELEN + 1];     // + 1 für Ende-Markierung
  int nr;
  float note;                     // float = double mit weniger Genauigkeit
};

int main(void)
{
  struct schueler klasse[MAX_SCHUELER];  // unser Struct-Array namens "klasse"
  int anzahl;           // tatsächliche Anzahl der Schüler

  // Einlesen
  for (anzahl = 0; ; ++anzahl) {
    if (anzahl >= MAX_SCHUELER) {
      printf("Max. Anzahl von Schülern (%d) erreicht!", MAX_SCHUELER);
      break;
    }
    printf("Matrikelnummer (0 für Ende)? ");
    // scanf bekommt die Adresse des Members "nr" der Schülers Nummer anzahl
    scanf("%d", &(klasse[anzahl].nr));
    if (klasse[anzahl].nr <= 0) break;  // Eingabe-Ende
    printf("Name? ");
    // 1.) Bei scanf wird auch bei %s immer nur *ein* Wort gelesen
    //     Es kann daher nicht Vorname + Nachname eingetippt werden!
    // 2.) Auch innerhalb einer Struct gilt:
    //     Ein Array-Member ohne [] dahinter liefert einen Pointer auf das Array
    //     ==> Das Member name ist ein Array, hier ist *kein* & notwendig!
    scanf("%s", klasse[anzahl].name);
    printf("Note? ");
    scanf("%g", &(klasse[anzahl].note));
  }

  // Sortieren
  for (int n = anzahl - 1; n > 0; --n) {
    for (int i = 0; i < n; ++i) {
      if (klasse[i].note > klasse[i + 1].note) {
        struct schueler tmp;  // eine einzelne Struct
        // Kopiert 3 Mal eine ganze Struktur!
        tmp = klasse[i + 1];
        klasse[i + 1] = klasse[i];
        klasse[i] = tmp;
      }
    }
  }

  // Ausgabe
// Variante mit Index
//  for (i = 0; i < anzahl; ++i) {
//    printf("%2d: Name: %-32s Nr: %09d Note: %3.1f\n",
//           i + 1, klasse[i].name, klasse[i].nr, klasse[i].note);
//  }

// Variante mit Pointer
// statt "p < klasse + anzahl" funktioniert auch "p < &(klasse[anzahl])"
  for (struct schueler *p = klasse; p < klasse + anzahl; ++p) {  
    printf("%2d: Name: %-32s Nr: %09d Note: %3.1f\n",
           // die Differenz zweier Pointer kann int, long oder longlong sein
           // ==> zur Sicherheit Typumwandlung auf int
           ((int)(p - klasse)) + 1, p->name, p->nr, p->note);
  }

  exit(EXIT_SUCCESS);
}
