Forum: PC-Programmierung Container Problem


von Hans (Gast)


Lesenswert?

int main(void)
{
  vector<Dmxdaten *> cont;
  vector<Dmxdaten *>::iterator it;
  Dmxdaten *a_1 = new Dmxdaten("Ledwert",2,3,4);
  cont.push_back(a_1);
      for (it = cont.begin(); it != cont.end(); it++)
       { cout << *a_1; }

 return 0;
 }

Er wirft mir da immer bei cout die Adresse raus

mein Plan war folgender globale Operatorfuntion

ostream &operator<<(ostream &os, const vector<Dmxdaten*> &p)
{
  cout << //Daten;
  return os;
}
 Leider gehts nicht er sprint nicht in die ostream

von Matthias (Gast)


Lesenswert?

Fehlt da bei dem Operator nicht etwas?

von Peter (Gast)


Lesenswert?

Hallo,

mit *a_1 bekommt du ja das object in dem container und das ist nunmal 
ein zeiger.


cout << *a_1; sollte es tun.


Ich schreibe es immer so. Debuggt sich einfacher.


for (it = cont.begin(); it != cont.end(); it++)
{
   Dmxdaten& tmp = *(*it);
   cout << tmp;
}

von Peter (Gast)


Lesenswert?

Oh was soll überhaupt die Schleife mit dit Iterator wenn du ihn nicht 
verwendest?

Das ist unsinn von mir

> mit *a_1 bekommt du ja das object in dem container und das ist nunmal
> ein zeiger.
> cout << *a_1; sollte es tun.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Oh was soll überhaupt die Schleife mit dit Iterator wenn du ihn nicht
> verwendest?

Ich bin sicher das das wieder mal ein Tippfehler ist, der entstanden 
ist, weil nicht tatsächlicher Code per Copy&Paste kopiert wurde, sondern 
ein Bsp händisch hier eingetippt wurde.

>
> Das ist unsinn von mir

Wenn mans wortwörtlich nimmt, hast du hier recht.
Wenn man die Frage gedanklich um die Tippfehler in der Fragestellung 
bereinigt, ist deine Antwort goldrichtig.

von Hans (Gast)


Lesenswert?

int main(void)
{
  vector<Dmxdaten *> cont;
  vector<Dmxdaten *>::iterator it;
  Dmxdaten *a_1 = new Dmxdaten("Ledwert",2,3,4);
  cont.push_back(a_1);
      for (it = cont.begin(); it != cont.end(); it++)
       {
                Dmxdaten *tmp = *it;
     cout << *tmp;
       }

 return 0;
 }

so gehts

von Klaus W. (mfgkw)


Lesenswert?

und dann gehört hier kein ::iterator hin, sondern ein ::const_iterator,
und ++it ist bei Iteratoren immer besser als it++ (weil semantisch hier
egal, und besser optimierbar).

von Hans (Gast)


Lesenswert?

? ich hab mir das aus einem Buch abgeschrieben und da ist es so drinnen
aber ok

von Karl H. (kbuchegg)


Lesenswert?

Wenn wir schon dabei sind, dann ist es schon mal (meistens) Blödsinn, 
die Datenobjekte im vector dynamisch zu allokieren. Bringt nur 
Mehraufwand, weil man sich dann auch um die Freigabe bzw. Kopie, op= 
kümmern muss.
Was anderes ist es natürlich, wenn mehrere Referenzierungen auf 
dieselben Daten notwendig sind. Aber das scheint hier nicht der Fall zu 
sein.

-> Wann immer möglich, lass den std::vector sich um die eigentlichen 
Objekte kümmern! Das ist sein Job!
1
int main(void)
2
{
3
  vector<Dmxdaten> cont;
4
  cont.push_back( Dmxdaten("Ledwert",2,3,4) );
5
6
  vector<Dmxdaten>::const_iterator it;
7
  for (it = cont.begin(); it != cont.end(); ++it)
8
  {
9
    cout << *it;
10
  }
11
12
  return 0;
13
}

von Peter (Gast)


Lesenswert?

Wenn das in den Buch zu drin steht, dann würde ich das buch entsorgen. 
Oder steht über den code etwas wie "Finden sie den Fehler in den 
Codeabschnitt"

von Klaus W. (mfgkw)


Lesenswert?

Hans schrieb:
> ? ich hab mir das aus einem Buch abgeschrieben und da ist es so drinnen
> aber ok

