2012-11-10 14 views
5

Mam następujący blok kodu używam wierteł niemieckich czasowników:Kod dynamiczne w C

if (strcmp(*option, "sein") == 0) 
    *option = linie.sein; 

if (strcmp(*option, "haben") == 0) 
    *option = linie.haben; 

if (strcmp(*option, "possessiv") == 0) 
    *option = linie.possessiv; 

if (strcmp(*option, "reflexiv") == 0) 
    *option = linie.reflexiv; 

if (strcmp(*option, "accusativ") == 0) 
    *option = linie.accusativ; 

if (strcmp(*option, "dativ") == 0) 
    *option = linie.dativ; 

Jednak chciałbym skondensować go do czegoś podobnego:

*option = linie.(*option); 

Albo:

*option = linie.(*option)(); 

Niestety, żaden z nich nie działa. Jakieś pomysły?

Edit @dasblinkenlight:

typedef struct 
{ 
    char subjekt[20]; 
    char sein[20]; 
    char haben[20]; 
    char possessiv[20]; 
    char reflexiv[20]; 
    char accusativ[20]; 
    char dativ[20]; 
} satz; 

satz linie = 
{ 
    .subjekt = "", 
    .sein = "", 
    .haben = "", 
    .possessiv = "", 
    .reflexiv = "", 
    .accusativ = "", 
    .dativ = "" 
}; 

char *option = argv[1]; 
+0

Proszę pokazać definicje 'linie' i' option'. – dasblinkenlight

+0

Pojemniki i pętle. Powinieneś naprawdę nauczyć się "0-1-Many Rule". –

+3

Niestety nie jest to możliwe w C, ponieważ nie ma możliwości odbicia ani dynamicznego kodu. –

Odpowiedz

4

Jesteś mieszanie w czasie kompilacji i możliwości wykonawcze. W języku C nie można użyć identyfikatora bezpośrednio z łańcucha uzyskanego w czasie wykonywania. Możesz jednak przenieść swoje porównania do funkcji nieprzezroczystej.

char *f(const satz *linie, const char *option) 
{ 
    if (strcmp(option, "sein") == 0) 
     return linie->sein; 
    else if (strcmp(option, "haben") == 0) 
     return linie->haben; 
    else if (strcmp(option, "possessiv") == 0) 
     return linie->possessiv; 
    else if (strcmp(option, "reflexiv") == 0) 
      return linie->reflexiv; 
    else if (strcmp(option, "accusativ") == 0) 
     return linie->accusativ; 
    else if (strcmp(option, "dativ") == 0) 
     return linie->dativ; 
    else 
     return NULL; 
} 

*option = f(&linie, *option); 
+0

Masz rację co do mieszania comile-time i runtime napisów Kirilenko. Powiedziałbym, że to jest tak dobre, jak się da. Dziękuję za Twoją odpowiedź. – user1408643

5

Odpowiedź Kirilenki jest dobra i sprawdza się w przypadku krótkich struktur, takich jak Twoja. Jednak w przypadku dłuższych struktur utrzymanie wszystkich wywołań strcmp może być kłopotliwe. Aby rozwiązać ten problem, możesz zdefiniować relację między słowem kluczowym, które próbujesz dopasować, a offsetem odpowiedniego elementu w twojej strukturze.

struct relation 
{ 
    char keyword[20]; 
    int offset; 
}; 

Następnie można użyć przesunięcia makro (w stddef.h), aby połączyć słowo kluczowe z jego pozycją w strukturze.

#define REL_LEN (7) 

struct relation rel[REL_LEN] = { 
    {"subjekt", offsetof(satz, subjekt) }, 
    {"sein", offsetof(satz, sein) }, 
    {"haben", offsetof(satz, haben) }, 
    {"possessiv", offsetof(satz, possessiv) }, 
    {"reflexiv", offsetof(satz, reflexiv) }, 
    {"accusativ", offsetof(satz, accusativ) }, 
    {"dativ", offsetof(satz, dativ) } 
}; 

Wreszcie funkcja pobierania ciągu znaków za pomocą powyższego odwzorowania może wyglądać mniej więcej tak.

char *lookup_keyword(const satz *linie, const char *option, 
        const struct relation *rel, size_t rel_size) 
{ 
    int i; 
    char *pchar = (char *)linie; 

    for (i=0; i<rel_size; i++) 
    { 
     if (strcmp(option, rel->keyword) == 0) 
     { 
      pchar += rel->offset; 
      return pchar; 
     } 
     rel++; 
    } 
    printf("Error: no mapping found matching %s!\n", option); 
    return ""; 
} 

I można wywołać go jak tak

char *option = argv[1]; 

printf("Result for %s: %s\n", option, 
     lookup_keyword(&linie, option, rel, REL_LEN));