Hi,
du hast da echt grundlegende Dinge bei der Nutzung von Zeigern nicht verstanden. Du brauchst ein verünftiges Buch, z.B.:
http://www.amazon.de/C-Kompendium-D...856047?ie=UTF8&s=books&qid=1194306948&sr=1-11
Dieses Buch ist zwar ein dicker Brocken und auch eher ein Nachschlagewerk, hast du aber genügend Ehrgeiz ist es zu packen. Alles, was du nicht verstehst, bei Google einfach nachschlagen. Oder noch zusätzlich ein Einstiegsbuch holen.
Nun zu deinem Code. Es sei gesagt, dass ich mich nur auf die Fehler im enthaltenen Code konzentriere und nicht auf den Programmierstil achte (is nicht bös gemeint, aber übe immer weiter und mit mehr Erfahrung schreibst du besseren Code - aber wie gesagt, lerne wie oben erwähnt, deine Werkzeuge richtig kennen).
Code analyse:
Code:
#include <iostream>
using namespace std;
int main()
{
int* palt;
int* pneu;
char status= 'j';
int counter = 0;
int swap;
int counter2;
while(status=='j') {
cout<<"Geben Sie die "<<counter+1<<". Zahl ein: ";
cin>>swap;
if(counter!=0)
delete[] palt;
palt=new int[counter+1];
counter2=0;
while(counter2<counter) {
palt[counter2] = pneu[counter2];
counter2++;
}
palt[counter2]=swap;
if(counter!=0)
delete[] pneu; // <- [COLOR="Red"]hier stürzt es im 2. Durchlauf der Schleife ab[/COLOR]
counter++;
pneu=new int[counter];
pneu=palt; // <- [COLOR="Red"]dies ist der Grund für den Absturz[/COLOR]
cout<<"Wollen Sie eine Zahl eingeben? j/n : ";
cin>>status;
}
cout<<endl<<endl;
for( int a=0; a<counter; a++)
cout<<pneu[a]<<" | ";
return 0;
}
Der Grund des Absturzes (rot markiert) ist, dass du versuchst den Speicherplatz freiugeben, worauf ein Zeiger zeigt. Diesen Speicherplatz hast du aber schon vorher freigegeben. Wie fragst du dich? Siehe die untere rot markierte Stelle, denn dort kopierst du NICHT den Wert des Speicherplatzes worauf palt zeigt einfach zu der entsprechenden Stelle in pneu, sondern die ADRESSE dieses Speicherplatzes weist du palt zu. D.h. wohin palt zeigt, zeigt nun auch pneu. Dementsprechend zeigt pneu auf denselben Wert wie auch palt (aber auch an DIESELBE Adresse, wo der Wert liegt - und hier ist das Problem).
Im nächsten Durchlauf löschst du palt und legst es neu an - was passiert, erkläre ich dir kurz: palt und pneu haben zuvor auf dieselbe Adresse x1 gezeigt, an der der Wert y1 abgelegt ist. Nun löschst du palt, d.h. du gibst den Speicherplatz mit der Adresse x1 frei (wo auch der Wert y1 nun freigegeben ist). D.h. widerum, dass Windows diesen Speicherplatz nach belieben ändern kann - schließlich ist es frei. Für palt wird ein neuer Speicherplatz angelegt (mit anderer Adresse), nun zeigt es woanderhin (d.h. pneu wird davon nicht beeinflusst).
Wenn du nun hinterher pneu löschst / freigibst, dann gibt es einen Absturz, denn der Speicherplatz worauf es zeigt ist schon eigentlich freigegeben - du hast ja palt vorher freigegeben, welches an dieselbe Stelle gezeigt hat. Soetwas kann Folgen haben: Du hast keine Rechte mit pneu mehr an die freigegebene Stelle zuzugreifen - bei Win 98 / Linux / auch WinXP, wenn du das Programm als Release compilierst, hättest du eventuell einfach in einen nicht reservierten Speicherplatz (im RAM) geschrieben, wo u.U. Betriebssystemdateien liegen -> System wird instabil, Systemabsturz möglich (keine Sorge, bei Neustart sollte alles wieder ok sein). Aber stell dir mal vor, deine Software ist eine Serversoftware oder Wichtigeres...
Nun, den Fehler kann man zwar beseitigen, indem man anstatt
diesen Code schreibt:
Code:
*pneu=*palt; // Kopiere Inhalt der Adresse worauf palt zeigt in den Inhalt der Adresse, worauf pneu zeigt
Jedoch wird dies nur dafür sorgen, dass das Programm an dieser Stelle nicht mehr abstürzt, aber mehr auch nicht. Das Programm wird nicht so laufen, wie du es dir wünschst. Es gibt einfach zu viel zu erzählen, warum das Programm so nicht läuft. Dies tue ich hier nicht. Die Fehler wirst du selbst erkennen, wenn du dich mehr um Grundlagen von Zeigern bzw. überhaupt von C/C++ kümmerst. Du darfst dein Engagement nicht verlieren bzw. musst immer am Ball bleiben.
Tipp:
Ich erkenne die Problematik des Programms. Du weißt nicht, wieviele Zahlen der Benutzer eingeben möchte, demnach weißt du auch nicht, wieviel Speicherplatz du reservieren sollst.
Nun, am besten Wäre, wenn du den Benutzer fragst, denn dann kannst du direkt auf Arrays setzen. Denn je weniger Zeiger, desto besser, was aber nicht heißt, dass du nicht lernen sollst mit ihnen umzugehen. Warum besser? Mit Zeigern kann man leicht Fehler machen, die zu Ausnahmefehlern führen und das gesamte Programm zum Absturz bringen können.
Wenn du den Nutzer aber nicht abfragen möchtest, dann würde ich vorschlagen, dass du zunächst einen Zeiger mit 10 Elementen erstellst (dynamische Speicherverwaltung ist leider mit Arrays an sich nicht möglich). Sind diese nach 10 Abfragen voll und der Benutzer möchte nicht aufgeben, dann erweiterst du den Speicherbereich wieder um 10 Elemente (oder eben nach einer anderen Gleichung). So brauchst du nicht in jedem Durchlauf die Inhalte umzukopieren und es spart Zeit, was sich auch im Ablauf deines Programms bemerkbar macht.
Hier ein Programm, welches die Funktion erfüllt, der du ersehnst. Schaue es dir gut an. U.U. gibt es eine elegantere Lösung:
Code:
#include <iostream>
using namespace std;
int main() {
int size = 10;
int* nums1 = new int[size]; // Array von Zahlen
int* nums2 = NULL; // Ersatzarray für Erweiterungen
int buff = 1; // Eingabepuffer
int whichPtr = 1; // Welcher Zeiger ist aktiv, nums1 oder nums2?
int i,j = 0; // Zeigervariable
cout << "Um zu beenden >0< eingeben und >Enter< druecken." << endl << endl;
for( i=0; true; i++ ) {
// Zahl abfragen, prüfen, ob beenden
cout << "Bitte " << i+1 << ".Zahl eingeben: ";
cin >> buff;
cin.clear();
cin.ignore(100,'\n');
if( buff == 0 )
break;
// Je nachdem in welcher Árrayzeiger aktiv ist
if( whichPtr == 1 )
nums1[i] = buff;
else
nums2[i] = buff;
// Arrayzeigergrenzen überprüfen, u.U. erweitern
if ( i == (size-1) ) {
if( whichPtr == 1 ) {
// nums2 erstellen +10 größer nums1
nums2 = new int[size+10];
// Array umkopieren
for( j=0; j<size; j++ )
nums2[j] = nums1[j];
// Nums1 löschen
delete[] nums1;
nums1 = NULL;
whichPtr = 2; // Aktuellen Zeiger umstellen
size += 10; // size=size+10
}
else {
// nums1 erstellen +10 größer nums2
nums1 = new int[size+10];
// Array umkopieren
for( j=0; j<size; j++ )
nums1[j] = nums2[j];
// Nums2 löschen
delete[] nums2;
nums2 = NULL;
whichPtr = 1; // Aktuellen Zeiger umstellen
size += 10; // size=size+10
}
}
}
// Eingaben ausgeben
cout << endl;
cout << "Eingegebene Zahlen:" << endl;
if( whichPtr == 1 )
for ( j=0; j<i; j++ )
cout << nums1[j] << " ";
else
for ( j=0; j<i; j++ )
cout << nums2[j] << " ";
// Zeiger löschen, wenn nicht NULL
if( nums1 != NULL )
delete[] nums1;
if( nums2 != NULL )
delete[] nums2;
return 0;
}