Anfänger Fragen

Thomasio

Erfahrenes Mitglied
Hallo an alle,

schon wieder ich, auch wenn noch kein halbes Jahr rum ist, dafür ist die Frage vermutlich wirklich dumm

Nach allem was ich so gelesen habe, soll man keine globalen Variablem verwenden, um gleiche Variablennamen in verschiedenen Funktionen verwenden zu können

Sämtliche Beispiele in Anfängertutorials sind natürlich auch immer so geschrieben, dass es ohne globals geht, aber immer wenn ich versuche einen Schritt weiter zu denken um meinen Lernfortschritt aus den Lektionen zu prüfen komme ich wieder ans gleiche Problem
Ich tendiere nahezu automatisch dazu globals zu verwenden, weils einfach praktisch ist und ich es von php her gewohnt bin, nur ist der ganze Aufbau von C (und erst recht bei C++) auf die Verwendung von lokalen Variablen ausgelegt, so dass ich immer gleich daran erinnert werde doch lieber keine globals zu verwenden
Der Sinn der Sache ist mir durchaus klar, nur bleiben mir da einige Fragen offen

1) Wenn ich zum Beispiel eine Datei habe in der Konstanten für verschiedene Funktionen gespeichert sind, etwa eine Liste mit Namen oder sowas, dann muss ich ohne globals jedesmal wenn ich in einer Funktion einen Namen aus der Liste brauche die Datei neu einlesen, strings splitten usw, bis ich den gesuchten Namen gefunden habe
Klar, dazu schreibe ich eine subroutine, die das ausliest, im code also schön kurz und übersichtlich, aber für den Rechner eine Unmenge an Lesezugriffen auf die Festplatte, während ein globales array hier bei Programmstart einfach alle Namen lesen könnte und ab sofort allen Funktionen die Liste zur Verfügung steht
Sinn also klar, aber kann mir einer erklären, wie ich später mal, wenn ich grosse Anwendungen schreibe, vermeide, dass die Geschwindigkeit in die Knie geht?
Lies 1000 mal die gleiche Datei, nur damit ich keine globals verwenden muss macht bei allem Verständnis für Vermeidung von Bugs für mich irgendwie trotzdem keinen Sinn

2) Was mir absolut nicht in den Kopf will, egal wie oft ich es nochmal lese ist die Sache mit dem Austausch von Variablen beim Aufruf einer Funktion
Scheint auch in Verbindung mit meiner php Vorbelastung zu stehen, bzw auch dabei will ich ständig globals verwenden, weil ich nicht kapiere, wie rum da nun Variablen bzw deren Werte übergeben werden und welche Variable überhaupt an welcher Stelle zur Verfügung steht, bzw. wie ich an den Wert einer Variablen komme, die nicht innerhalb der Funktion definiert wurde und auch nicht global ist
Ich weiss nicht mal ob ich das Problem verständlich erklären kann, bis jetzt probiere ich unglaublich viel herum, wenn ich etwas nicht weiss, dann nach dem Motto Versuch macht klug, aber ich würde zu gerne den Vorgang dahinter verstehen, damit ich nicht jedesmal bei der kleinsten Änderung im Script wieder ausprobieren muss, ob der Wert meiner Variablen denn noch gültig ist, bzw noch darauf zugegriffen werden kann, nachdem ich zwischen Erstellen der Variablen und nächster Verwendung ein paar [{}] verwendet habe, oder wissen muss ob meine nächste Funktion die Variable überhaupt kennt

3) Falls die ersten 2 noch nicht dumm genug waren, richtig dämlich stelle ich mich an, wenn ich in jeder zweiten Zeile etwas von memory leaks und deren Vermeidung lese, das wird in sämtlichen Kursen derartig oft wiederholt, da passe ich ganz fein auf, dass ich mir das von Anfang an richtig angewöhne, nur begreife ich nicht, was ich wann wie löschen befreien oder sonstwas damit machen muss
char buffer[50]
free(buffer)
Klar, das kann ich mir überall nachlesen, nur sagt mir keiner dazu, was macht denn "free"? Leert den buffer? Oder löscht ihn ganz?
Was ist mit Variablen? Wenn eine Variable definiert wird
int i = 1
und dies innerhalb einer Funktion 1000 mal läuft, habe ich dann nicht 1000 i´s alle mit dem gleichen Wert, muss ich die nach Gebrauch nicht wieder löschen, oder was?
Gerade im Moment hänge ich bei einem mehrdimensionalen array
char buffer[10][10][10]
Was ich damit machen kann ist mir klar, aber ob ich da auch
free(buffer)
verwenden kann? Keine Ahnung! Steht auch im Tutorial nicht dabei, ist auch nicht besonders wichtig in Übungen die kaum mal mehr als 2 Funktionen haben und nur 2 oder 3 mal durchlaufen, aber wenn schon, dann will ich das von Anfang an so machen, dass ich später weiss wie es geht

