C Datenbank

Hallo Leute :)

Ich hab ein kleines Problem... Ich würde gern einen char-String mit mehreren Möglichkeiten vergleichen... Jedesmal aber mit "strcmp" zu arbeiten finde ich ein bisschen aufwendig...
Gibt es eine Möglichkeit diesen String mit einer Art Datenbank zu vergleichen?

Danke Schonmal MCStreetguy
 
Selbst wenn eine Datenbank dahinter läge, müsste auch dort der String-Vergleich mit strcmp gemacht werden. Du kannst aber auch einfach C++ und std::string::compare verwenden.
 
Jedesmal aber mit "strcmp" zu arbeiten finde ich ein bisschen aufwendig
falls mit "aufwändig" die Laufzeit/"Aufwand für den Rechner" gemeint ist - das, was Du suchst ist meist als: "dictionary" "map/hashmap/hashtable" "associative array" bekannt.
Hash table - Wikipedia, the free encyclopedia

Da wird man eine Implementierung für C suchen und einbinden müssen (selberschreiben ist _etwas_ aufwändig) wie z.B uthash uthash: a hash table for C structures
[OT]
Oder man nutzt eine andere Sprache, die dictionaries von sich aus beherrscht bzw. im Stadard-Framework mitbringt (python, perl, lua, Java, php, C#, C++).
Vor allem ist das (sichere) Arbeiten mit Zeichenketten in C alles andere als bequem.
[/OT]
 
Aber sind Hash-Tabellen, die in structs verwendet werden, nicht auf statische Array-Grössen angewiesen damit die Speicher-Reservierung korrekt funktioniert?
 
Zumindest laut uthash Beispielen nicht (da gibt es HASH_ADD_STR und HASH_ADD_KEYPTR) - und gespeichert wird eher nur der Verweis auf die Struktur selbst (keine Kopie). Wobei mir bei uthash die Kollisionsauflösung nicht so wirklich zusagt.

Gibt ja noch Glib Hash Tables, was aber imho schon etwas aufwändiger zum Einbinden ist.
http://en.literateprograms.org/Hash_table_(C) ist einfach, übersichtlich usw, erfordert aber manuelles "resizing" und die Hashfunktion ist imho etwas zu simpel.
Libcfu | Free Development software downloads at SourceForge.net schaut an sich recht gut aus - autoresize, keys/values "frei wählbar", nur nicht so dolle dokumentiert.

Wobei es eher auf die Absicht des Threaderstellers ankommt (kann ja sein, dass nur Eingabe im Menü oder ähnlichem mit vorgegebenen Strings verglichen werden soll) ;)
 
Die Ideale Datenstruktur für das Problem ist eigentlich ein Trie

Was es da für Implementierungen gibt weiß ich nicht. Wenn die triviale Lösung schnell genug ist, dann belass es einfach dabei. In der Regel haben komplexe Algorithmen auch einen gewissen Overhead, so dass es sich in der Regel erst ab einer gewissen Problemgröße lohnt diese zu nutzen.
 
Ich weiß nich ob das ganz klar geworden ist, aber es geht darum ein Kommando einzugeben und das wird dann mit einer Reihe möglicher Eingaben verglichen... Jedesmal per strcmp und if eine abfrage zu starten ist mir aber wie gesagt zu aufwändig... es soll aber in C bleiben...
Gibt es da nix einfacheres?
 
Doch das ist schon klar, die Frage ist nur wie viele mögliche Eingaben? 10,100,1000 ....? Und wie lange ist die Eingabe?

Definiere zu Aufwendig. Programmieraufwand, Programmlaufzeit, Speicherverbrauch ...

Programmiertechnisch einfacher als mehrere strcmp in ner Schleife wird es nicht werden.
 
Aber sind Hash-Tabellen, die in structs verwendet werden, nicht auf statische Array-Grössen angewiesen damit die Speicher-Reservierung korrekt funktioniert?

