C++ array dynamisch erweitern

elektro2

Cadet 4th Year
Registriert
Feb. 2014
Beiträge
67
Hallo zusammen,

ich habe ja schon gesagt, dass ich gerade dabei bin, wieder ein bisschen meine C++ Kenntnisse aufzufrischen.

Bin leider ziemlich raus nach gut einem Jahr.

Problem: Ich bekomme als vierten wert immer nur eine Adresse aber nie den wert, den ich über cout<< einlese. Findet ihr den Fehler?

Danke im Vorraus!

Code:
#include <iostream>

using namespace std;

void addArray(int* p, int count)         // 3 Elemente sind drin, 4 sollen es nach dem Funtionsaufruf sein !
{
	int zahl;
	cout << " Welche Zahl adden?" << endl;
	cin >> zahl;

	int *temp = new int[count - 1];

	for (int i = 0; i < count - 1; i++)
	{

		temp[i] = p[i];

	}

	p = new int[count];

	for (int j = 0; j < count - 1; j++)
	{
		p[j] = temp[j];
	}

	p[count] = zahl;

	delete[] temp;
	
}

int main()
{
	int* array = new int[];

	array[0] = 20;
	array[1] = 30;
	array[2] = 40;

	addArray(array, 4);      // count soll die Anzahl der Elemente angeben, die dass array nach dem Funktionsaufruf hat!

	for (int i = 0; i < 4; i++)
	{
		cout << array[i] << endl;

	}
	system("Pause");
	cin.get();
	return 0;
}
Ergänzung ()

Ich bin auch gerade nochmal die Schleifen in Gedanken durchgegangen und denke, dass es daran nicht liegen wird.
 
elektro2 schrieb:
Code:
int main()
{
	int* array = new int[];

	array[0] = 20;
	array[1] = 30;
	array[2] = 40;

Das obige ist eine sog. "Segmentation violation". Danach stürzt das Programm höchstwahrscheinlich ab oder verhält sich unkontrollierbar.
 
ich dachte, dass mir die erste Zeile ein int array "unendlich erweiterbarer" Länge liefert.. Habe ich da einen Denkfehler gemacht? Also sogesehen eine anfangsadresse für ein Integer Array
 
elektro2 schrieb:
ich dachte, dass mir die erste Zeile ein int array "unendlich erweiterbarer" Länge liefert.. Habe ich da einen Denkfehler gemacht? Also sogesehen eine anfangsadresse für ein Integer Array

Das ist es nicht. Das dürfte der Compiler aber auch nicht durchgehen lassen. VC 2015RC sagt z.B.:
"(35): error C3078: you cannot 'new' an array of unknown bounds"
 
Ich habe das array mal standartgemäß angelegt aber es kommt trotzdem der gleiche Output.... 20, 30, 40, -44848589489 oder sowas

Code:
#include <iostream>

using namespace std;

//FUNKTION

void addArray(int* p, int count)         // 3 Elemente sind drin, 4 sollen es nach dem Funtionsaufruf sein !
{
	int zahl;
	cout << " Welche Zahl adden?" << endl;
	cin >> zahl;

	int *temp = new int[count - 1];     // Temp array für 3 Elemente erstellen

	for (int i = 0; i < count - 1; i++)
	{
     	temp[i] = p[i];                              // Werte von alten array ins temp array kopieren
    }

	p = new int[count];                         // Neues array für 4 Werte erstellen

	for (int j = 0; j < count - 1; j++)
	{
		p[j] = temp[j];                                 // Die Alten 3 Werte kopieren
	}

	p[count] = zahl;                              // Den neuen Wert ans Ende anhängen

	delete[] temp;                                  // Temp array löschen
	
}

// MAIN

int main()
{
	int array[] = { 1, 8, 20 };

	array[0] = 20;
	array[1] = 30;
	array[2] = 40;

	addArray(array, 4);      // count soll die Anzahl der Elemente angeben, die dass array nach dem Funktionsaufruf hat!

	for (int i = 0; i < 4; i++)
	{
		cout << array[i] << endl;
    }
	system("Pause");
	cin.get();
	return 0;
}
 
Zuletzt bearbeitet:
Du musst dem new() Operator auch sagen wie groß dieses Array dann sein soll. Du hast keinen unendlichen Speicher, also kann new() auch nicht unendlich Speiche allozieren.
Und wenn du die Größe nachträglich ändern wolltest, müsstest du den neuen größeren Speicherplatz allozieren, alle Daten umkopieren und das alte Array mit delete() löschen.

Du hast ein Array mit 3 Elementen angelegt und rufst 4 Elemente ab. Merkst du was?
 
aber genau diese Umkopieren mache ich doch in meiner Funktion.. oder nicht?

Ich habe meinen Code mal kommentiert :)
 
