mehrdimensionales char* array
-
Hallo,
ich bin gerade dabei mich wieder mit den C-Grundlagen zu befassen und stehe vor einer Aufgabe, zu der ich weder in meinen Büchern noch online eine logisch erklärbare Hilfe gefunden habe - oder ich bin einfach nur zu doof.
Im Prinzip mehr als trivial:
Ich wollte eine Art String-Tabelle anlegen.
Problem:
Sie muss aus char* bestehen und sie muss global sein. Weiterhin weiß ich nicht wie lange die einzelnen Werte sind und wie lange die Tabelle werden muss, sprich wieviel "Einträge" sie hat.
Ich dachte dabei immerwieder an ein mehrdimensionales Array, aber wie soll ich das global anlegen wenn ich keine Daten habe, wie groß es werden soll?
Übrigens würde ich à la tabelle[i]="..." zugreifen können...
Danke für die Hilfe,
grüße Simon
-
Hallo,
du möchtest also ein dynamisches Array aus C-Strings.
Dazu nimmst du ein Array aus char*.Betrachte nun zuerst die Elemente des Arrays.
Das sind char* also Pointer auf Speicher.
Erstelle dafür Hilfsfunktionen und bediene dich bei der StdLib, um Funktionen zu haben, die Speicher für Strings neu reservieren etc.
Wenn ein String dazukommt, wird Speicher für ihn erstellt mit malloc.
Dann hast du ja von malloc die Adresse des neuen Strings.
Den legst du in das Array ab.
Löscht du den String, musst du den Speicher freigeben und dann setzt du das entsprechende Feld des Arrays auf NULL.
Klar soweit?Ok, nun muss aber noch das Array wachsen und schrumpfen.
Nimm dazu auch wieder eigene Funktionen, die wenn z.B. das Array um eins wachsen soll, neuen Speicher reserviert und das alte Array in das Neue kopiert und dann den Speicher des Alten freigibt (aber nicht den Speicher, auf den seine Arrays zeigen).
Wenns um Performance geht, wird es oft so gemacht, dass das Feld nicht um 1 sondern immer um 100 Einträge oder so wächst und erst wenn es voll ist, wird neu erweitert.Wie gesagt, der Kniff besteht darin, das ganze soweit aufzuteilen, dass du später nur zwei Hauptfunktionen aufrufen musst.
Einmal AddToArray(char* String) und einmal DelFromArray(int Nr).Mach am besten erstmal ein Array, das aus 100 Pointern auf char besteht.
Wenn du damit dann umgehen kannst (also Funktionen hast, die Strings erstellen und deren Adressen in die Felder schreiben können, mit Prüfung, ob noch Platz ist etc.)
dann kannst du dich später daran machen, statt auf 100 festgelegt zu sein, das auch dynamisch wachsen zu lassen.Ist alles wirklich net so trivial und sehr fehleranfällig, aber wenn du das erst einmal gemeistert hast, bist du in Sachen Pointer und Speicherverwaltung fit wie ein Turnschuh...
-
PCMan, du brauchst realloc()
-
Ich hab zwecks Lerneffekt das auch mal probiert vorerst nur mit Integern und Eindimensional.
Nur woher weiß ich jetzt obs klappt oder nicht ?!?
Und 2te Frage wie ruf ich malloc fuer ein 2-Dimensionales Array auf?char *str[20]=malloc(sizeof(char)); //Wenn ich Strings der Länge 20 einlesen will
so?
Gruß HiFish#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { int x=1,i=0,j=1; int zw=0; int *ar=(int *)malloc(sizeof(int)); int *zwar; while(x) { scanf("%d",&zw); if(zw==1001) { x=0; free(ar); }else if(j==i) { j+=10; zwar=realloc(ar,j*sizeof(int)); ar=zwar; *(ar+i)=zw; }else { *(ar+i)=zw; } if(zw==1101) { for(x=0;x<i;x++) { printf("z%d:%d ptr:%p\n",x+1,*(ar+x),(ar+x)); } } i++; } }
-
HiFish schrieb:
Nur woher weiß ich jetzt obs klappt oder nicht ?!?
Debugger starten und nachsehen, was das Programm macht
Und 2te Frage wie ruf ich malloc fuer ein 2-Dimensionales Array auf?
char *str[20]=malloc(sizeof(char)); //Wenn ich Strings der Länge 20 einlesen will
so?
Nein, so bestimmt nicht - du deklarierst ein Array aus 20 char-Zeigern und pointerst es dann auf einen 1 Byte großen Heap-Bereich.
char** data = malloc(anzahl*sizeof(char*)); for(i=0;i<anzahl;++i) data[i]=malloc(laenge+1);//+1 für schließendes '\0' ... for(i=0;i<anzahl;++i) free(data[i]); free(data);
-
ok habs jetzt mal mit char versucht, funktioniert auch (beinahe..)
Zum einen gibt er quatsch bei den ersten beiden Einträgen aus(aber nur wenn man ca. 15+ Einträge hat bei nur zB. 5 Einträgen passt alles):s1:� 1 ▒2 82 X2 //1 eingegeben s2:� //2 eingegeben s3:3 //... s4:4 s5:5 s6:6
und nach ca. 20 Eingaben bricht das Programm mit folgender Fehlermeldung ab:
*** glibc detected *** ./dyn: realloc(): invalid next size: 0x09e83008 *** ======= Backtrace: ========= /lib/libc.so.6[0x4d5345] /lib/libc.so.6(__libc_realloc+0x101)[0x4d5d30] ./dyn[0x8048592] /lib/libc.so.6(__libc_start_main+0xc6)[0x484de6] ./dyn[0x8048439] ...
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { int x=1,akt_pos=0,length=0,i=0; char zw[21]; char **ar=malloc(sizeof(char*)); char *zwar; while(x) { scanf("%s",&zw); if(strstr(zw,"end")!=0) { x=0; for(i=0;i<=length;i++) { free(ar[i]); } free(ar); }else if(length==akt_pos) { realloc(ar,(10*sizeof(char*))); for(i=0;i<=10;i++) { ar[length+i]=malloc(21); } length+=10; strncpy(ar[akt_pos],zw,20); }else { strncpy(ar[akt_pos],zw,20); } akt_pos++; if(strstr(zw,"print")!=0) { for(x=0;x<akt_pos;x++) { strncpy(zw,ar[x],20); printf("s%d:%s \n",x+1,zw); } } } }
-
Bei realloc() mußt du die Gesamtgröße des neuen Bereiches angeben, nicht nur die Größenänderung (und außerdem ändert die Funktion nicht den übergebenen Parameter, sondern gibt die neue Adresse per return zurück):
ar=realloc(ar,(10+length)*sizeof(char*));
-
jetzt geht es,hätte ich selber sehen müssen/sollen
vielen Dank für den Hinweis
-
Hallo,
Danke für die Hilfe, aber ich sehe, dass ich mich bei den Eingaben dennoch darauf einigen muss, dass keine Eingabe quasi länger als 21 Zeichen ist.Mit der VCL hat man nämlich diese Probleme nicht mehr (wobei ich glaube, das ist nicht ganz korrekt, sie werden nur von C++ und seinen Bibliotheken umgangen).
-
#include <stdlib.h> #include <string.h> char **table=NULL; size_t table_size=0; /* in feldern, nicht bytes */ void resize_table (size_t new_size) { int i; if(new_size!=table_size) { /* falls table verkleinert werden soll, dann ueberzählige strings freigeben */ for(i=new_size; i<table_size; ++i) free(table[i]); if(table_size==0) table=(char**)malloc(sizeof(char*)*new_size); else table=(char**)realloc(table,sizeof(char*)*new_size); if((table_size=new_size)==0) table=NULL; for(i=table_size; i<new_size; ++i) table[i]=NULL; } } void set_table_entry (int i, const char *str) { resize_table(i+1); if(str) table[i]=strdup(str); else { if(table[i]) free(table[i]); table[i]=NULL; } }
-
Hallo
hatte gerade das gleiche Problem ein 2D-Feld dynamisch zu erzeugen.
Die Lösung dafür habe ich auf folgender Internetseite gefunden:http://www.cpp-tutor.de/cpp/le17/le17_01.htm
template <typename T, int r, int c>
class matrix
{
T *data; // Zeiger-Zeiger(!) auf dyn. 2D-Feld
int col; // Spalten
int row; // Zeilen
public:
// ctor, allokiert 2D-Feld dynamisch
matrix()
{
row = r; // Zeilen/Spalten merken
col = c;
// 2D-Feld dyn. allokieren
data = new T[row];
for (int i=0; i<row; i++)
data[i] = new T[col];Das ist die relevante Stelle der Seite.
Habe selbst dazu ein einfaches Bsp. geschrieben. Ist verständlicher:#include<iostream>
using namespace std;class Array{
public:
Array();
void Ausgabe();private:
int Zeile;
int Spalte;
int** Feld; //wichtig für dynamisches 2D-Feld
};Array::Array(){
Zeile = 4;
Spalte = 3;Feld = new int*[Zeile]; //wichtig für dynamisches 2D-Feld
for(int i=0; i<Zeile; i++) //wichtig für dynamisches 2D-Feld
Feld[i] = new int[Spalte]; //wichtig für dynamisches 2D-Feldfor(int i=0; i<Spalte; i++){
for(int j=0; j<Zeile; j++) Feld[i][j] = j+i; //Fülle 2D-Feld
};
};void Array::Ausgabe(){
for(int i=0; i<Spalte; i++){
cout<<endl;
for(int j=0; j<Zeile; j++) cout<<Feld[i][j];
};
cout<<endl;
};int main(){
Array objekt;
objekt.Ausgabe();
system("pause");
};
-
Tja, Templates in C wäre doch schön