Wenn es in einem Buch steht, muß es ja noch nicht optimal sein.

von Peter (Gast)


Lesenswert?

@Karl heinz Buchegger
ja so sieht es erstmal besser aus. Hat aber sehr grosse Performance 
nachteile. Jedesmal wenn ein object in den Vektor eingefügt wird, wird 
von jeden Object der Copyconstructur aufgerufen und das Object kopiert. 
Das mag bei einer Liste von 10O Objeken noch gehen, aber wenn mal ein 
paar 1000 drin sind und das objekt selber wieder eine Liste hat. Dann 
hat ist diese viel zu langsam.
Ich glaube sogar beim einfügen selber wird schon das erste Mal kopiert.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> @Karl heinz Buchegger
> ja so sieht es erstmal besser aus. Hat aber sehr grosse Performance
> nachteile. Jedesmal wenn ein object in den Vektor eingefügt wird, wird
> von jeden Object der Copyconstructur aufgerufen und das Object kopiert.
> Das mag bei einer Liste von 10O Objeken noch gehen, aber wenn mal ein
> paar 1000 drin sind und das objekt selber wieder eine Liste hat. Dann
> hat ist diese viel zu langsam.
> Ich glaube sogar beim einfügen selber wird schon das erste Mal kopiert.

Ja das wird es.
Kommt immer drauf an, wieviele Objekte es sind und wie teuer es ist eine 
Kopie zu machen und wie häufig die Operation ist. Aber im Zweifel ist es 
für einen Beginner vernünftiger als einen Haufen Speicherlecks zu 
hinterlassen :-)

(Schade, dass die originalen Smart-Pointer nicht Containerfähig sind. 
Aber wozu gibt es denn Boost :-)

von Klaus W. (mfgkw)


Lesenswert?

Ich weiß ja nicht, wofür man hier einen std::vector braucht,
aber in 90% der Fälle ist der vector ohnehin die falsche Wahl.
Leider ist er einem Feld zu ähnlich, deshalb nimmt ihn jeder
für alles mögliche, anstatt einen passenden Container zu nehmen.
Das führt dann aber auch gleich wieder zu weit...

von Hans (Gast)


Lesenswert?

Also funktionieren tut es soweit (Ich erkäre es mal)

"Ledwert",------------------------------2,3,4

Ledewert wird von einer Klasse eingelesen die Werte 2,3,4 werden von 
einer
abgeleiteten Klasse eingelesen nachdem das ganze dann eingelesen wurde
wird es in Vector oder list abgespeichert siehe oben

wieso ich das jetzt so gemacht habe ist doch klar

ich kann von der Oberklasse wieder ne neue Klasse ableiten
nur diesmal zb mit 10 Kanälen statt mit 3 wie jetzt

und kann dann mit Zeiger jedesmal zwischen den abgeleiteten klassen 
wählen

das ist doch top

von Klaus W. (mfgkw)


Lesenswert?

Ich habe es zwar nicht richtig verstanden, aber egal.

Es sieht zumindest so aus, daß in dem vector Zeiger auf
Objekte von verschiedenen Klassen liegen.
Das ist dann in der Tat ein Argument für Zeiger im vector
statt der Elemente selbst, anders geht es nicht.

Wenn eine std::list statt des vector auch möglich ist,
dann ist zumindest das Anfügen wesentlich effizienter.

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:
>
> wieso ich das jetzt so gemacht habe ist doch klar
>
> ich kann von der Oberklasse wieder ne neue Klasse ableiten
> nur diesmal zb mit 10 Kanälen statt mit 3 wie jetzt

Ähm. Das klingt jetzt nach einem falschen Einsatzzweck für 
Polymorphismus.

Ob ein Lader 3 oder 10 Kanäle hat, ist eine Eigenschaft des Laders - ein 
Property.

Wenn du eine Klasse public ableitest, dann entspricht das gemeinhin 
einer 'Ist-ein' Beziehung.

So wie in:

Ein Hund ist ein Tier

class Tier
{
};

class Hund : public Tier
{
};

oder:  Ein Pkw ist ein Auto

Wenn aber ein Lader 3 Kanäle hat und ein anderer hat in einer anderen 
Ausbaustufe 10 Kanäle, dann ist das doch im Prinzip immer noch der 
gleiche Lader, nur mit mehr Ladestufen. Er kann deswegen nicht mehr oder 
weniger (zb. zusätzlich noch Kaffee kochen). Ich kann doch auch hergehen 
und einen Lader von 3 Kanälen auf 10 Kanälen ausbauen, ohne dass sich am 
Lader (abgesehen von der Anzahl der Ladestufen) etwas verändert. So wie 
ein Pkw immer noch dasselbe Auto ist, wenn ich einen Kindersitz einbaue.