Nö, Hashtables will man eh nich aufm Stack bauen, sondern im Heap haben...

Allgemein mal... schau dir z.B. mal die Implementierung von Python an, die ist extrem schnell... Key Lookup ist in 99.9% der Fälle O(1) und worst case O(n)... Insertion und Deletion ist ebenfalls fast immer O(1) und worst case auch nur O(n)...

Ich weiß nich ob das ganz klar geworden ist, aber es geht darum ein Kommando einzugeben und das wird dann mit einer Reihe möglicher Eingaben verglichen... Jedesmal per strcmp und if eine abfrage zu starten ist mir aber wie gesagt zu aufwändig... es soll aber in C bleiben...
Gibt es da nix einfacheres?

getopt
 
Zuletzt bearbeitet:
Code:
[color=#007020]#include <string.h>
#include <stdio.h>
#include <stdint.h>
[/color]
[color=#007020][b]typedef[/b][/color] [color=#007020][b]enum[/b][/color] 
{
    NONE, ADD, SUB, DELETE, PRINT
} cmd_type;

[color=#007020][b]typedef[/b][/color] [color=#007020][b]struct[/b][/color]
{
    [color=#007020][b]const[/b][/color] [color=#902000]char[/color] [color=#666666]*[/color]cmd_str;
    cmd_type cmd;
} menu_type;

[color=#007020][b]static[/b][/color] cmd_type [color=#06287e]get_command[/color]([color=#007020][b]const[/b][/color] [color=#902000]char[/color] [color=#666666]*[/color]input)
{
    menu_type entries[] [color=#666666]=[/color]
    {
        {[color=#4070a0]"add"[/color], ADD},
        {[color=#4070a0]"sub"[/color], SUB},
        {[color=#4070a0]"delete"[/color], DELETE},
        {[color=#4070a0]"print"[/color], PRINT}
    };
    [color=#902000]unsigned[/color] [color=#902000]int[/color] i;
    [color=#007020][b]for[/b][/color] (i [color=#666666]=[/color] [color=#40a070]0[/color]; i [color=#666666]<[/color] [color=#007020][b]sizeof[/b][/color](entries)[color=#666666]/[/color][color=#007020][b]sizeof[/b][/color](entries[[color=#40a070]0[/color]]); i[color=#666666]++[/color])
    {
        [color=#007020][b]if[/b][/color] (stricmp(input, entries[i].cmd_str) [color=#666666]==[/color] [color=#40a070]0[/color]) [color=#007020][b]return[/b][/color] entries[i].cmd;
    }
    [color=#007020][b]return[/b][/color] NONE;
}

[color=#007020][b]static[/b][/color] [color=#902000]void[/color] [color=#06287e]menu_executer[/color]([color=#007020][b]const[/b][/color] [color=#902000]char[/color] [color=#666666]*[/color]input)
{    
    cmd_type cmd [color=#666666]=[/color] get_command(input);
    [color=#007020][b]switch[/b][/color] (cmd)
    {
        [color=#007020][b]case[/b][/color] ADD: puts([color=#4070a0]"adding"[/color]);
        [color=#007020][b]break[/b][/color];

        [color=#007020][b]case[/b][/color] SUB: puts([color=#4070a0]"sub command"[/color]);
        [color=#007020][b]break[/b][/color];
        
        [color=#007020][b]case[/b][/color] PRINT: puts([color=#4070a0]"print cmd"[/color]);
        [color=#007020][b]break[/b][/color];

        [color=#007020][b]case[/b][/color] DELETE: puts([color=#4070a0]"del cmd"[/color]);
        [color=#007020][b]break[/b][/color];

        [color=#007020][b]case[/b][/color] NONE: puts([color=#4070a0]"unknown command :("[/color]);
        [color=#007020][b]break[/b][/color];
        [color=#002070][b]default:[/b][/color] puts([color=#4070a0]"default action"[/color]);
    }
}

[color=#902000]int[/color] [color=#06287e]main[/color]([color=#902000]void[/color])
{
    [color=#60a0b0][i]/* while menu loop bla */[/i][/color]
    menu_executer([color=#4070a0]"aDD"[/color]);
    menu_executer([color=#4070a0]"Print"[/color]);
    menu_executer([color=#4070a0]"cdw"[/color]);
    [color=#007020][b]return[/b][/color] [color=#40a070]0[/color];
}
oder: falls eher eine Aktion je nach Eingabe ausgeführt werden soll:
Code:
[color=#007020]#include <string.h>
#include <stdio.h>
#include <stdint.h>
[/color]
[color=#007020][b]typedef[/b][/color] [color=#007020][b]struct[/b][/color]
{
    [color=#007020][b]const[/b][/color] [color=#902000]char[/color] [color=#666666]*[/color]cmd_str;
    [color=#902000]int[/color] ([color=#666666]*[/color]func) ([color=#902000]void[/color]);
} menu_type;

[color=#902000]int[/color] [color=#06287e]add[/color]([color=#902000]void[/color]) { [color=#007020][b]return[/b][/color] puts([color=#4070a0]"dummy add"[/color]); }
[color=#902000]int[/color] [color=#06287e]sub[/color]([color=#902000]void[/color]) { [color=#007020][b]return[/b][/color] puts([color=#4070a0]"dummy sub"[/color]); }
[color=#902000]int[/color] [color=#06287e]print[/color]([color=#902000]void[/color]) { [color=#007020][b]return[/b][/color] puts([color=#4070a0]"dummy print"[/color]); }

[color=#007020][b]static[/b][/color] [color=#902000]int[/color] [color=#06287e]get_command[/color]([color=#007020][b]const[/b][/color] [color=#902000]char[/color] [color=#666666]*[/color]input)
{
    menu_type entries[] [color=#666666]=[/color]
    {
        {[color=#4070a0]"add"[/color], [color=#666666]&[/color]add},
        {[color=#4070a0]"sub"[/color], [color=#666666]&[/color]sub},
        {[color=#4070a0]"print"[/color], [color=#666666]&[/color]print}
    };
    [color=#902000]unsigned[/color] [color=#902000]int[/color] i;
    [color=#007020][b]for[/b][/color] (i [color=#666666]=[/color] [color=#40a070]0[/color]; i [color=#666666]<[/color] [color=#007020][b]sizeof[/b][/color](entries)[color=#666666]/[/color][color=#007020][b]sizeof[/b][/color](entries[[color=#40a070]0[/color]]); i[color=#666666]++[/color])
    {
        [color=#007020][b]if[/b][/color] (stricmp(input, entries[i].cmd_str) [color=#666666]==[/color] [color=#40a070]0[/color]) [color=#007020][b]return[/b][/color] entries[i].func();
    }
    puts([color=#4070a0]"unknown command :("[/color]); 
    [color=#007020][b]return[/b][/color] [color=#666666]-[/color][color=#40a070]1[/color];
}

[color=#902000]int[/color] [color=#06287e]main[/color]([color=#902000]void[/color])
{
    [color=#60a0b0][i]/* while menu loop bla */[/i][/color]
    get_command([color=#4070a0]"aDD"[/color]);
    get_command([color=#4070a0]"Print"[/color]);
    get_command([color=#4070a0]"cdw"[/color]);
    [color=#007020][b]return[/b][/color] [color=#40a070]0[/color];
}
Btw: bezüglich Python Hashtableumsetzung: http://incise.org/hash-table-benchmarks.html schlägt sich nicht soo schlecht. Und bei 64-Bit Version dürfte man auch deutlich mehr Keys reinkriegen (wobei man ab einer gewissen Größe imho sowieso über eine eventuell geeignetere Struktur/DB nachdenken sollte).
 
Zurück
Oben