4) Komplett im Wald stehe ich dann, wenn es um verschiedene Typen, oder nur verschiedene Schreibweisen des gleichen Typs geht
char buffer
char* buffer
char buffer[10]
char buffer[]
char buffer*
da fassen sich selbst die einfachsten Anfänger Tutorials derartig kurz, dass ich mir einfach keine Eselsbrücke bauen kann, mit der ich mir mal merken könnte, was denn nun was bedeutet, da schlage ich 100 mal am Tag nach, jedesmal wenn in einer Übung sowas auftaucht (und wenn ich mal nicht nachschlage, dann bekomme ich unter garantie eine fehlermeldung ala invalid conversion) selbst das Video "Thinking in C" von Bruce Eckel sagt dazu sinngemäss soviel wie "da wollen wir jetzt gar nicht so tief einsteigen", aber bitte wie soll ich es denn begreifen, wenn es nicht mal in den einfachsten Anfängertutorials beschrieben wird

Ich wäre dankbar wenn jemand mir mal diese Grundbegriffe für ganz Dumme erklären könnte
 
Zum einen, Respekt für die doch recht ausführlich beschriebenen Problemchen eines Programmierers.

Für eigentlich alle deine Probleme im Gesamten wurden in jahrzehntelanger Arbeit verschiedene Softwareentwicklungsmethoden erfunden, um die eigenen Anforderungen in Quellcode zu übersetzen. Also sind deine Fragen nicht einfach zu beantworten.

Du hast Dich jetzt dafür entschieden, den Zweig einzuschlagen, bei dem dem Entwickler eine sehr mächtige, recht allgemeingehaltene aber doch komplizierte Sprache benutzen kann um Software zu bauen.

Da ich eigentlich nicht denke, dass Du in naher Zukunft Software für die integrierte Linuxarchitektur oder embeddete Systeme entwickeln wirst möchte ich Dir vorschlagen Dich auf C++ zu beschränken.
Zwar sind C und C++ Artverwand und sehr Syntax-gleich aber doch in dem Vorgehen grundverschieden.

Man kapselt zusammengehörige Funktionalitäten in Klassen, um so die Neu- und Weiterentwicklung von Software auf kleine Teilbereiche zu verteilen. Ausserdem gibt es die Möglichkeit mit private/public/protected jedem Entwickler zu zeigen, welche Funktionalitäten überhaupt ausserhalb der Klasse zur Verfügung stehen.

zu 1.)
zu Deinem Beispiel mit der Konfigurationsdatei. Eine Klasse, die das Verarbeiten und Einstellungen übernimmt wäre da am sinnvollsten.
Dort wird das Laden der Werte in klasseneigene Membervariablen, das Zurück-Speichern und das zur Verfügungstellen geregelt. Ist es zum Beispiel nicht sinnvoll eine Einstellung aus dem Programm heraus verändern zu dürfen, wird die set-Methode für die Membervariable (diese sind im Normalfall alle private!) einfach private gemacht. So kann man diese Einstellung dann z.B. nur auslesen.
Wo Du diese Klasse dann speicherst kommt halt darauf an, wie und wo du die Einstellungen benötigst.

zu 2.)
die Reihenfolge von Variablen in Funktionsaufrufen kann man in eigentlich jeder guten IDE (Visual Studio , Eclipse, DevCPP) als Tooltip beim programmieren sehen, das stellt heutzutage eigentlich keine Hürde mehr da, solange man die Variablennamen im Funktionskopf sprechend und eindeutig wählt. Auch die Sichtbarkeit von Variablen kann man damit sehr gut überprüfen.

