Werte innerhalb Funktion über ganze Laufzeit speichern

3FJack

Grünschnabel
Hallo,

ich habe die Aufgabe, ein Programm in C umzusetzen welches über folgende main-Funktion mehrere Paramteter übergibt, innerhalb der Funktion den Primfaktor der Zahl ermittelt und anschließend an die main-Funktion zurückgibt bis alle Primfaktoren ausgegeben wurden.

Die main-Funktion muss folgendermaßen aussehen:

Code:
int main() {
    
    int pf;
    
    while (( pf = primfaktor (12)) > 1)
        printf("%d\n", pf);
    while (( pf = primfaktor (7)) > 1)
        printf("%d\n", pf);
    printf ("%d\n",primfaktor (1));
}

Ausgabe komplett:

2
2
3
7
usw.

Jedoch habe ich Probleme die Funktion unter den folgenden Rahmenbedingungen umzusetzen:

- keine globalen Variablen
- innerhalb der Funktion keine Ein- und Ausgabe erlaubt
- die Kommunikation muss über die Schnittstelle erfolgen

Wenn von der als Paramter übergebenen Zahl 12 die Zahl 2 als erster Primfaktor zurückgegeben wird hängt das Programm in einer Dauerschleife, da ich keine Möglichkeit sehe den Wert des Primfaktors und des Quotienten zu speichern. Außerdem ist die Funktion nicht rekursiv.

Ich hoffe jemand kann mir einen kleinen Tipp geben der mich meinem Ziel näher bringt.

Danke!
 
Zuletzt bearbeitet:
Hi und Willkommen bei tutorials.de,

die Aufgabe zwingt einen praktisch dazu, Sachen zu machen,
die hier zwar gut gehen, aber bei größeren Programmen Probleme machen...naja

Lösung: static

Innerhalb der Funktion eine Variable so machen:
C:
static int bla = 0;
(mit einem Wert. ggf. anderer als 0, aber nicht ohne)

Die Art von Variable behält ihren Wert wie globale Variablen
über die Funktionsaufrufe hinweg dauerhaft,
kann aber nicht wie eine globale Variable von überall aus verwendet werden
(nur innerhalb der Funktion).
Gleichnamige Variablen anderswo sind damit kein Problem (bei glob.Vars wäre es eins).
Die 0 (etc.) ist der Startwert ganz am Anfang, beim ersten Funktionsaufruf.
 
Hi,

vielen Dank für die schnelle Antwort.

Mit static hab ich es als erstes Versucht und bin gescheitert : ) da Du mich nochmal explizit darauf hingewiesen hast, werde ich es damit nochmal probieren.

Anbei der bisherige Code. Es ist zwar nicht der effizienteste Algorithmus zur Primfaktorzerlegung, aber er funktioniert und ist kompakt. Hoffentlich geht mir da noch ein Licht auf.



Über Tipps würde ich mich sehr freuen, aber bitte nichts fertiges posten : )
 
Zuletzt bearbeitet:
Was die Sache vereinfachen könnte:
Mach dir eine eigene Funktion getNextPrim oder so,
die zu einer gegebenen Zahl eben die nächsthöhere Primzahl sucht.

Zu den Variablen der Hauptfunktion:
Für was werden sie gebraucht...
a) Zwischenspeichern der Zahl und des zuletzt bearbeiteten Teilers
b) Erkennen, wenn man einen neue, andere Zahl übergibt
Wenn man zB. die Primfaktoren von 24 will: 2, 2 bei den ersten zwei Aufrufen.
Und dann ruft man die Funktion aber mit 98 auf -> 24 vergessen und bei 98 neu beginnen.
(auch 98 würde 2 2 an den ersten beiden Stellen haben,
aber die müssen wieder ausgegeben werden).
Dazu muss man sich auch die ursprüngliche, ungeteilte Zahl speichern

Wenn man es so macht fehlt bei dir schon eine Variable.
Annahme: pruefzahl ist die aktuelle geteilte Zahl und ein neues origzahl ist das Original.

Was noch zu beachten ist:
Wenn man einmal eine Zahl fertigzerlegt hat (1 wurde einmal zurückgegeben)
kann man die Funktion mit einer anderen Ausgangszahl wieder verwenden,
oder auch einzweites Mal mit der Gleichen.
Steht zwar vermutlich nicht ausdrücklich in der Angabe,
aber da sollte meiner Meinung nach wieder von vorn begonnen werden
(obwohl die übergebene Zahl == gemerkte Zahl)


