d'hondt verfahren in c



  • Hey, ich soll ein C programm für das d'hondt verfahren schreiben. Ich habe bis jetzt folgendes:

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <string.h>
    
    #define N_PARTEIEN 200
    #define N_SITZE 300
    #define N_STRING 80
    #define N_ZAHL 10
    
    /*
    ** Beschreibung einer H�chstzahl
    */
    typedef struct T_PARTEI* P_PARTEI;
    typedef struct {
      int    nr;     /* Laufende Nummer der H�chstzahl */
      double wert;   /* Wert des Divisors             */
      P_PARTEI partei; /* Laufende Nummer der Partei    */
    } HOECHSTZAHL;
    
    /*
    ** Beschreibung einer Partei
    */
    typedef struct {
      char   name[N_STRING]; /* Name der Partei    */
      int    stimmen;        /* Anzahl der Stimmen */
      int    sitze;          /* Anzahl der Sitze   */
      double prozent;        /* Prozentualer Anteil*/
    } PARTEI;
    
    static int fehler  = 0;
    void fehler (char* text) {
      fprintf (stderr, "Fehler: %s\n", text);
      exit (1);
    }
    /*
    ** Einlesen einer Partei
    ** Partei A;4160
    */
    PARTEI liesPartei (char * zeile) {
      PARTEI partei = {"", 0, 0, 0.0 };
      char zahl[N_ZAHL];
      int i, j;
      for (i = 0; i < N_STRING; i++) {
        if (zeile[i] == ';') {
          partei.name[i] = 0;
          break;
        }
        partei.name[i] = zeile[i];
      }
      if (zeile[i] !=';')
        fehler ("; fehlt");
      for (j=0, i++; i < N_STRING && j < N_ZAHL; i++, j++) {
        zahl[j] = zeile[i];
        if (zeile[i] == 0) {
          break;
        }
      }
      partei.stimmen = atoi (zahl);
      return partei;
    }
    
    /*
    ** Ausgabe einer Partei
    */
    void printPartei (PARTEI p) {
      printf ("Partei %-20s Stimmen=%8d Sitze = %5d Prozent = %3.2lf%%\n", 
        p.name, p.stimmen, p.sitze, p.prozent*100);
    }
    
    /*
    ** Daten
    */
    PARTEI      parteien[N_PARTEIEN];  /* Daten f�r die Parteien */
    HOECHSTZAHL divisoren[N_SITZE+1];  /* Die Divisoren          */
    int anzahlSitze = 0; 
    int anzahlParteien = 0;
    int anzahlStimmen = 0;
    int anzahlHoechstzahlen = 0;
    
    /*
    ** Eingabe aller Daten
    */
    void eingabe (char* name) {
      FILE* f = fopen (name, "r");
    
      while (fgets (zeile, N_STRING-1, f)) {
        PARTEI p = liesParete (zeile);
        printPartei (p);
      }
    }
    
    /*
    ** Ausgabe aller Daten
    */
    void ausgabe () {
      int i = 0;
      printf ("Anzahl der Parteien = %d \n", anzahlParteien);
      for (i = 0; i < anzahlParteien; i++)
        printPartei (parteien[i]);
    }
    
    /*
    ** Berechne die Divisoren.
    ** Fuer jede Partei werden alle Divisoren berechnet
    ** Ein neuer Divisor wird zu den vorhandenen Divisoren hinzugefuegt.
    ** Dadurch koennten (anzahlSitze+1) - Divisoren vorliegen.
    ** Danach werden die Divisoren (anzahlSitze+1) nach ihrem Wert sortiert.
    ** Es werden nur die ersten anzahlSitze-Divisoren beruecksichtigt,
    ** da es nicht mehr Sitze zu verteilen gibt.
    ** Diese Divisoren stehen f�r die Sitze der Parteien
    */
    void berechneDivisoren () {
       //...
    }
    
    /*
    ** Berechne die prozentualen Anteile der Parteien
    */
    void berechneProzent () {
       //...
    }
    
    /*
    ** Berechne die Sitze der Parteien
    ** Die Folge der Divisoren (anzahlHoechstzahlen) wird untersucht. 
    ** Bei jedem Divisor ist angegeben, zu welcher Partei er geh�rt.
    ** Die Anzahl der Sitze der entsprechenden Partei wird erh�ht.
    */
    void berechneSitze () {
       //...
    }
    
    int main (int argc, char* argv[]) {
      char *name = "dhondt-ergebnisse2.txt";
      char zeile [N_STRING];
      if (argc > 1)
      eingabe (name);
      berechneProzent();
      berechneDivisoren ();
      berechneSitze();
      ausgabe ();
      fclose (f);
      return 0;
    }
    

    Die Parteien sollen über eine externe Datei zugeführt werden.
    Ich weiss aber nicht wie ich die Berechnung durchführen soll also hoffe ich auf Hilfe 🙂
    mfg
    cj



  • Wo ist dein Problem mit C?
    Weißt du nicht, wie man mit C rechnet?
    Schreibe dir deine Wunschformeln auf und zumindestens für die 4 Grundrechenarten ist das in C sehr einfach.



  • ich weiss nicht wie ich die höchstzahl ermittle bzw. wie ich einen algorithmus schreibe der dies durchführt. Und die restlichen Berechnungen resultieren daraus. Wenn ich die Rechnung durchführe habe ich für jede Partei eine Zahl in dem jeweilligen array für jeden divisor und ich weiss nicht wie ich die Zahlen dann im folgenden ordne, da ich ja die höchste Zahl der arrays miteinander vergleichen muss um den sitz zu verteilen. Und wenn der Vergleich dann erstellt wäre müsste ich die höchste Zahl die ich für den ersten Sitz erhalten habe eliminieren, damit der Algorithmus wieder durchgeführt werden kann. Aber ich weiss nicht wie ich dies umsetze.



  • Wenn du nur die Höchstzahl bestimmen willst, brauchst du nicht zu sortieren.
    Du schreibst dir eine Funktion, die ein Array mit einer bekannten Anzahl Elemente übergeben bekommt und den Höchstwert zurückliefert, das schreibe ich dir nicht hin, das ist trivial.
    Wenn du sortieren willst, machst du das Gleiche:
    Du schreibst dir eine Funktion, die ein Array mit einer bekannten Anzahl Elemente übergeben bekommt und dann das Array sortiert, z.B. mit qsort aus der Standardbibliothek oder irgendeinem selbstgestrickten Algorithmus. Auch das schreibe ich dir nicht hin, das ist trivial.



  • kann ich die höchstzahl jedes arrays miteinander vergleichen, dann die höchste Zahl 0 setzen und es dann wiederholen nachdem der Sitz verteilt ist?



  • okay ich dachte ich würd allein zurecht kommen aber ich hab überhaupt keine idee mehr wie ich an das problem raangehen soll.
    Bitte kann mir jemand helfen ich muss das Programm am Montag abgeben.
    mfg
    CJ



  • Wenn du nicht weißt, wie man ein Array in C sortiert, dann fehlen dir absolute Grundlagen. Die musst du dir dann eben aneignen, d.h. hinsetzen und lernen.



  • ich weiss wie man ein array sortiert(z.B. mit bubblesort), ich weiss nur nicht wie ich dieses Programm realisieren soll-.-



  • Hast du denn schon Code, der funktioniert? Fang doch schon mal mit der Einlesefunktion an. Du hast zwar eine gepostet, aber funktioniert die auch? Etwas wirr/umständlich sieht das schon aus. Das geht wesentlich einfacher.
    Es wäre hilfreich wenn du eine Funktion schreibst, welche die Parteien mit den erhaltenen Stimmmen einliest und in der Konsole ausgibt.
    Wenn das funzt, gehst du einen Schritt weiter und speicherst diese Daten in Strukturen, als Vorbereitung für die Berechnung, usw.
    Poste doch auch mal das Dateiformat - sind alle Daten in einer Zeile, oder pro Partei eine Zeile, etc.



  • So ich habe die Eingabe jetzt soweit das sie funktioniert und habe jetzt auch einen ansatz zur Berechnung, wobei dieser noch nicht alle Fälle abdeckt.
    Aber ich bekomme nun einen Fehler:
    error C2371: 'berechneSitze': Neudefinition; unterschiedliche Basistypen c:\users\cj\documents\visual studio 2010\projects\einlesen.c\einlesen.c\einlesen.c Zeile:80 1 einlesen.c

    Der komplette Code dazu ist folgender:(Wobei sich der Fehler auf die berechneSitze() bezieht, da seit dem ich diese Funktion eingebaut habe ich denn Fehler bekomme.

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <string.h>
    
    #define N_PARTEIEN 200
    #define N_SITZE 300
    #define N_STRING 80
    #define N_ZAHL 10
    
    typedef struct{
    	char name[N_STRING];
    	int stimmen;
    	int sitze;
    	double prozent;
    }PARTEI;
    
    void printPartei (PARTEI p) {
      printf ("Partei %-20s Stimmen=%8d Sitze = %5d Prozent = %3.2lf%%\n", 
        p.name, p.stimmen, p.sitze, p.prozent*100);
    }
    
    PARTEI liesPartei (char * zeile) {
      PARTEI partei = {"", 0, 0, 0.0 };
      char zahl[N_ZAHL];
      char c = '#';
      int i, o;
      for (i = 0; i < N_STRING; i++) {
        if (zeile[i] == c) {
          partei.name[i] = 0;
          break;
        }
        partei.name[i] = zeile[i];
      }
      if (zeile[i] != c)
    	  printf ("# fehlt");
      for (o=0, i++; i < N_STRING && o < N_ZAHL; i++, o++) {
        zahl[o] = zeile[i];
        if (zeile[i] == 0) {
          break;
        }
      }
      partei.stimmen = atoi (zahl);
      return partei;
    }
    
    	PARTEI partei[N_PARTEIEN];
    	int anzahlSitze = 0;
    	int anzahlParteien = 0;
    	int anzahlStimmen = 0;
    
    void eingabe (char* name)
    {
    	int i = 0;
    	PARTEI p[N_PARTEIEN];
      char zeile[N_STRING];
      FILE* f = fopen (name, "r");
      if (f == NULL) 
        printf("Datei nicht gefunden");
      fscanf (f, "%d\n", &anzahlSitze);
      while (fgets (zeile, N_STRING-1, f))
      {
    	i++;
        p[i] = liesPartei (zeile);
        printPartei (p[i]);
    
      }
      berechneSitze(p);
    }
    
      void ausgabe()
      {
      int i = 0;
      printf ("Anzahl der Parteien = %d \\n", anzahlParteien);
      for (i = 0; i < anzahlParteien; i++)
        printPartei (partei[i]);
    }
    
      void berechneSitze(PARTEI pa[])
      {
    	  int m,j, k, l;
    	for(k = 1; k <= anzahlSitze; k++)
    {		
    	for(m = 1, j = 1;  m < anzahlParteien && j < anzahlParteien;)
    	{
    		if(pa[m].stimmen < pa[j].stimmen)
    		{
    			m++;
    		}
    		else
    		{
    			if(pa[j].stimmen < pa[m].stimmen)
    			{
    				j++;
    			}
    			else
    			{
    				if(pa[m].stimmen == pa[j].stimmen && m == j)
    				{
    					m++;
    				}
    				else
    				{
    					printf("Fehler");
    				}
    			}
    		}
    	}
    		if (pa[m].stimmen < pa[j].stimmen)
    		{
    			pa[j].sitze++;
    			printf("Partei %d hat %d Sitze", j, pa[j].sitze);
    			pa[j].stimmen = pa[j].stimmen/(k + 1);
    
    		}
    		else
    		{
    			if(pa[j].stimmen <= pa[m].stimmen)
    			{
    				pa[m].sitze++;
    				printf("Partei %d hat %d Sitze", m, pa[m].sitze);
    				pa[m].stimmen = pa[m].stimmen/(k + 1);
    
    			}
    
    		}
    	}
    }
    
    int main()
    {
    	char *name = "C:\\Users\\cj\\Desktop\\dhondt-ergebnisse.txt"; 
    	eingabe (name);
    
    }
    

    Das aufgerufene Format ist wie oben genannt .txt.
    Und die txt ist wie folgt aufgebaut:
    Partei A # 1000
    Partei B # 2000
    Name der Partei # Stimmen

    Ich hoffe die Informationen konnten euch helfen hier einblick zu erhalten.



  • ich konnte denn fehler jetzt lösen indem ich die berechneSitze() vor der eigabe() schrieb. Allerdings wird die berechneSitze() jetzt nicht bearbeitet-.- und somit einfch beim debuggen übersprungen



  • Der Funktionsaufruf in Zeile 68 ging schief, weil der Prototyp nicht bekannt war.
    Wenn du am den Anfang des Programms die Funktion deklarierst,

    void berechneSitze(PARTEI pa[]);
    

    dann funzt das.
    Die Funktion berechneSitze wird bestimmt aufgerufen, aber vllt. passiert deshalb nichts weiter weil vllt. anzahlSitze Null ist?



  • ALso das Programm fürht nun die berechneSitze() aus allerdings übernimmt es mir nicht die aus der Datei eingelesenen Dateien in die berechneSitze(). Wie kann ich die eingelesene Partei denn nun in die berechneSitze übergeben?
    Danke wegen der Hilfe bis jetzt:)



  • cjarma schrieb:

    while (fgets (zeile, N_STRING, f))  
      {
        i++;
        p[ i ] = liesPartei (zeile);
        printPartei (p[ i ]);
       
      }
    

    Du solltest i nur dann inkrementieren, wenn ein Datensatz erfolgreich eingelesen wurde, sonst steht da Datenmüll drin.

    Es ist auch gar nicht nötig, dass du anzahlSitze global deklarierst.
    Das gilt auch für die übrigen Variable.
    Du kannst die Anzahl der eingelesenen Datensätze beim Einlesen zählen und dann
    als Parameter übergeben:

    void berechneSitze(PARTEI pa[N_PARTEIEN], int anzahl );
    


  • okay ich habe das Programm jetz soweit zum laufen gebracht und es funktioniert auch, wobei ich noch die Prozentberechnung einbauen muss aber das dürfte kein Problem ergeben. Allerdings bekomme ich jetzt wenn das Programm beendet ist den Fehler: Run-Time Check Failure #2 - Stack around the variable 'p' was corrupted.

    hier nochmal der code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <string.h>
    
    #define N_PARTEIEN 200
    #define N_SITZE 300
    #define N_STRING 80
    #define N_ZAHL 10
    
    typedef struct{
    	char name[N_STRING];
    	int stimmen;
    	int sitze;
    	double prozent;
    }PARTEI;
    
    void printPartei (PARTEI p) {
      printf ("Partei %-20s Stimmen=%8d Sitze = %5d\n", 
        p.name, p.stimmen, p.sitze, p.prozent*100);
    }
    
    PARTEI liesPartei (char * zeile) {
      PARTEI partei = {"", 0, 0, 0.0 };
      char zahl[N_ZAHL];
      char c = '#';
      int i, o;
      for (i = 0; i < N_STRING; i++) {
        if (zeile[i] == c) {
          partei.name[i] = 0;
          break;
        }
        partei.name[i] = zeile[i];
      }
      if (zeile[i] != c)
    	  printf ("# fehlt");
      for (o=0, i++; i < N_STRING && o < N_ZAHL; i++, o++) {
        zahl[o] = zeile[i];
        if (zeile[i] == 0) {
          break;
        }
      }
      partei.stimmen = atoi (zahl);
      return partei;
    }
    
    	PARTEI partei[N_PARTEIEN];
    	int anzahlSitze = 0;
    	int anzahlParteien = 0;
    	int anzahlStimmen = 0;
    
    void ausgabe (PARTEI parteien[]) {
      int i = 0;
      printf ("Anzahl der Parteien = %d \\n", anzahlParteien);
      for (i = 0; i < anzahlParteien; i++)
        printPartei (parteien[i]);
    }
    
    	void berechneSitze(PARTEI pa[])
      {
    	  int a[N_PARTEIEN], b,m,j, k, l, o[N_SITZE], p[N_SITZE], n;
    	  for(n = 0; n <= N_SITZE; n++)
    	  {
    		  o[n] = 0;
    		  p[n] = 0;
    	  }
    	  for(n = 1; n <= anzahlParteien; n++)
    	  {
    		  a[n] = pa[n].stimmen;
    	  }
    	for(k = 1; k <= anzahlSitze; k++)
    {		
    	for(m = 1, j = 1;  m < anzahlParteien && j < anzahlParteien;)
    	{
    		if(pa[m].stimmen < pa[j].stimmen)
    		{
    			m++;
    		}
    		else
    		{
    			if(pa[j].stimmen < pa[m].stimmen)
    			{
    				j++;
    			}
    			else
    			{
    				if(pa[m].stimmen == pa[j].stimmen && m == j && m == anzahlParteien)
    				{
    					break;
    				}
    				else
    				{
    				m++;
    				}
    			}
    		}
    	}
    		if (pa[m].stimmen < pa[j].stimmen)
    		{
    			o[j]++;
    			pa[j].sitze++;
    			m++;
    			printf("%-20s hat %d Sitze\n", pa[j].name, pa[j].sitze);
    			pa[j].stimmen = a[j]/(o[j] + 1);
    
    		}
    		else
    		{
    			if(pa[j].stimmen <= pa[m].stimmen)
    			{
    				p[m]++;
    				pa[m].sitze++;
    				j++;
    				printf("%-20s hat %d Sitze\n", pa[m].name, pa[m].sitze);
    				pa[m].stimmen = a[m]/(p[m] + 1);
    
    			}
    
    		}
    	}
    	printf("Endergebnis:\n");
    	for(n = 1; n <= anzahlParteien; n++)
    	{
    		printf ("Partei %-20s Stimmen=%8d Sitze = %5d\n", 
    			pa[n].name, a[n], pa[n].sitze);
    	}
    }
    
    void eingabe (char* name)
    {
    	int i = 0;
    	PARTEI p[N_PARTEIEN];
      char zeile[N_STRING];
      FILE* f = fopen (name, "r");
      if (f == NULL) 
        printf("Datei nicht gefunden");
      fscanf (f, "%d\n", &anzahlSitze);
      while (fgets (zeile, N_STRING-1, f))
      {
    	anzahlParteien++;
    	i++;
        p[i] = liesPartei (zeile);
        printPartei (p[i]);
    
      }
      berechneSitze(p);
    }
    
    int main()
    {
    	char *name = "C:\\Users\\cj\\Desktop\\dhondt-ergebnisse.txt";
    	printf("Zu verteilende Sitze eingeben:");
    	scanf("%d", &anzahlSitze);
    	eingabe (name);
    
    }
    


  • An manchen Stellen in deinem Code werden Arraygrenzen überschritten.
    Das macht den Stack kaputt.



  • Habs gefunde 😃 war in der schleife die die felder des arrays auf 0 setzt.
    Hey ich wollte mich nochmal für die Hilfe bedanken, du hast mir echt geholfen 😃
    mfg
    cj



  • Okay, was ich aber meine sind Stellen im Code a la

    for(n = 0; n <= N_SITZE; n++)
    

    Das sprengt dir den Stack.
    Ich würde den Code noch vernünftig gliedern von den Einrückungen ganz zu schweigen.
    Und vor allem:
    Die Funktionen rufen sich verkettet gegenseitig auf, das ist stilistisch nicht besonders schön und später auch selbst für den Programmierer schwer lesbar/nachvollziehbar/wartbar.
    Wenn ich das bewerten müsste, würde ich fette Abzüge in der B-Note machen.
    :p


Anmelden zum Antworten