zu 3.)
In C++ ist das Problem der MemoryLeaks deutlich geringer als noch in C.
Jede Klasse hat einen Konstruktor und Destruktor, der beim Erstellen bzw. dem Zerstören einer Klasse aufgerufen wird. Alle Objekte die im Konstruktor auf dem Heap (mit new bzw malloc (C) ) erzeugt oder initialisiert werden müssen später im Destruktor mit delete, delete[] oder free (C) wieder freigegeben werden. D.h. der Speicherbereich wird von Windows verwaltet. Der ganze Speicher ist eigentlich vollgeschrieben. Was aber wo drin steht und welchen Bereich deine Software beschreiben darf, das wird verwaltet. Wenn Du also neuen Speicher haben willst, musst du das mit new erledigen. Dann ist der Speicher allerdings für dich reserviert, solange bis Du ihn wieder freigibst.
Wenn Du aber Objekte ohne new anlegst , dann kommen diese auf den Stack. Jede Funktion (Block) hat ihren eigenen Stack und das Programm im gesamten auch.
Jeder Block ist mit { und } begrenzt.
Wenn ein Block zuende ist, werden alle Variablen die in diesem Block erzeugt wurden wieder "vernichtet".
Beispiel:
C++:
LaubBaum laubBaum("Eiche");//statisch angelegt

if(1==1){
   LaubBaum laubBaum("Ahorn");//statisch angelegt, nur in der IF
   std::cout << laubBaum; // AHORN 
}

std::cout << laubBaum; // EICHE!!

C++:
LaubBaum *laubBaum = new LaubBaum("Eiche");

if(1==1){
   delete laubBaum;//vorher löschen, da sonst ein Objekt im Speicher "verlorengeht" und ein Speicherleck entsteht
   laubBaum = new LaubBaum("Ahorn");
   std::cout << *laubBaum; // AHORN 
}
std::cout << *laubBaum; // AHORN!!

zu 4.)
  • char buffer
    ein einzelnes Zeichen auf dem Stack (8Bit)
  • char* buffer
    ein 32Bit Zeiger (4byte) in einem 32bit System auf einen char irgendwo im Speicher (null wenn nicht initialisiert)
  • char buffer[10]
    ein Array der Länge von Zehn Chars hintereinander, *buffer ist das erste char
  • char buffer[]
    sollte nicht mehr benutzt werden
  • char buffer*
    sollte normalerweise nicht gehen (oder ist es schon so spät dass ich was übersehe? :p

Für Listen von Elementen nutzt man in C++ fertige STL-Speicherbuffer wie List, Map, Vektor. Da braucht man sich um die Länge der Liste im vornherein nicht kümmern!

Im Endeffekt musst Du halt noch viel lesen, viel probieren und vor allem viel Code schreiben!

Viel Erfolg
 
um es mit 2 Worten zu sagen: Au weia
oder auch in einem Wort: Bahnhof?

wurden in jahrzehntelanger Arbeit verschiedene Softwareentwicklungsmethoden erfunden

entweder hat da keiner mitgedacht, oder der Plan war es, die Sache so kompliziert wie nur irgend möglich zu machen
Mag sein, dass ich hier Äpfel mit Birnen vergleiche, aber in php ist das alles derartig viel einfacher, da frage ich mich einfach, warum noch keiner auf die Idee gekommen ist eine IDE zu entwickeln, die ähnlich einfach funktioniert
Logisch, in C/C++ hat man weit mehr Möglichkeiten als in php, also braucht es auch weit mehr an Befehlen, aber im Prinzip müsste es doch machbar sein

Nachdem ich php nun mal kenne, wenn ich in meinen Übungen auf ein Problem stosse fällt mir automatisch ein wie ich es in php lösen würde und dann versuche ich rauszufinden, wie man das in C "übersetzt", aber irgendwie haut das nie hin, oder ich bin einfach zu doof, z.B. das Problem was ich in meinem vorherigen Topic hatte, einen String nach int und string sortieren, das habe ich immer noch nicht gelöst

in php ganz einfach:

$string = "Dies 123 ist 345 ein 789 string";
$woerter = explode(" ", $string);
for ($i = 0; $i < count($woerter); $i++) {
if (strlen(intval($woerter[$i])) == strlen($woerter[$i])) {
$intarray[] = intval($worter[$i]);
}
else {
$stringarray[] = $worter[$i];
}
}

in C fängt das Problem schon beim explode an, zumindest habe ich nichts passendes gefunden
Schleife geht in C fast genauso, aber bei strlen(intval) ist dann in C endgültig Essig
Zu Problemen wie ein string ist bereits ein array, also ist ein array von strings bereits mehrdimensional bin ich gar nicht erst gekommen, von Speicher dafür anfordern und hinterher wieder frei geben mal gar nicht zu reden, und selbst wenn ich irgendwie da hin kommen würde, dann habe ich immer noch so kleine Problemchen am Rande, wie z.b. \0 am Ende von jedem Element im stringarray einzufügen
 
Thomasio hat gesagt.:
das Problem was ich in meinem vorherigen Topic hatte, einen String nach int und string sortieren, das habe ich immer noch nicht gelöst

in php ganz einfach:

$string = "Dies 123 ist 345 ein 789 string";
$woerter = explode(" ", $string);
for ($i = 0; $i < count($woerter); $i++) {
if (strlen(intval($woerter[$i])) == strlen($woerter[$i])) {
$intarray[] = intval($worter[$i]);
}
else {
$stringarray[] = $worter[$i];
}
}

in C fängt das Problem schon beim explode an, zumindest habe ich nichts passendes gefunden
Schleife geht in C fast genauso, aber bei strlen(intval) ist dann in C endgültig Essig
Zu Problemen wie ein string ist bereits ein array, also ist ein array von strings bereits mehrdimensional bin ich gar nicht erst gekommen, von Speicher dafür anfordern und hinterher wieder frei geben mal gar nicht zu reden, und selbst wenn ich irgendwie da hin kommen würde, dann habe ich immer noch so kleine Problemchen am Rande, wie z.b. \0 am Ende von jedem Element im stringarray einzufügen
Erstmal möchte ich mich Thomas anschliessen: du solltest lieber gleich C++ lernen. Es gibt auch gute C++ Frameworks mit denen du Programme für Windows schreiben kannst die dann auch noch Cross-Platform fähig sind wie z.B. wxWidgets bzw. Qt. Dann brauchst du dich erst gar nicht mit C und der WinAPI rumschlagen. Gut, es schadet natürlich auch nichts wenn du C kannst...

Hier ist mal ein kleines Beispielprogramm wie du in C die Sache angehen kannst.
C:
#include <stdio.h>
#include <string.h>

int main(void) {
  
  char string[50]; // muss wegen strtok ein änderbarer String sein.
  strncpy(string, "dies 123 ist 345 ein 789 string", sizeof(string) / sizeof(string[0]));

  for (char* word = strtok(string, " ");
       word != NULL; 
       word = strtok(NULL, " ")) {
    int number, n;
    if (sscanf(word, "%d%n", &number, &n) == 1 && n == strlen(word)) {
      printf("eine Zahl: %d\n", number);
    } else {
      printf("bloss ein String: %s\n", word);
    }
  }
}
Der Code ist übrigens C99 Code.

Gruß
 
Zuletzt bearbeitet:
hey danke,

das sieht so einfach aus, das verstehe ich sogar
offen bleibt mir dabei nur:

1) wenn ichs richtig sehe muss vor die letzte } noch ein free(string); rein?
2) wo und wie wird der speicher für char* word wieder freigegeben?
 