Zuletzt bearbeitet:
elektro2 schrieb:
Ich habe das array mal standardgemäß angelegt aber es kommt trotzdem der gleiche Output.... 20, 30, 40, -44848589489 oder sowas

Ja, Du hast ein array für drei Elemente angelegt. Das vierte Element ist undefiniert, der Speicherort nicht vorgesehen und es kann Dein Programm zum Absturz bringen ("stack fault").
 
Wie bereits erwähnt, muss die Arraygröße zur Compilerzeit bekannt sein.

Edit zum besseren Verständnis: Falls du ein Array erzeugst, so liegt es irgendwo an einer festen Adresse im Speicher. Es kann sein, dass direkt danach andere Daten im Speicher liegen. Falls du nun dein Array erweiterst (in dem Sinne wie du es dir vorstellst, also dass das Array hinten um ein Feld größer wird), so entsteht ein Problem. Das Betriebssystem weiß nun nicht, wie es weiter vorgehen soll, da ein Konflikt für den benötigten Speicher (und deren Adressen) entsteht. Deswegen ist die Erzeugen eines neuen Arrays erforderlich, da damit das System neuen, freien Speicher sucht und reserviert.
 
Zuletzt bearbeitet:
elektro2 schrieb:
aber genau diese Umkopieren mache ich doch in meiner Funktion.. oder nicht?

Nein. Deine Variable array in main und die Variable array in AddArray haben nix miteinander mehr zu tun nachdem du array=new() aufgerufen hast. Das neue array zeigt in eine total andere Speichergegend und am Ende hast du einfach nur ein Speicherleck produziert. Tip: call by reference wenn du sowas machen willst.
 
aber das Temp array braucht doch nur 3 Werte.
Ergänzung ()

Ich bin total durcheinander :D Also ich dachte, dass ich dadurch, dass ich das array übergebe, einen Zeiger auf das erste Element von array übergebe. Warum hat dann das array ( in der Funktion ist es p ) nichts mehr mit meinem alten array zu tun?
 
Zuletzt bearbeitet:
Genau, es braucht nur drei Werte, weil es die Größe des alten Arrays speichert/angibt. Intuitiver (für uns) wäre es, wenn du beim Funktionsaufruf das Array und dessen aktuelle Größe übergibst. Ist imo "logischer", da beide Werte zu einer "Sache" gehören. ;)
 
Das Problem ist das hier:

20. p = new int[count]; // Neues array für 4 Werte erstellen

Damit erzeugst du zwar ein neues Array mit 4 Elementen und weist das der Variable p zu, das hat aber keine Auswirkungen auf das Array in der Mainfunktion, da der Zeiger by Value übergeben wurde. Du müsstest int** p übergeben (und die anderen Stellen auch entsprechend anpassen), wenn meine C Kenntnisse noch nicht ganz eingerostet sind.

Wobei ich mit so Speicherallokation in Unterfunktionen vorsichtig wäre... das Zeug muss ja irgend wann auch wieder aufgeräumt werden...
 
Ich habe den Code mal umgeschrieben. Ich hoffe, dass er nun besser verständlich ist. Funktionieren tut er immer noch nicht :/


Code:
#include <iostream>

using namespace std;

//FUNKTION

void addArray(int* p, int count)         // 3 Elemente sind drin,
                                         //4 sollen es nach dem Funtionsaufruf sein !
{
	int zahl;
	cout << " Welche Zahl adden?" << endl;
	cin >> zahl;

	
	
	int *temp = new int[count];

	for (int i = 0; i < count ; i++)
	{
     	temp[i] = p[i];
    }

	p = new int[count+1];

	for (int j = 0; j < count ; j++)
	{
		p[j] = temp[j];
	}

	p[count+1] = zahl;

	delete[] temp;
	
}

// MAIN

