Hi Leute!
Ich suche schwierige Aufgaben zum selbst "durchrechnen", also ohne
Compiler/Debugger der Form von sowas hier:
int x = 11, y = 20, w = 3;
y = --w*10;
x -= ++y/7+4;
Habt ihr da ein paar Aufgaben für mich? Ich weiß, dass das jetzt
durchaus blöd klingt, aber da ich das grad am Lernen bin und mein Buch
dazu leider keine Übungsaufgaben ausspuckt hab ich keine Ideen wo ich
das jetzt herbekomme. Natürlich kann ich mir selber Aufgaben stricken,
aber das bringt mir nix, denn die Aufgaben sind dann nur so schwer so
weit eben mein "Horizont" reicht. Aber: Wenn jemand mehr kann als das
was ich weiß, wird mich das mehr fordern und ich kann dabei noch mehr
lernen...
Könnt ihr mir helfen?
Es gibt hier keine 'schwierigen' Aufgaben.
Bei x++ setzt du in die weitere Berechnung den 'alten' Wert von x in die
Berechnung ein. Bei ++x setzt du den bereits erhöhten Wert ein.
Ditto sinngemäss für --
Da nach schwierigen Berechnungen zu fragen, ist so wie wenn du nach
'schwierigen' Beispielen für Formeln suchst, in denen eine Wurzel
vorkommt. Die Berechnung einer Wurzel ist immer gleich, egal in welchem
Zusammenhang sie vorkommt.
2*sqrt(3) ist nicht schwieriger zu berechnen als sqrt( a*a + b*b )
So auch hier: das x++ bzw ++x wird immer gleich behandelt. Einmal geht
der alte Wert in die Berechnung weiter ein, das andere mal der bereits
erhöhte.
Das einzige was man sich merken muss. Wann genau die Erhöhung von x
abgeshchlossen ist und wann x daher seinen neuen Wert bekommt, ist nicht
weiter definiert. Es muss vor dem nächsten Sequenz-Punkt passiert sein,
aber wo genau, das darf der Compiler machen wie er will. Daher darf in
so einem Fall das x nur einmal in diesem Statement vorkommen.
x = x++;
hat daher undefiniertes Verhalten.
Genauso wie
j = x++ + x++;
oder gar
j = ++x++;
oder
printf( "%d %d", x++, x++ );
oder andere Variationen derselben Grundidee.
Und die restlichen 'unübersichtlichen' Kombinationen, sind mehr Übungen
in der Rangfolge der Operatoren, als das sie etwas mit ++ an sich zu tun
haben. In
int i = 5;
int* p = &i;
*p++;
was wird erhöht? Der Pointer oder der Wert auf den der Pointer zeigt
oder gar beides? Ist das daher gleichbedeutend mit
(*p)++;
oder
*(p++);
oder
(*(p++)++);
was wird erhöht? Der Pointer oder der Wert auf den der Pointer zeigt
9
oder gar beides? Ist das daher gleichbedeutend mit
10
11
(*p)++;
12
oder
13
*(p++);
14
oder
15
(*(p++)++);"
Also ich hab mir dazu jetzt Gedanken gemacht und bin zu dem Entschluss
gekommen, dass
*p++; den Pointer erhöht, nicht aber den Wert.
Das wäre doch dann gleichbedeutend mit: (*p)++.
*(p++), erhöht doch dann den Wert, oder?
Bei (*(p++)++) wird zuerst der Wert erhöht und dann der Pointer, oder?
Ich hab da mal noch eine Aufgabe bei der Ich mehrere Probleme hab:
1
charzk[2][6]={"Hallo","Welt"};
2
char*p,*q;
3
intj=3;
4
5
6
p=&zk[0][0];
7
q=p+6;
8
*(p++)=*q;
9
*(p+1)='s';
10
zk[0][j]='\0';
11
*q='g';
12
*(p+7)='h';
Die erste Zeile is ja klar. Die Adresse des Arrays an den Stellen 0,0
wird in dem Pointer p abgelegt.
In der zweiten Zeile wird nun im Pointer q die Adresse von p + 6
gespeichert. Hier hab ich dann schon das erste Problem: Wird hier von 0
(für die erste Adresse) losgezählt, oder von 1? Laut Compiler aber von
0, da ich nämlich nach der Addition von 6 auf das erste Element der
zweiten Zeile des 2-dim. Arrays zeige, also 7. 0 - 6 entspricht ja 7
Schritten.
In der dritten Zeile wird nun der Inhalt vom Pointer q auf p
Dereferenziert. Nun wird der Pointer p inkrementiert und zeigt auf das
Element 2 an der Stelle 1 im Array für die Zeile 1 bzw. 0.
In der vierten Zeile wird die Adresse des Pointers p um 1 inkrementiert
und danach an diese neue Adresse (also Element 3 an der Stelle 2 im
Array) das 's' geschrieben.
In der fünften Zeile wird in die Zeile 1 bzw. in die 1. Dimension des
Arrays die terminierende Null geschrieben.
In der sechsten Zeile wird an die Adrese (hier 2. dim. des Arrays,
Element 1 an der Stelle 0) ein 'h' geschrieben.
Nun zur siebten Zeile: Hier wird doch nun der Pointer p um 7 erhöht. P
zeigt noch immer auf das 3. Element an der Stelle 2 in der 1. dim. des
Arrays. Hier soll ich nun um 7 erhöhen. Muss ich da jetzt von 0 - 7
zählen oder von 1 - 7?
In der zweiten Zeile, in der ich ja q erhöht habe, hab ich von 0 an
begonnen zu zählen. Wenn ich das nun in der 7. Zeile auch mache, dann
komm ich um eine Stelle zu weit drüber... Was stimmt denn nun?
Überlege mal was *(p+0) bedeutet und welche Stelle das ist.
Und bei *(p+7) ist es egal ob du bei 0 oder 1 anfängst zu zählen, denn
du musst 7 Stellen weiter gehen.
Hast du dir denn die Variablen mal ausgegeben oder im Debugger
angesehen?
Nebenbei ist der erste Arrayindex die 0.
Hans Wurst schrieb:> In der vierten Zeile wird die Adresse des Pointers p um 1 inkrementiert> und danach an diese neue Adresse (also Element 3 an der Stelle 2 im> Array) das 's' geschrieben.
*(p+1) verändert p nicht. So wie bei i = j + 3; j auch nicht geändert
wird.
Darum bist du immer noch an der 2. Stelle.
Dann auch für dich der Hinweis auf die gleiche Diskussion in einem
anderem Forum: http://www.c-plusplus.de/forum/280958
Hans Wurst schrieb:> char *p, *q;> int j = 3;>>> *(p++) = *q;> *(p+1) = 's';> zk[0][j] = '\0';> *q = 'g';> *(p+7) = 'h';> [/c]>>>
Also:
char zk[2][6] = {"Hallo", "Welt"};
p = &zk[0][0];
> Die erste Zeile is ja klar. Die Adresse des Arrays an den Stellen 0,0> wird in dem Pointer p abgelegt.
genau
q = p + 6;
> In der zweiten Zeile wird nun im Pointer q die Adresse von p + 6> gespeichert.
Es wird nicht die Adesse 'von' p+6 gespeichert. Denn p+6 ist ein
arithmetischer Ausdruck und der hat keine Adresse. Es wird einfach der
um 6 erhöhte Inhalt von p in q gespeichert.
> Hier hab ich dann schon das erste Problem: Wird hier von 0> (für die erste Adresse) losgezählt, oder von 1?
In C wird IMMER von 0 weggezählt. Egal bei was.
*(p++) = *q;
> In der dritten Zeile wird nun der Inhalt vom Pointer q auf p> Dereferenziert.
q ird dreferenziert und das Zeichen, das man so erhält wird dort
abgelegt, wohin p zeigt.
*(p+1) = 's';
> In der vierten Zeile wird die Adresse des Pointers p um 1 inkrementiert> und danach an diese neue Adresse (also Element 3 an der Stelle 2 im> Array) das 's' geschrieben.
Da wird nichts inkrementiert. inkrementieren bedeutet auch
zurückschreiben. Und hier wird p nicht verändert.
's' wird an der Adresse abgelegt, die durch p+1 erhalten wird
zk[0][j] = '\0';
> In der fünften Zeile wird in die Zeile 1 bzw. in die 1. Dimension des> Arrays die terminierende Null geschrieben.
kann man so sagen. da j 3 ist, wird an die 4.te Array Position eine '\0'
geschrieben
*q = 'g';
> In der sechsten Zeile wird an die Adrese (hier 2. dim. des Arrays,> Element 1 an der Stelle 0) ein 'h' geschrieben.
Da q noch nicht verändert wurde, denke ich hast du das richtig gesehen.
*(p+7) = 'h';
> Nun zur siebten Zeile: Hier wird doch nun der Pointer p um 7 erhöht. P> zeigt noch immer auf das 3. Element an der Stelle 2 in der 1. dim. des> Arrays. Hier soll ich nun um 7 erhöhen. Muss ich da jetzt von 0 - 7> zählen oder von 1 - 7?
0.
IMMER 0. In C wird immer bei 0 angefangen zu zählen.
> komm ich um eine Stelle zu weit drüber... Was stimmt denn nun?
Wenn du den Überblick verlierst, hilft es mitzuzeichen.
Mal dir ein entsprechend großes 2D-Gitter auf und spiel Computer.
Verfolge welche Werte p hat, indem du einen mit 'p' beschrifteten Pfeil
in dieses Gitter zeigen lässt und den du umzeichnest wann immer sich p
verändert.
Wenn du denkst jetzt hast du es, dann überlg dir, wie du
programmtechnisch verifizieren kannst, ob auch tatsächlich das passiert
ist, was du denkst das passiert ist.
"In C wird IMMER von 0 weggezählt. Egal bei was."
Wenn ich das jetzt im ersten Fall tu, dann gehe ich aber doch 7
Schritten, oder? Ich zähle quasi 0,1,2,3,4,5,6.
Wenn ich im zweiten Fall bei 2 stehe, und dann p = p + 7 machen soll,
dann müsste ich ja 8 Schritte machen, wenn ich von der 0 weg zählen
soll. Aber das ist doch dann nicht mehr richtig...
Bei Schritten bewegst du dich weiter. Bei 0 Schritt bleibst du wo du
bist.
Unterscheide zwischen Index (ab 0) und Position (sprachlich ab 1.).
Nochmal: bei int a[10]; ist das Element a[0] an der 1. Position im Feld
(Index 0). Um zu a[2] zu gelangen musst du 2 weiter zählen.
> Wenn ich das jetzt im ersten Fall tu, dann gehe ich aber doch 7> Schritten, oder? Ich zähle quasi 0,1,2,3,4,5,6.
Nein, das sind zwar sieben verschiedene Indizes, aber nur sechs
Schritte:
0 --> 1 \
1 --> 2 |
2 --> 3 |
3 --> 4 }- 7 Schritte
4 --> 5 |
5 --> 6 |
6 --> 7 /
-> du kommst bei 7 an nach 7 Schritten
char zk[2][6] = {"Hallo", "Welt"};
char *p, *q;
int j = 3;
p = &zk[0][0];
q = p + 6;
*(p++) = *q;
*(p+1) = 's';
zk[0][j] = '\0';
*q = 'g';
*(p+7) = 'h';
wie ich schon sagte:
Es hilft sich die Dinge aufzumalen
Mal dir ein 2*6 Array auf
1
+---+---+---+---+---+---+
2
| H | a | l | l | o | \0|
3
+---+---+---+---+---+---+
4
| W | e | l | t | \0| |
5
+---+---+---+---+---+---+
und jetzt spielen wir Computer
1
p=&zk[0][0];
Variable p einrichten und dafür sorgen, dass sie auf zk[0][0] zeigt
1
p
2
+-----+
3
| o------+
4
+-----+ |
5
|
6
+-----+
7
v
8
+---+---+---+---+---+---+
9
| H | a | l | l | o | \0|
10
+---+---+---+---+---+---+
11
| W | e | l | t | \0| |
12
+---+---+---+---+---+---+
1
q=p+6;
In gleichem Masse ein Variable q einrichten, die 6 Felder von p aus
gesehen weiter zeigt.
Wo ist das? Na zählen wir doch einfach. Dort wo p hinzeigt ist 0, denn
wenn man sich von p aus um 0 Schritte weiterbewegt, ist man immer noch
bei p.
1
+---+---+---+---+---+---+
2
| 0 | 1 | 2 | 3 | 4 | 5 |
3
+---+---+---+---+---+---+
4
| 6 | | | | | |
5
+---+---+---+---+---+---+
dort soll also das q hinzeigen
1
p
2
+-----+
3
| o------+
4
+-----+ |
5
|
6
+-----+
7
v
8
+---+---+---+---+---+---+
9
| H | a | l | l | o | \0|
10
+---+---+---+---+---+---+
11
| W | e | l | t | \0| |
12
+---+---+---+---+---+---+
13
^
14
|
15
+------+
16
|
17
q |
18
+----+ |
19
| o------+
20
+----+
1
*(p++)=*q;
was soll passieren. Zunächst die rechte Seite der Zuweisung:
Vom Feld, auf das q zeigt, soll der Wert geholt werden. In die Zeichnung
schauen, das ist ein 'W'.
Was soll damit passieren - jetzt wird die rechte Seite der Zuweisung
interessant.
*(p++)
Das sind 2 Operation. Die Hauptoperation ist *p. Das Zeichen soll also
dort abgelegt werden, wo p hinzeigt. Und als Nebenoperation wird p um 1
Feld weitergestellt. Wobei dieses Weiterstellen die Speicheroperation
nicht beeinflusst. Zum Speichern gilt der Wert, den p zu Beginn der
Operation hatte (wegen Postinkrement)
Nach der Hauptoperation sieht die Sache daher so aus
1
p
2
+-----+
3
| o------+
4
+-----+ |
5
|
6
+----+
7
v
8
+---+---+---+---+---+---+
9
| W | a | l | l | o | \0|
10
+---+---+---+---+---+---+
11
| W | e | l | t | \0| |
12
+---+---+---+---+---+---+
13
^
14
|
15
+------+
16
|
17
q |
18
+----+ |
19
| o------+
20
+----+
und nach dem Postinkrement, sind wir hier:
1
p
2
+-----+
3
| o------+
4
+-----+ |
5
|
6
+-+
7
v
8
+---+---+---+---+---+---+
9
| W | a | l | l | o | \0|
10
+---+---+---+---+---+---+
11
| W | e | l | t | \0| |
12
+---+---+---+---+---+---+
13
^
14
|
15
+------+
16
|
17
q |
18
+----+ |
19
| o------+
20
+----+
1
*(p+1)='s';
rechts vom = steht ein einzelnes Zeichen. Ein 's'.
Was soll damit geschehen?
*(p+1)
Aha. Also: von p ausgehend 1 Feld weitergehen und dort dann das s
ablegen.
Verändert sich p selber? Nein. Davon steht nichts in der Anweisung
Wo ist p+1?
Zählen wir wieder. Ausgehend von p
1
+---+---+---+---+---+---+
2
| | 0 | 1 | | | |
3
+---+---+---+---+---+---+
4
| | | | | | |
5
+---+---+---+---+---+---+
damit wird das 's' dort abgespeichert:
1
p
2
+-----+
3
| o------+
4
+-----+ |
5
|
6
+-+
7
v
8
+---+---+---+---+---+---+
9
| W | a | s | l | o | \0|
10
+---+---+---+---+---+---+
11
| W | e | l | t | \0| |
12
+---+---+---+---+---+---+
13
^
14
|
15
+------+
16
|
17
q |
18
+----+ |
19
| o------+
20
+----+
1
zk[0][j]='\0';
das ist leicht. j hat den Wert 3. Also einfach das Feld [0][3] aufuschen
und dort ein \0 reinschreiben
1
p
2
+-----+
3
| o------+
4
+-----+ |
5
|
6
+-+
7
v
8
+---+---+---+---+---+---+
9
| W | a | s | \0| o | \0|
10
+---+---+---+---+---+---+
11
| W | e | l | t | \0| |
12
+---+---+---+---+---+---+
13
^
14
|
15
+------+
16
|
17
q |
18
+----+ |
19
| o------+
20
+----+
1
*q='g';
dort wo q hinzeigt, in das Feld kommt ein 'g' hinein.
1
p
2
+-----+
3
| o------+
4
+-----+ |
5
|
6
+-+
7
v
8
+---+---+---+---+---+---+
9
| W | a | s | \0| o | \0|
10
+---+---+---+---+---+---+
11
| g | e | l | t | \0| |
12
+---+---+---+---+---+---+
13
^
14
|
15
+------+
16
|
17
q |
18
+----+ |
19
| o------+
20
+----+
1
*(p+7)='h';
und zum Schluss nochmal eine ähnliche Operation wie vorhin. Ausgehend
von p 7 Felder weiterzählen und dort ein 'h' hineinschreiben. Wo ist
das? (Dort wo p hinzeigt ist wieder 0)
1
+---+---+---+---+---+---+
2
| | 0 | 1 | 2 | 3 | 4 |
3
+---+---+---+---+---+---+
4
| 5 | 6 | 7 | | | |
5
+---+---+---+---+---+---+
dort muss also ein 'h' hinein.
1
p
2
+-----+
3
| o------+
4
+-----+ |
5
|
6
+-+
7
v
8
+---+---+---+---+---+---+
9
| W | a | s | \0| o | \0|
10
+---+---+---+---+---+---+
11
| g | e | h | t | \0| |
12
+---+---+---+---+---+---+
13
^
14
|
15
+------+
16
|
17
q |
18
+----+ |
19
| o------+
20
+----+
Wie schon gesagt: einfach mal ein bischen mitzeichnen. Dann verlieren
diese abstrakten Dinge gleich ein wenig von ihrem Schrecken.
DirkB schrieb:> Darum bist du immer noch an der 2. Stelle.> Dann auch für dich der Hinweis auf die gleiche Diskussion in einem> anderem Forum: http://www.c-plusplus.de/forum/280958
Nett. Ich glaube der Herr M.... will uns verarschen!
Nachdem man in darauf hingewiesen hat dass er seine ähh... "Ergüsse" [1]
[2] vielleicht nicht unter richtigem Namen posten sollte lässt er seinen
Account (Nickname: Bandchef) löschen, meldet sich unter anderem Namen
neu an und macht munter weiter. Vom Crossposting reden wir gar nicht
erst.
[1] Beitrag "Array als Parameter in einer Funktion"
[2] Beitrag "Fragen zur Rekursion"