Thomasio hat gesagt.:
1) wenn ichs richtig sehe muss vor die letzte } noch ein free(string); rein?
Da siehst du leider was falsches. ;)

Die Variable "string" ist ein statisches char-Array von 50 Elementen und somit kümmert sich der Compiler um das Bereitstellen und Freigeben vom Speicher. Wenn ich explizit Speicher mit malloc bzw. calloc anfordere muß ich ihn auch mit free wieder freigeben.
Thomasio hat gesagt.:
2) wo und wie wird der speicher für char* word wieder freigegeben?
Für die Variable word wird nirgends extra Speicher alloziert. Die Funktion strtok verändert direkt den String der zu Anfang als Initialisierung übergeben wird und gibt direkt einen Zeiger innerhalb des Strings "string" zurück. Siehe http://www.hmug.org/man/3/strtok.php

/edit: Bsp: Wenn also strtok das erste mal für den String "dies 123 ist 345 ein 789 string" aufgerufen wird, sucht die Funktion nach dem Trennzeichen und setzt an die Stelle dann ein Terminierungszeichen. D.h. strlen(string) == 4. strtok gibt dann die Adresse vom Stringanfang zurück. D.h word == string.

Gruß
 
Zuletzt bearbeitet:
Wie kann man denn PHP mit C++ vergleichen? :confused:

C und C++ sind soviele Jahre älter und auch noch Hochsprachen, wohingegen PHP eine langsame Interpreter/Scriptsprache ist.

Lern es oder lass es..an der Sprache C/C++ kannst Du eh nicht rütteln.
Ansonsten gibt es VB, C#, Delphi etc. die allesamt einfacher, aber nicht so mächtig sind.
 
Zurück