int main()
{
	int array[] = { 20, 30, 40 };

	addArray(array, 3);      // count soll die derzeitige Anzahl der Elemente vor dem Funktionsaufruf sein

	for (int i = 0; i < 4; i++)
	{
		cout << array[i] << endl;
}
	system("Pause");
	cin.get();
	return 0;
}
 
Zuletzt bearbeitet:
Du übergibst in Zeile 43 eine Kopie von deinem Array "array". Darauf arbeitest du in der Unterfunktion.
Nach dem du aber fertig bist in der Unterfunktion springt das Programm zurück zur main-Funktion. Da du aber der Unterfunktion eine Kopie von deinem Array übergeben hast, wurde das Array aus der main-Funktion nie verändert.
Ergo: Du musst einen Pointer auf dein Array übergeben (damit die Unterfunktion weiß, wo dein zu behandelnde Array im Speicher liegt) und dann auf deren Speicheradressen arbeiten. So arbeitest du in beiden Funktionen auf dem selben Array.

EDIT: Oder bin ich nun auch schon zu lange aus C++ raus? :)
 
Gibt es dafür überhaupt eine Lösung oder würde man das ganz anderes machen? Ich selber würde das Problem natürlich über einen Vektor mit push_back lösen, aber ich wollte mich wirklich mal wieder den Pointer widmen, weil das ein wichtiges Thema in c++ ist :)
Ergänzung ()

Klappt auch nicht, obwohl ich die Referenz übergebe :/ .. Ich verzweifel

Code:
#include <iostream>

using namespace std;

//FUNKTION

void addArray(int** p, int count)         // 3 Elemente sind drin,
                                         //4 sollen es nach dem Funtionsaufruf sein !
{
	int zahl;
	cout << " Welche Zahl adden?" << endl;
	cin >> zahl;

	
	
	int *temp = new int[count];

	for (int i = 0; i < count ; i++)
	{
     	temp[i] = *p[i];
    }

	*p = new int[count+1];

	for (int j = 0; j < count ; j++)
	{
		*p[j] = temp[j];
	}

	*p[count+1] = zahl;

	delete[] temp;
	
}

// MAIN

int main()
{
	int array[] = { 20, 30, 40 };
	
	int* pointer = array;

	addArray(&pointer, 3);      // count soll die derzeitige Anzahl der Elemente vor dem Funktionsaufruf sein

	for (int i = 0; i < 4; i++)
	{
		cout << array[i] << endl;
    }
	system("Pause");
	cin.get();
	return 0;
}
 
elektro2 schrieb:
Ergänzung ()

Klappt auch nicht, obwohl ich die Referenz übergebe :/ .. Ich verzweifel

Nicht verzweifeln. Du hast es doch schon beinahe. Ich habe nur ein paar random-changes in Deinem Code gemacht - es geht!
Code:
#include <iostream>
using namespace std;


 int addArray(int** p, int count_alt, int neue_zahl)     // n Elemente sind drin,
{                                                           // n+1 sollen es nach 
 int *temp = new int[count_alt + 1];   // dem Funktionsaufruf sein !
 for (int i = 0; i < count_alt; i++) {
    temp[i] = (*p)[i];
 }
 temp[count_alt] = neue_zahl;
 delete [] *p;
 *p = temp;
 return count_alt + 1;
}

 int main()
{
 int groesse = 3;
 int *array = new int[groesse];
 array[0] = 20, array[1] = 30, array[2] = 40;

 int neue_zahl;
 cout << " Welche Zahl adden?" << endl; fflush(stdout);
 cin >> neue_zahl;
 // count soll die derzeitige Anzahl der Elemente vor dem Funktionsaufruf sein
 groesse = addArray(&array, groesse, neue_zahl);

 for (int i = 0; i < groesse; i++) {
    cout << array[i] << endl;
 }
 cout << endl;
 cin.get();

 return 0;
}
 
WOW DAnke !!! es klappt wirklich. Ich werde nun versuchen nachzuvollziehen, was du da alles geändert hast :) danke schonmal

Eine Frage habe ich noch :) Ich sehe gerade, dass du im Gegensatz zu mir einen int zurückgegeben hast und dadurch direkt die Größe von dem array in der Main geändert hast. Ist das ein muss oder ist das einfach nur "schöner"?:)

Was wäre z.b, wenn man die Größe einfach auf 100 legt, also groesse= 100; ???
 
Zuletzt bearbeitet:
Zurück
Oben