Was du hast ist am ehesten noch eine 'Hat-ein' Beziehung.
So wie in: Ein Auto hat einen Motor

Und das modelliert man mit einer Membervariablen
1
class Auto
2
{
3
  ...
4
  private:
5
    Motor*  pMotor_;   // Pointer, weil es verschiedene Motoren gibt
6
};
7
8
class Pkw : public Auto {};
9
class Lkw : public Auto {};
10
11
class Motor {};
12
class Benziner : public Motor {};
13
class Diesel : public Motor {};

Diese Gerüst modelliert:
Es gibt Autos
Es gibt Motoren
Ein Auto HAT_EINEN Motor
Ein Pkw IST_EIN Auto
Ein Lkw IST_EIN Auto
Ein Benzinmotor IST_EIN Motor
Ein Dieselmotor IST_EIN Motor

Und mit diesen Klassen kannst du jetzt alles zusammenstellen:
Ein Pkw mit Benzinmotor, Pkw mit Dieselmotor, Lkw mit Benzinmotor, Lkw 
mit Dieselmotor.
Und wenn die Firma nächstes Jahr einen Elektromotor auf den Markt 
bringt, ist das kein Problem. Dann gibt es eben einen Motortyp mehr:
1
class Elektro : public Motor {};

und schon kannst du alle Autos, sei es jetzt Pkw oder Lkw mit 
Elektromotor ausrüsten. Denn: Ein Auto HAT_EINEN Motor.

In diesem Sinne HAT dein Lader 3 oder 10 Ladestufen, die vielleicht 
verschiedene Ausprägungen haben können (was wies ich, mit 
unterschiedlicher Technologie aufgebaut sind, wenn das für dein Programm 
wichtig ist)
1
class Lader
2
{
3
 ...
4
5
  private:
6
    std::list< Ladestufe* > ladeStufen_;
7
};



> und kann dann mit Zeiger jedesmal zwischen den abgeleiteten klassen
> wählen

Da hast du recht: Sobald Polymorphie ins Spiel kommt, müssen es Zeiger 
sein. Daran hab ich jetzt nicht gedacht.

von Hans (Gast)


Lesenswert?

Früher im studium wurde uns das so beigebracht

zb Fläche berechnen von Kreis und Dreieck

mann macht ne Base als Interface

Kreis und Dreieck leitet man ab

und speichert das ganze in nem Container ab



der container bekommt auch noch ne eigene Klasse


das ist auch mein Ziel für heute abend

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:
> Früher im studium wurde uns das so beigebracht
>
> zb Fläche berechnen von Kreis und Dreieck
>
> mann macht ne Base als Interface
>
> Kreis und Dreieck leitet man ab

Ja. Ist doch das gleiche Prinzip

Es gibt ein geometrisches Primitiv (= Basisklasse)
Ein Kreis IST_EIN geometrisches Primitiv
Ein Dreieck IST_EIN geometrisches Primitiv

Jedes geometrische Primitiv kann seine Fläche berechnen.
-> die Member Funktion area() kann grundsätzlich in die Basisklasse 
wandern, da jedes geometrische Primitiv seine Fläche berechnen können 
muss. Da aber die Flächenberechnung je nach tatsächlichem Primitiv 
anders ausfällt, ist das eine virtuelle Funktion, die von den 
tatsächlichen Primtiva implementiert werden muss.

Eine Basisklasse, die selbst abstrakt ist (von der man also kein Objekt 
erzeugen kann) nennt man Interface. Wobei hier die Definition, wann man 
genau von einem Interface spricht und wann von einer Basisklasse, etwas 
schwammig ist. Normalerweise enthält ein Interface nur einen Satz von 
abstrakten virtuellen Funktionen und nicht mehr.

> und speichert das ganze in nem Container ab
> der container bekommt auch noch ne eigene Klasse

Das ist in dem Fall sicherlich sinnvoll, da der Container ja Pointer 
enthalten muss, da Polymorphie gefordert ist. Wann immer ein Objekt 
andere Resourcen dynamisch verwalten muss, ist man meistens gut beraten, 
wenn man diese 'Details' in eine eigene Klasse verpackt. Das 
zugrundeliegende Prinzip nennt man RAII (Resource Acquisition Is 
Initialization)

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

