Assoziative Array in >C< wie zu ralisieren?

Hallo zusammen, ich darf nur C verwenden, nicht C++

Habe jetzt sowas definiert:

char dbmenue[1][222] = { „o = Datenbank öffnen/anlegen“ };

Hätte aber lieber sowas:

char dbmenue[o][222] = { „o = Datenbank öffnen/anlegen“ };

Damit ich später mehrmals puts( dbmenue[o] ) schreiben kann.

Geht das vielleicht sogar irgendwie ?

Danke & Grüße Sebastian

Hallo Sebastian

#define DB_MENUE_o 1 // man kann auch enums nehmen, hat vor und nachteile
#define DB_MENUE_a 2 // nur ein o oder a ist ein wenig wenig, daher dieser lange namensvorsatz DB_MENUE_
#define DB_MENUE_x 3 // usus ist es, Makros (#define … ) groß zu schreiben

puts(dbmenue[DB_MENUE_o])

ich hoffe das meintest Du

Gruß
achim

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo Achim,

puts(dbmenue[DB_MENUE_o])

ok, so könnte man es machen.
Gefällt mir schon ganz gut :smile:

Trotzdem häte ich lieber etwas wie ich es aus PHP kenne:
puts(dbmenue[‚o‘])

vielleicht müsste ich da eben eine eigene Funktion schreiben.

Also so
puts(dbmenue(‚o‘))

wird mir dann aber alles zu uneinsichtich für den Programmierer.
Hmmmm. Naja :smile:

Danke und tschü Sebastian

Vor allem

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo Sebastian

puts(dbmenue[DB_MENUE_o])

ok, so könnte man es machen.
Gefällt mir schon ganz gut :smile:

Trotzdem häte ich lieber etwas wie ich es aus PHP kenne:
puts(dbmenue[‚o‘])

Als PHP entworfen wurde, entschied man sich
dafür, die in Perl getrennte Syntax für
assoziative Arrays (Hash) und normale
Arrays zusammenzuwerfen. Aus (Perl)

 dbmenue{'o'} ==\> Perl Hash, {}-Syntax
 dbmenue[111] ==\> Perl Array

wird in PHP

 dbmenue['o'] ==\> PHP Hash
 dbmenue[111] ==\> PHP Array(?)

Ich halte das aber für einen
Schwachpunkt von PHP. Faktisch ist
nun „alles irgendwie“ ein assoziatives
Array.

vielleicht müsste ich da eben eine eigene
Funktion schreiben.
Also so
puts(dbmenue(‚o‘))
wird mir dann aber alles zu uneinsichtich für den
Programmierer. Hmmmm. Naja :smile:

C ist eine maschinennahe Sprache und sieht so
aus wie es aussieht, um eben direkt auf die Maschine
abgebildet werden zu können. Ein „Hash“ ist
daher in C nicht zu erwarten (benötigt immer
einen nichttrivialen Mechanismus).

Die richtige (imho) Lösung hast Du selber
schon vorgeschlagen, Du „kapselst“ die
Details Deiner „Assoziation“ in einer Funktion,
die irgendwas sinnvolles zurückliefert.

Du kannst ja auch gleich in der Funktion die
Ausgabe machen:

 print\_dbmenue('o');

oder sowas.

Was soll denn dbmenue() überhapt machen?

eine solche "assoziative Zuordnung mache ich
in C immer über ein struct-Array und eine Schleife,
zb.:

 char\* dbmenue(char key)
 {
 typedef struct { char key; char \*value; } MyTABLE;
 static MyTABLE table[] = {
 { 'x', "Menupunkt\_x" },
 { 'v', "Menupunkt\_v" },
 { 'o', "Menupunkt\_o" },
 { 'a', "Menupunkt\_a" },
 { 0 , 0 }
 }, \*pt = table;
 
 for( ; pt-\>key; ++pt)
 if(key == pt-\>key)
 return pt-\>value;

 return 0;
 } 

 main()
 {
 puts( dbmenue('x') );
 }

Grüße

CMБ

Grüße

CMБ

Danke Achim und Semjon :smile:

war sehr interessant.

werde wohl mal Semjons Vorschlag umsetzten.

