Globale Variablen durch Zeiger ersetzen?

2 Antworten

x0: Diese Variable soll wohl die errechnete Nullstelle darstellen. Also definiere doch einfach einen Rückgabetyp für die Funktion und gebe dann das Ergebnis zurück:

double nullstelle (int fn, double a, double b, double g) {
   // ...
   return m;
}

// ... in main double x0 = nullstelle (fn, a, b, g); // ...

ok: Wozu benötigst du diese Variable? In der Funktion nullstelle wird sie zwar am Ende auf 1 gesetzt und in main dann geprüft, doch das ist doch unnötig. Die Funktion nullstelle läuft so und so durch und sollte es zuvor zu einer Endlosschleife kommen, stürzt das Programm eh früher oder später ab.

anzit: An dieser Stelle sehe ich verschiedene Möglichkeiten. Entweder du nutzt wirklich einen Pointer oder du arbeitest bspw. mit einer Structure.

a) Mit Pointer:

void nullstelle (int fn, double a, double b, double g, int *anzit) {
   // ...
   ++(*anzit); // dereference and increment
   // ...

// ... in main
int anzit = 0;
nullstelle (fn, a, b, g, &anzit);
// ...
printf("%d Iteration\n", anzit);

b) Mit Structure (diesmal unter Berücksichtigung von x0):

struct NullstellenStatistik {
   int anzit;
   double x0;
};

NullstellenStatistik nullstelle (int fn, double a, double b, double g) { NullstellenStatistik result; int anzit = 0;
// ... while loop etc
result.x0 = m; result.anzit = anzit;
return result; }

PS.: Deinen Bezeichnern solltest du in Zukunft aussagekräftige Namen geben.

XGreenlanternX 
Fragesteller
 08.12.2017, 15:12

Danke für die Antwort

Ich hatte anschließend noch das Problem, dass er die Iterationsschritte nicht ausgegeben hat.

Hab vergessen erst zu dereferenzieren und dann zu inkrementieren

0
regex9  08.12.2017, 17:03
@XGreenlanternX

Beachte bitte noch den Beitrag von TeeTier bezüglich const correctness. Darauf bin ich in meiner Antwort nicht eingegangen.

0

Erst mal vorweg: Füge deine Quelltexte in Zukunft lieber bei Pastebin ein, und kopiere einfach den Link in deine Frage:

https://pastebin.com/

Das ist kostenlos und funktioniert ohne Registrierung. :)

Der Quelltexteditor hier auf GF ist ziemlich verbuggt, und die neue Version noch nicht für alle Nutzer freigeschaltet, also geht es vorläufig nur mit diesem Workaround, falls der Quelltext anschließend auch noch lesbar sein soll.

Zu deiner Frage: Ja, globale Variablen sind äußerst unschön und es ist sehr vorbildlich, dass du darauf verzichten möchtest! Zumal sie in deinem Falle wirklich nicht benötigt werden.

Im Grunde genommen musst du deine Funktion nur so definieren, dass sie einen Zeiger erwartet, und innerhalb der Funktion musst du den Zeiger mit vorangestelltem Sternchen "dereferenzieren", um auf den gezeigten Wert zugreifen zu können:

void func(double * const num) {
*num = 123.456;
}

Innerhalb deines Programms kannst du dann lokale Variablen, bzw. deren Adresse, wie folgt übergeben:

double value = 0.0;

func(&value);

Danach hat "value" den Wert "123.456". Ich denke, daraus kannst du dir selber ableiten, wie du deinen eigenen Quelltext so umbauen kannst, dass er ohne globale Variablen auskommt.

Noch eine kleine Anmerkung zum const-Schlüsselwort: Damit werden dem Compiler unter der Haube wirklich viele Optimierungen ermöglicht, also solltest du immer und überall alles als const Deklarieren, was nur irgendwie geht. Dabei gibt es bei einem Zeiger-Parameter folgende Möglichkeiten, die sich stark unterscheiden:

/* 1 */ void func(double * num);
/* 2 */ void func(double * const num);
/* 3 */ void func(double const * num);
/* 4 */ void func(double const * const num);
Es hilft oft sehr, wenn du den ganzen Klumpatsch von Rechts (!) nach Links (!) liest:
  1. "num" ist ein "Zeiger" auf einen "double" (dem Zeiger kann innerhalb der Funktion eine neue Adresse zugewiesen werden; der Variablen dahinter kann ebenfalls ein neuer Wert zugewiesen werden)
  2. "num" ist ein "konstanter" "Zeiger" auf einen "double" (dem Zeiger kann innerhalb der Funktion KEINE neue Adresse zugewiesen werden; der Variablen dahinter aber schon ein neuer Wert)
  3. "num" ist ein "Zeiger" auf einen "konstanten" "double" (dem Zeiger kann innerhalb der Funktion eine neue Adresse zugewiesen werden; der Variablen dahinter aber KEIN neuer Wert)
  4. "num" ist ein "konstanter" "Zeiger" auf einen "konstanten" "double" (WEDER kann dem Zeiger eine neue Adresse, NOCH der Variablen dahinter ein neuer Wert zugewiesen werden)

Warum es diese Unterscheidungen gibt, und warum man darauf achten sollte, muss dich jetzt vielleicht noch nicht interessieren. Merk dir einfach, dass alles const sein sollte, was const sein kann.

In deinem Code willst du ja ein Ergebnis über einen Zeiger zurück liefern, also muss der Zeiger an sich nicht veränderbar sein, der Wert dahinter aber schon.

Naja, viel Spaß noch! :)

PS: Wenn bei einem Konstrukt wie oben ein "const" VOR dem Variablentyp steht, ist das das gleiche, als ob "const" NACH dem Variablentyp steht. Beispiel:

/* 4 */ void func(double const * const num);
/* 5 */ void func(const double * const num);

Beide Varianten sind komplett gleichwertig. Welche du bevorzugst hängt von deiner persönlichen Präferenz ab. Bei 4 liest du von Rechts nach Links einfach "konstanter Double" und bei 5 "double Konstante".

PPS: Und die Kommentar haben Null Mehrwert. Sinnlose Kommentare solltest du dir unbedingt verkneifen! Das sind nur nutzlose Fehlerquellen! :)