von Hans (Gast)


Lesenswert?

list<string> liste;
list<string>::iterator iter;

liste.push_front("daten");
cout << liste.front();


wollte noch schnell was testen

kann ich nicht einen Datenstring in ne liste reinschreiben
und anschließend wieder auslesen?

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:
> list<string> liste;
> list<string>::iterator iter;
>
> liste.push_front("daten");
> cout << liste.front();
>
>
> wollte noch schnell was testen
>
> kann ich nicht einen Datenstring in ne liste reinschreiben
> und anschließend wieder auslesen?

sicher kannst du.
Eventuell solltest du deinem cout Objekt noch einen endl nachschieben, 
damit es den Buffer ausleert.

von Hans (Gast)


Lesenswert?

int main ()
{
list<string> liste;
list<string>::iterator iter;


liste.push_front("daten");

cout << liste.front() << endl;


return 0;
}

so? das geht aber auch nicht!

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:
> int main ()
> {
> list<string> liste;
> list<string>::iterator iter;
>
>
> liste.push_front("daten");
>
> cout << liste.front() << endl;
>
>
> return 0;
> }
>
> so? das geht aber auch nicht!

Was geht nicht?

Wenn ich das hier
1
#include <iostream>
2
#include <list>
3
#include <string>
4
5
using namespace std;
6
7
int main()
8
{
9
list<string> liste;
10
list<string>::iterator iter;
11
12
liste.push_front("daten");
13
cout << liste.front();
14
cout << endl;
15
}

durch den Compiler jage, compiliert alles wunderbar und das Ergebnis ist 
wie erwartet.


Sag niemals "das geht nicht". Sag konkret, was das Problem ist. Du gehst 
ja auch nicht zu deinem Arzt und sagst "Es tut weh"

von Hans (Gast)


Lesenswert?

ah ich habs
ich hab vergessen

die #include <string>

mit anzugeben

von Hans (Gast)


Lesenswert?

Hallo ich hab mir mal noch ein paar gedanken gemacht


Ich hab das Programm

int main(void)
{
  vector<Person **> cont;
        vector<Person **>::iterator it;

  Person *a_1 = new Person("Hans",2,3,4);
  Person **a_2 = & a_1;
  cont.push_back(a_2);

   for (it = cont.begin(); it != cont.end(); it++)
   {
       cout << (***it);
   }
 return 0;
 }

wieso springt der Combiler bei der Vektorhe hier rein

reference operator*() const
    {// return designated object
      return ((reference)**(_Mybase *)this);
    }

Da dürfte ehr doch gar nicht reinspringen?

von Peter (Gast)


Lesenswert?

doch das ist eine überladenen operator vom iterator, das sollte soweit 
stimmt. Aber warum zum Teufel sollte man einen Zeiger auf einen Zeiger 
verwenden?

von Klaus W. (mfgkw)


Lesenswert?

wo hast du reference operator*() const... her?
Aus dem vector-Header?
In std::vector ist ein Untertyp iterator definiert, den
du nimmst (entgegen meiner Empfehlung const_iterator zu nehmen,
so kann man sich den Mund fusslig reden...).
Und für den ist wiederum operator* überladen.
Mit *it rufst du genau dieses Ding auf.

von Klaus W. (mfgkw)


Lesenswert?

Peter schrieb:
> ... Aber warum zum Teufel sollte man einen Zeiger auf einen Zeiger
> verwenden?

Zum Üben, ist doch ok!

von Lukas (Gast)


Lesenswert?

Der Combiler macht aus ***it
**it.operator*();  und schon ruft er die richtige Medhote auf

von Klaus W. (mfgkw)


Lesenswert?

id.oberador, wenn schon

von Hans (Gast)


Lesenswert?

Ich hab die abspeicherung der Daten nun so gelöst
Interface dann 2 Klassen die das Interface implementieren um 
untersiedliche
Kanäle einzugeben und eine Klasse mit Vector als Container.

meine Problem ist folgendens Vector speicher ja nur Adressen von Ob ab.

das ist ja keine Problem solange die Ob existieren

aber wenn ich die Daten nun so einlesen will hab ich ein Problem

DatenKlasse1 daten_1;
DatenKlasse2 daten_2;