Um mit den Variablenstartwerten zu beginnen:
teiler=2 schaut gut aus, aber was ist pruefzahl.
Negative Zahlen und Null sind zum Zerlegen nicht erlaubt, also als ungültigen Startwert zB 0
origzahl auch 0
Wenn dann die übergebenezahl != origzahl:
Neue Zerlegungskette hat begonnen:
pruefzahl=übergebenezahl und origzahl=übergebenezahl

Und egal, ob es von falschen übergebenen Werten oder sonst wo kommt:
Wenn pruefzahl dann <1 ist: Fehler
(wie du auf -2 als Returnwert kommst kA., 0 würde es auch tun. egal)


Und um den andersseitigen Sonderfall auch gleich zu behandeln:
Wenn pruefzahl 1 ist (1 übergeben oder das Ende einer Zerlegungskette)
ist der Faktor zum Zurückgeben ja 1.
Aber dann will man die gleiche Originalzahl ggf. wieder zerlegen lassen,
und der Vergleich oben würde nicht merken, dass die prüfzahl wieder
auf die volle Originalzahl gesetzt werden muss:
Deshalb alle drei Variablen teiler,pruefzahl, origzahl wieder auf ihre
programmweiten Startwerte 2,0,0 setzen (und return 1)


Das war der umständliche Teil :D
Was jetzt noch zu tun ist:
Wenn die pruefzahl durch teiler teilbar ist: Durchdividieren und teiler zurückgeben. Klar.
Sonst solange teiler auf eine nächste Primzahl setzen, bis teilbar,
und dann dividieren und teiler zurückgeben.
 
Hi,

vielen Danke nochmal für die Mühe. Ich habe das Programm fertig bekommen.

Ich habe keine weitere Funktion verwendet, jedoch ist der Code dadurch sehr
unübersichtlich geworden.

Den Code aus dem vorherigem Post habe ich gelöscht, da dieses Programm
auf Plagiat etc. geprüft wird und einer meiner Kommilitonen schon
darauf gestoßen ist : )

Sobald ich mein Ergebnis bekommen habe werde ich die Primfaktorzerlegung
und die Schnittstelle mit Primfaktorzerlegung hier posten und den Post als
erledigt markieren.

Danke!
 
Den Code aus dem vorherigem Post habe ich gelöscht, da dieses Programm
auf Plagiat etc. geprüft wird und einer meiner Kommilitonen schon
darauf gestoßen ist : )

Solange du eine Lösung gefunden hast, ist das ja ganz ok. :)

Aber auch wenn es fast unedlich viele Möglichkeiten gibt ein Problem zu lösen, ist es sehr gut möglich, dass Leute dieselbe Idee haben, eben weil manche Lösungen einfach gut sind und manche ungünstig. Die Leute gucken dabei in der Regel eher auf 1:1 Copy&Paste. Ich will dir jetzt nicht raten das nächste mal einfach Variablennamen umzubenennen und auf gut Glück, merkt schon keiner. :rolleyes:

Allerdings, wenn du deinen Quellcode kommentierst, ihn verstanden hast und ggf. an einer Stelle, wo du einen Algorithmus von z.B. Wikipedia genutzt hast einfach den Link mit hinzufügst, dann wird das auch ok sein. Zumal man ja merkt, dass sich and er Stelle jemand Gedanken gemacht hat.

Das nur ganz am Rande.

Schönen Abend noch,
Jennesta
 
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int primfaktor(int n)
{
  int i;

  while (n%2 == 0)
  {
  printf("%d", 2);
  n = n/2;
  }

 
  for (i = 3; i <= sqrt(n); i = i+2)
  {

  while (n%i == 0)
  {
  printf("%d", i);
  n = n/i;
  }
  }

  if (n > 2)
  printf ("%d", n);
}
int main()
{
  int pf;
  
  while ((pf = primfaktor (12))> 1)
  printf ("%d\n", pf);
  while ((pf = primfaktor(7)) > 1)
  printf ("%d\n", pf);
  printf ("%d\n" , primfaktor (1));
  return 0;
  
}

Könnte der Code vielleicht so aussehen? Und wie gehts das mit der Fehlermeldung -2 ?
 
Im main werden schon alle Primfaktoren ausgegeben, weitere printf in der Funktion sind falsch.
Lies doch einmal zumindest das , was hier schon angesprochen wurde, um das zu lösen

Und welche "Fehlermeldung -2"?
 
Zurück