Bist gestern hatte ich noch den unteren (wenns interessiert).

LG Sebastian

#include // fuer malloc()
#include

#define MAX 2500000
void hauptmenue( );
int id_assoc1( char );
void dbmenue( );
void dbmenue( ){

char c=‚0‘;

// wanndelt einen char in eine zugehörigen int werd
// könnte man auch mit switch machen.

int i, strlen_id_str , strlen_dbmenue, nums_dbmenue ;

char id_str[] = „xobahs“ ;
char dbmenue[255][80] = {
„Exit. D.h. Programmende“ ,
„Datenbank oeffnen/anlegen“ ,
„bestehende Datenbank bearbeiten (Name vorhanden)“ ,
„Datensaetze anzeigen (sequentiell, nacheinander)“ ,
„Datensaetze hinzufuegen (von Tastatur) / importieren (aus externer Datei)“ ,
„Datensaetze suchen“
};
//return 0;
strlen_id_str = sizeof( id_str ) ;
strlen_dbmenue = sizeof( dbmenue[1] ) ;
nums_dbmenue = sizeof( dbmenue ) / strlen_dbmenue ;

printf( „Bitte waehlen Sie einen der %i Menueeintraege (Buchstaben) \n“, nums_dbmenue );

do {
// Ausgabe - DB Menü (Tastaurküzel und Text dazu ausgeben.)
for( i=0 ; i " );
c = getche(); //printf( „%i“, c );
clrscr();

// Groß und Kleinschreibung soll keine Rolle spielen.
// c %c" );
i = getche();
switch(i){
case ‚1‘: puts( " Eins." ); break;
default: puts( " Eingabe unbekannt." ); break;
}
clrscr();

} while( i != ‚0‘ );
}

int main( ) {
dbmenue();
//hauptmenue( );
/*
int i=0;

int* pa; // Zeiger auf eine Speicherzelle vom Datentyp double

while ( i++

Hallo Sebastian

Bist gestern hatte ich noch den unteren (wenns interessiert).
#include // fuer malloc()
#include

[Code]

Aha, ungefähr ist mir klar, was Du anstellen
willst. Ich hab mal Dein Programm so um-
gemodelt (nicht schlagen :wink:, dass es mit
so einer Tabelle geht, um mal ein konkretes
Beispiel zu haben.

Nicht weiterlesen, falls
Du es selber machen willst :wink:

*******************************************

S P O I L E R S P A C E

*******************************************

#include // malloc()
#include // printf()
#include // getche()
#include // toupper()/tolower()

#define SCREEN\_WIDTH 80 // Konstante, abhaengig von device!
#define SCREEN\_HEIGHT 24 // Konstante, abhaengig von device! 

 typedef struct { char cmd; char \*value; } DBMAP;

 DBMAP \*dbmenue(void)
{
 static DBMAP table[] = {
 {'\0', "Ihre Eingabe konnte nicht zugeordnet werden" },
 { 'x', "Exit. D.h. Programmende" },
 { 'o', "Datenbank oeffnen/anlegen" },
 { 'b', "bestehende Datenbank bearbeiten (Name vorhanden)" },
 { 'a', "Datensaetze anzeigen (sequentiell, nacheinander)" },
 { 'h', "Datensaetze hinzufuegen (von Tastatur)/importieren (aus externer Datei)"},
 { 's', "Datensaetze suchen" },
 }, \*pt;
 
 int i, key, t\_size=sizeof(table)/sizeof(\*table), t\_last=t\_size-1;
 char prmpt[] = "Bitte waehlen Sie einen der (bisher) %i Menueeintraege (Zeichen)\n";
 printf( prmpt, t\_size );

 for(i=0; i" );
 key = tolower( getche() ); // Groß und Kleinschreibung ==\> alles klein

 for(pt=table+t\_last; pt-\>cmd && key!=pt-\>cmd; --pt)
 ; // zaehlt von hinten bis key == '\x0' ist (0)
 // oder die Taste gefudnen wurde
 return pt; // fallback auf table[0] ==\> default antwort
}

 int main( ) 
{
 DBMAP \*aktion;

 while ( aktion=dbmenue(), aktion-\>cmd != 'x' ) { // Komma operator, lowest prio
 if(aktion-\>cmd != '\x0')
 printf("\nSie drueckten: %c\n \"%s\"\n\n", aktion-\>cmd, aktion-\>value ); 
 else
 printf("\nBitte lesen: NUR die angegebenen Zeichen!\n\n"); 
 } 

 return 0;
}

Grüße

CMБ

Hallo Semjon,

ja so etwas in der Art habe ich seit gestern schon umgesetzt.
Werde aber trotzdem deines noch mal genauer anschauen und testen.
Danke abermals :smile:

Naja… ich paiste es auch noch mal rein… warum auch nicht:

#include
#include

typedef struct { char key; char *value; } AssocTabl;

void hauptmenue( );
AssocTabl* get_dbmenue_row( int , char );
void print_line(char, int);
void print_dbmenue(){
AssocTabl* KeyVal; // AssocTabl* dbmenue( int offset, char key )
print_line(’_’,80);
get_dbmenue_row(-1,0); // Index auf erstes Element setzen
while( KeyVal = get_dbmenue_row(1,0) ) printf("%c = %s\n", KeyVal->key , KeyVal->value );
print_line(’_’,80);
}
void print_line(char c, int len ){ for(; len>0; len–){ printf("%c",c);}printf("\n" ); }
AssocTabl* get_dbmenue_row( int offset, char key ){
// offset ist (normalerweise) 1 oder 0, -1 bedeutet key_last_used zurücksetzen.
// get_val_flag ist entweder 0 oder eine zahl (besser nur 1)
int i =0 ; // temp. Zählvariable
static int key_last_used = -1; // Wird dann beim ersten Offset (meist) auf 0 schreiten.

// Static damit der Inhalt nicht jedesmal neu definiert wird. Nur aus performance gründen.
static AssocTabl dbmenue[] = {
{ ‚x‘, „Exit. D.h. Programmende“ },
{ ‚v‘, „Datenbank oeffnen/anlegen“ },
{ ‚o‘, „bestehende Datenbank bearbeiten (Name vorhanden)“ },
{ ‚a‘, „Datensaetze anzeigen (sequentiell, nacheinander)“ },
{ ‚h‘, „Datensaetze hinzufuegen (von Tastatur) / importieren (aus externer Datei)“ },
{ ‚s‘, „Datensaetze suchen“ },
{ 0 , 0 }
}, *pt = dbmenue;

//printf("%i", key_last_used );
if( offset == -1 ){ key_last_used = -1; }

if( !offset && !key ){
printf( „Meldung aus Funktion, Zeile 49\n“
„AssocTabl* dbmenue( int offset, int get_val_flag, char key )\n“
„(!offset, … , !key ) macht keinen Sinn.\n“);
getchar(); return 0;
}

if( offset > 0 ){ // negativer Werte sind besondere Steuerzeichen.
// Wir setzen den Index hoch und geben den Eintrag zurück.
key_last_used += offset ;
if( dbmenue[key_last_used].key ) return &dbmenue[key_last_used];
key_last_used = -1; // Zurücksetzen, damits beim nächsten durchlauf wieder vorne beginnt.
return 0;
}

// Groß und Kleinschreibung soll keine Rolle spielen. c " ); // Bash zeichnen.
key = getche(); clrscr(); // Taste erfassen und Bildschirm löschen.
if( !(KeyVal = get_dbmenue_row(0, key )) ){
printf( "Fuer Ihre Eingabe >%c%ckey );
switch( key ) {
case ‚v‘: break; // „Datenbank oeffnen/anlegen“ },
case ‚o‘: break; // „bestehende Datenbank bearbeiten (Name vorhanden)“ },
case ‚a‘: break; // „Datensaetze anzeigen (sequentiell, nacheinander)“ },
case ‚h‘: break; // „Datensaetze hinzufuegen (von Tastatur) / importieren (aus externer Datei)“ },
case ‚s‘: break; // „Datensaetze suchen“ },
case ‚x‘: break; // „Exit. D.h. Programmende“
default: print_line(’=’,80);
printf( „Programmierfehler. Unkonsistenz: Der Fall %c ist ohne Funktionalitaet.\n“, key );
print_line(’=’,80);
}
} while( key != ‚x‘ );
}