und das dann folgendes mache

 for (int i = 0;i <10;i++)
      {
        cout << "Bitte Daten eingeben \n";
        if (cin >> daten_1)
          ch.gebein(&daten_1);

        if (cin >> daten_2)
           ch.gebein(&daten_2);
        cin.clear();
        cin.ignore(INT_MAX, '\n');
      }

das ist natürlich nicht gerade schön mir ist schon klar das das so nicht 
gehen kann aber wie löst man sowas in c++

von Rene H. (Gast)


Lesenswert?

Ich verstehe nicht was Du genau willst, kannst Du das bitte anders 
formulieren?

Sind mit Ob Objekte gemeint?
Wo ist die Klasse mit den Vektoren?
Welche zwei Klassen haben welches Interface implementiert?

Du kannst schlecht erwarten, dass alle den ganzen Thread durchlesen, 
damit sie Wissen was Du genau implementieren willst.

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:
>
> das ist ja keine Problem solange die Ob existieren

Wenn sie nicht existieren, dann musst du sie erzeugen.

>
> aber wenn ich die Daten nun so einlesen will hab ich ein Problem
>
> DatenKlasse1 daten_1;
> DatenKlasse2 daten_2;

Das ist schon Käse.
Du weißt nicht, welche Objekte du brauchst, ehe dir der Benutzer nicht 
sagt, was er haben möchte.

Ergo kannst du die Objekte so nicht anlegen, sondern musst abwarten bis 
der Benutzer seine Wahl getroffen hat. Erst dann kannst du mittels new 
das neue Objekt erzeugen, es mit Daten füllen und die Adresse des 
Objektes in den vector stopfen.

Tja. Und jetzt geht der Eiertanz los.
Wer kümmert sich darum, dass die Objekte wieder freigegeben werden, wer 
sorgt dafür, dass in einer Kopie des vectors auch Kopien der Objekte 
sind, ditto für Zuweisung, etc.


(Bist du sicher, dass du auf der Uni schon mal C++ programmiert hast? 
Deine Fragen sind sehr 'basic'. Ich kann kaum glauben, dass man auf der 
Uni keine dynamische Objektallokierung in C++ mehr macht)


PS: Das

  DatenKlasse1 daten_1;
  DatenKlasse2 daten_2;

 for (int i = 0;i <10;i++)
      {
        cout << "Bitte Daten eingeben \n";
        if (cin >> daten_1)
          ch.gebein(&daten_1);

        if (cin >> daten_2)
           ch.gebein(&daten_2);
        cin.clear();
        cin.ignore(INT_MAX, '\n');
      }

ist höchst wahrscheinlich eine Todsünde. Stopfe nie die Adresse einer 
Stack-Allokierten Variablen in einen Container, der Pointer verwaltet!
Der Container ist meistens Owner der Pointer, heißt: Er ist dafür 
zuständig, dass die Objekte wieder delete-ed werden. Gibst du die 
Adresse eines Stack-Allokierten Objektes in einen Container, dann macht 
das einen kräftigen Bumm!

von Karl H. (kbuchegg)


Lesenswert?

So macht man das:

Es ist nicht die for-Schleife, die dafür zuständig ist, dass ein Objekt 
seine Daten bekommt. Im einfachsten Fall ist es das Objekt selber, denn 
nur das Objekt weiß, welche Daten es benötigt.
Das folgt genau dem objektorientiertem Gendankengang: Funktionalität 
dorthin wo sie hingehört, nämlich zum Objekt.
Wenn du die Datenobjekte von solchen Feinheiten, wie Ein/Ausgabe (die ja 
des öfteren Formatabhängig sein wird) freihalten willst, dann baut man 
eine Hilfsklasse, die über das konkrete Objekt und seine Bedürfnisse 
Bescheid weiß, das Objekt erzeugt und es mit den Daten füttert.
1
#include <iostream>
2
#include <vector>
3
4
using namespace std;
5
6
class Primitiv
7
{
8
  public:
9
    virtual void readData()    {}
10
    virtual void printData()   {}
11
};
12
13
class Rectangle : public Primitiv
14
{
15
  public:
16
    virtual void readData()
17
    { cout << "Rechteck:\n";
18
      cout << "  Länge:  ";  cin >> length_;
19
      cout << "  Breite: ";  cin >> width_;
20
    }
21
    
22
    virtual void printData()
23
    { cout << "Rechteck:    Länge " << length_ << " Breite " << width_ << "\n"; }
24
25
  private:
26
    double length_;
27
    double width_;
28
};
29
30
class Circle : public Primitiv
31
{
32
  public:
33
    virtual void readData()
34
    { cout << "Kreis:\n";
35
      cout << "  Radius:  ";  cin >> radius_;
36
    }
37
38
    virtual void printData()
39
    { cout << "Kreis:    Radius " << radius_ << "\n"; }
40
41
  private:
42
    double radius_;
43
};
44
45
int main()
46
{
47
  int choice;
48
  std::vector< Primitiv* > primitiva;
49
50
  for( int i = 0; i < 5; ++i )
51
  {
52
    Primitiv* newPrim = NULL;
53
54
    cout << "Was wollen sie? Rechteck(=0) oder Kreis(=1): ";
55
    cin >> choice;
56
57
    if( choice == 0 )
58
      newPrim = new Rectangle;
59
    else if( choice == 1 )
60
      newPrim = new Circle;
61
62
    if( newPrim )
63
    {
64
      newPrim->readData();
65
      primitiva.push_back( newPrim );
66
    }
67
  }
68
  
69
  cout << "Sie haben eingegeben:\n";
70
  for( size_t i = 0; i < primitiva.size(); ++i )
71
    primitiva[i]->printData();
72
    
73
  for( size_t i = 0; i < primitiva.size(); ++i )
74
    delete primitiva[i];
75
}


