Programmierhilfe für Studium gesucht - C
-
Bashar schrieb:
s1 zeigt auf eine gegebene Struktur vom Typ
struct string_t
.s1
ist sogarstring_t**
-
sizeof
liefert dir Größe (den Speicherverbrauch) in Bytes von einer Variablen.laenge ist vom Typ
int
und das sind i.A. 16 - 32 Bit also 2 - 4 Byte
Du brauchst den Wert von laengeFalls du auf dumme Gedanken kommst:
s ist ein Zeiger und die sind z.B. auf 32-Bit Systemen auch 4 Byte groß.
Das hat nichts mit der Länge des Textes zu tun, auf die s zeigt.
-
Also erstmal danke an euch alle, dass ihr euch die Zeit genommen habt, um mir zue helfen.
Aber das mit dem Programmieren wird wohl bis Freitag nichts bei mir...
Ich kann euch ja nichtmals erklären, woran es bei mir scheitert.Also Vielen Dank an alle, aber ich muss mir irgendwo jemanden suchen, ders mir programmiert und erklärt
-
Dabei ist das nicht mal eine schwere Aufgabe, wie lange studierst du denn schon?
-
Seit Oktober...
Aber in den Vorlesungen lernt man bei unserem Dozent nichts und in den 3-4 Übungsstunden, die wir hatten, haben wir ganz andere Sachen gemacht.
Und ich finde es ziemlich schwer sich das alles in der kurzen Zeit selbst beizubringen, wenn man auch noch andere Fächer hat...
-
Ja zum lernen ist ein Forum nicht so geeignet.
Deine Versuche gestern liessen bei mir ein wenig den Eindruck aufkommen, dass Du Deine Vorschläge gar nicht testen kannst.
Dem ist aber nicht so? Du hast einen Compiler zu Deiner Verfügung?Ich denke bis Freitag würdest Du das hinbekommen - mit viel Initiative.
Aber in kleinen Schritten hätten wir Dich schon dahin gebracht.
(Als erstes hättest Du aber die Code-Tags (der C Button unter dem Editierfeld) entdecken müssen.)
Die Aufgabe ist nicht so trivial, wie sie scheint. (Oder ich habe Tomaten auf den Augen...)
Mein Anfang - nur für den leeren String - steht unten.Ist das Verständlich?
Versuch Dich nochmal an derset()
Funktion!
Der Einfachheit halber benutz folgenden Prototypen:void string_set(string s1, char *s);
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef struct { int len; /* Anzahl der Zeichen in s; -1 wenn s == NULL */ char *s; /* ein C-string mit abschließendem \0-Zeichen (oder NULL) */ } string_t; typedef string_t* string; string string_alloc() { string s = malloc(sizeof(string_t)); if (s!=NULL) { // initialisieren nach Vorgabe s->len = -1; s->s = NULL; } return s; } void string_free(string s) { // nicht der NULL Zeiger? if (s!=NULL) { // Speicher fuer einen cstring alloziert? if (s->s!=NULL) free(s->s); // dann den cstring freigeben free(s); // das gesamte string_t Objekt freigeben } } // die Bedingungen testen bool is_valid(string s) { if(s->s==NULL) return s->len==-1; // wenn s==NULL, dann len==-1 return true; // ueber "gefuellte" strings koennen wir noch keine Aussage machen } int main(void) { string s = string_alloc(); if(!is_valid(s)) puts("Fehler!\n"); string_free(s); }
-
Paul_McIcetea schrieb:
Aber in den Vorlesungen lernt man bei unserem Dozent nichts und in den 3-4 Übungsstunden, die wir hatten, haben wir ganz andere Sachen gemacht.
Studierst du Informatik oder ist es bei dir nur ein "Nebenfach"?
Du solltest nicht erwarten, in den Vorlesungen irgendwas zu "lernen", dafür sind sie nicht da. Schon gar nicht, dass dir jemand beibringt, wie man programiert. Das Studium ist nicht die Schule, von der Vorstellung solltest du dich ganz schnell verabschieden, sonst ist es schnell vorbei.
Es ist auch überhaupt nicht ungewöhnlich, dass man einfach irgendwas voraussetzt, was man noch nie gemacht oder gelernt hat. Das kommt fast ständig. Oft ist es auch einfach nur irgendeine Laune des Professors. Da kommt plötzlich in irgendeinem Fach eine Übungsaufgabe, für die man irgendwas ziemlich kompliziertes können muss, was man mit dem Fach überhaupt nichts zu tun hat und was man noch nie gemacht hat. Wir mussten im C++ Praktikum irgendwelche physikalischen Vorgänge simulieren. Da haben wir einfach ein Paper hingeklatscht bekommen und das wars. Wir waren Informatiker, keine PhysikerDa muss man sich erstmal überhaupt an den Stil von solchen Publikationen gewöhnen, die Symbole entziffern, in die Formeln irgendwas reininterpretieren, den Text verstehen um zu wissen, auf welche andere Teilformeln da verwiesen wird usw... Viel, viel komplizierter als in einem einfachen C++ Praktikum nötig gewesen wäre. Aber dadurch lernt man auch mehr "fürs Leben".
-
Macht es eigentlich einen Unterschied wie ich das Free aufrufe?
Angenommen es ist so :
struct Mystring { char *text; size_t len; };
void freestr(struct Mystring *del) { if (del->text){ free(del->text); del->len = 0; puts("\nFree\n"); } }
oder
void freestr(struct Mystring del) { if (del.text){ // del ist ja eigentlich nur eine kopie....wobei bei *del auch nur eine Kopie des Zeigers übergeben wird // oder habe ich das falsch in Erinnerung? free(del.text); del.len = 0; puts("\nFree\n"); } }
In beiden Fällen angenommen, der Char Zeiger ist Null wenn kein Speicher alloziert wurde...
-
Beim Ersten hast du eien Kopie der Adresse und greifst somit auf das Original zu.
Beim Zweiten änderst du nur die Kopie. Das Original wird nicht verändert, obwohl du den Speicher dafür freigibst -> Crash.unsure schrieb:
In beiden Fällen angenommen, der Char Zeiger ist Null wenn kein Speicher alloziert wurde...
Das musst du dann aber auch in deinem freestr sicherstellen.
In der Aufgabe stand auch etwas von -1
-
Ja, das macht einen gewaltigen Unterschied, angesichts der Tatsache, dass du verstehen musst, warum man manchmal Zeiger auf Objekte an Funktionen übergibt und manchmal Kopien der Objekte.
Nein, es macht im Prinzip keinen Unterschied, da die halbe Funktion bloß Hokuspokus ist. Das mit der Nullprüfung ist 100% sinnlos. Das Nullsetzen schützt dich bloß davor, dass du eventuell in deinem Programm vorhandene Logikfehler beim Testen entdecken könntest. Das was an der Funktion hier wirklich wichtig ist, das free, funktioniert bei beiden Varianten.
-
Das was an der Funktion hier wirklich wichtig ist, das free, funktioniert bei beiden Varianten.
vs
Beim Zweiten änderst du nur die Kopie. Das Original wird nicht verändert, obwohl du den Speicher dafür freigibst -> Crash.
Ich hätte jetzt auch gedacht das die 2. Variante also mit der Kopie des Objekts nicht "funktioniert"...
In beiden Fällen angenommen, der Char Zeiger ist Null wenn kein Speicher alloziert wurde...
Das musst du dann aber auch in deinem freestr sicherstellen.
if (del->text) macht das doch ? Ok, fehlt der else zweig..
...dass du verstehen musst, warum man manchmal Zeiger auf Objekte an Funktionen übergibt und manchmal Kopien der Objekte.
Das ist mir nicht immer 100% klar... Ne Faustregel gibt´s wohl nicht ?
-
unsure schrieb:
Das was an der Funktion hier wirklich wichtig ist, das free, funktioniert bei beiden Varianten.
vs
Beim Zweiten änderst du nur die Kopie. Das Original wird nicht verändert, obwohl du den Speicher dafür freigibst -> Crash.
Ich hätte jetzt auch gedacht das die 2. Variante also mit der Kopie des Objekts nicht "funktioniert"...
Bei beiden wird der Speicher freigegeben Das wolltest du doch.
unsure schrieb:
In beiden Fällen angenommen, der Char Zeiger ist Null wenn kein Speicher alloziert wurde...
Das musst du dann aber auch in deinem freestr sicherstellen.
if (del->text) macht das doch ? Ok, fehlt der else zweig..
Wenn ein NULL-Zeiger ein Anzeichen für nicht allozierten Speicher ist, musst du nach dem freigeben den Zeiger auch auf NULL setzen.
unsure schrieb:
...dass du verstehen musst, warum man manchmal Zeiger auf Objekte an Funktionen übergibt und manchmal Kopien der Objekte.
Das ist mir nicht immer 100% klar... Ne Faustregel gibt´s wohl nicht ?
Brauchst du das Original?
Darfst du es verändern?
Das hängt auch ein bisschen von der Größe des Objektes ab. Wie teuer ist die Kopieraktion?
(In den ersten C-Versionen konnte man structs nicht als Ganzes an Funktionen übergeben.)
-
Bei beiden wird der Speicher freigegeben Das wolltest du doch.
Ja schon, aber natürlich so , das es auch "passt".
Beim Zweiten änderst du nur die Kopie. Das Original wird nicht verändert, obwohl du den Speicher dafür freigibst -> Crash.
Aber die Kopie ist ja auch die Kopie der Speicheradresse, also müsste der Speicher für´s Original auch Freigegeben sein? Wann würde das warum crashen?
-
Brauchst du das Original?
Darfst du es verändern?Hm... Ja das kommt jetzt darauf an.. Ich will es auf jedenfall verändern, darum nehme ich normal die Pointer Variante.
Also ich hätte jetzt so oder so die Pointer Variante (aus dem Bauch heraus) genommen.Brauch ich das Original ? Kommt drauf an ob die Freigabe bei der Kopie, siehe obrigen Post , funktioniert..
-
unsure schrieb:
Ja schon, aber natürlich so , das es auch "passt".
Wie passt es denn?
unsure schrieb:
Aber die Kopie ist ja auch die Kopie der Speicheradresse, also müsste der Speicher für´s Original auch Freigegeben sein?
Ja
unsure schrieb:
Wann würde das warum crashen?
Das
del.len = 0;
kommt nicht ins Original zurück.
-
Merde. Sorry, das hab ich jetzt total übersehen. War / ist n blödes Beispiel.
Brauch ich das Original
Meistens schon
Fast immer. Darum (Bauchgefühl ON) : übergib mal lieber per Reference...
-
DirkB schrieb:
Das
del.len = 0;
kommt nicht ins Original zurück.Die eigentliche Frage ist doch: Wollen wir das überhaupt?
Lemma: Nutzung eines Objekts nach Zerstörung ist ein Fehler in der Programmlogik.
Korollar: Bei der Zerstörung des Objekts ist egal, in welchem Zustand es hinterlassen wird.
Korollar 2: Ein zerstörtes Objekt in einem Zustand zu hinterlassen, bei dem eine Weiterbenutzung keinen Fehler erzeugt, verschleiert eben diese fehlerhafte Weiterbenutzung. Ansonsten würde es nämlich beim Testen abstürzen und man würde den Fehler bemerken.In der gleichen Kategorie: Prüfen von Zeigern auf NULL vor free (macht nämlich genau gar nichts, sofern man dann keinen else-Zweig hat, der einen Fehler ausgibt) und setzen von Zeigern auf NULL nach free (verhindert Fehlerfindung beim Testen, dadurch dass man keinen Fehler bei doppeltem free auslöst).
-
In diesem Fall würde ich als das Objekt die struct Mystring sehen.
Und diese existiert ja noch weiter. Daher sollten die internen Zustände schon eindeutig sein.Zudem tritt das Problem mit del.len ja auch beim concat auf.
Und einen NULL-Pointer zu finden sollte einfacher sein, als einen der sonstwohin zeigt.