Sinnvollerweise wird man natürlich den vector<Primitiv*> wieder in eine 
eigene Klasse verpacken, die sich um das Datenmanagement kümmert, sodass 
derjenige, der diesen Container benutzt sich darüber keine Gedanken 
machen muss, dass Objekte richtig umkopiert bzw. gelöscht werden. Auch 
wird man dieser neuen Containerklasse dann Methoden verpassen, die eine 
Kopie eines Objektes erzeugen können (dazu benötigt man dann einen 
virtuellen Copy Constructor) etc. Aber das würde jetzt zu weit führen.

von Hans (Gast)


Lesenswert?

Hallo an der FH wurden ja keine Projekte gemacht
sondern es waren Übungsaufgaben wo die jeweiligen Klassen
beschrieben und nur der jeweilige Code eingetragen werden musste

Informatik hab ich übrigens nicht studiert

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:
> Hallo an der FH wurden ja keine Projekte gemacht
> sondern es waren Übungsaufgaben wo die jeweiligen Klassen
> beschrieben und nur der jeweilige Code eingetragen werden musste

Oh Gott.
Jetzt gibt es diesen Fülltext-Schwachsinn auch schon in der 
Programmierung. Vom Grundsatz "Wiederholung macht den Meister" hält man 
anscheinend nicht mehr viel.

> Informatik hab ich übrigens nicht studiert

Gut. Ich nehm alles zurück. Bin davon ausgegangen, dass dein Studium 
irgendwas mit Programmierung zu tun hatte.

von Hans (Gast)


Lesenswert?

natürlich hattem wir C++ als Prüfung
aber das waren magere 2 SWS Vorlesung und 2 SWS Übung
ich kann dein Programm was du da geschrieben hast schon nachvollziehen
aber selbst erstellen könnte ich es ohne vorgabe vom grundgerüst aus dem
stand heraus nicht.

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:
> natürlich hattem wir C++ als Prüfung
> aber das waren magere 2 SWS Vorlesung und 2 SWS Übung
> ich kann dein Programm was du da geschrieben hast schon nachvollziehen
> aber selbst erstellen könnte ich es ohne vorgabe vom grundgerüst aus dem
> stand heraus nicht.

Genau das meine ich mit 'Fülltext' und dessen Verdammung.

Das Meiste des Programms ist Standard-Routine-Kram. Wenn die Idee erst 
mal da ist, wie ich das Zeugs angehe, dann kommt bei mir das 
'Muskelgedächtnis' ins Spiel. Obiges tippen die Finger schon fast von 
alleine, ohne dass ich groß darüber nachdenken muss. Nur bekommt man 
kein 'Muskelgedächtnis' wenn man immer nur Lücken in einem Fülltext 
aufüllt (aus genau dem gleichen Grund bin ich erbitterter Gegner der 
'Mathe Hausaufgaben werden gemacht, indem man das Ergebnis auf den 
kopierten Zettel in die Punktzeile einsetzt' Praxis unserer 
Grundschulkinder)

Aber da kannst du nichts dafür. Da müsste man ein ernstes Wort mit den 
Ausbildnern reden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.