2017-04-09 3 views
-3

Ich wollte ein Programm machen, um mehrere Strings zu wechseln, um die if-else-leiter zu vermeiden.Ist diese Art der Stringwechsel effizient? Gibt es effizientere?

Meine Idee war es, eine verkettete Liste zu machen und jeden Knoten zu entfernen, der in irgendeiner Position anders ist. Dann könnte ich einfach zurückgeben welches Argument es war und diese Nummer wechseln.

Mein Code:

int str_switch(char* query, int arg_count, ...) { 
    //Variables 
    int i, j; 
    struct node* args = (struct node*)calloc(arg_count, sizeof(struct node)); 
    va_list list; 

    //va_list -> array 
    int start = 0; 
     //data 
    va_start(list, arg_count); 
    for (i = 0; i < arg_count; i++) { 
     args[i].data = va_arg(list, char*); 
     args[i].prev = i - 1; 
     args[i].next = i + 1; 
    } 
    va_end(list); 
     //start 
    args[0].prev = -1; 
     //end 
    args[arg_count - 1].next = -1; 

    //switch 
    int len = strlen(query); 
    for (i = 0; i <= len; i++) { //i <= len: null character is also compared 
     for (j = start; j != -1; j = args[j].next) { 
      //remove from list 
      if (*(args[j].data + i) != *(query + i)) { 
       //only one element in list 
       if (args[j].prev == -1 && args[j].next == -1) { 
        start = -1; 
       } 
       //first element 
       else if (args[j].prev == -1) { 
        start = args[j].next; 
        args[start].prev = -1; 
       } 
       //last element 
       else if (args[j].next == -1) { 
        args[args[j].prev].next = -1; 
       } 
       //mid element 
       else { 
        args[args[j].prev].next = args[j].next; 
        args[args[j].next].prev = args[j].prev; 
       } 
      } 
     } 
    } 

    //return 
    free((void*)args); 
    return start; 
} 

Die node Struktur sieht wie folgt aus:

struct node { 
    int next; 
    int prev; 
    char *data; 
}; 

Kleine Testprogramm:

#include<stdio.h> 
#include<stdlib.h> 


int main(void){ 
    char query[10] = "Horse"; 
    switch(str_switch(query, 3, "Bird", "Dog", "Horse")) { 
     case 0: // Bird 
      printf("It\'s a bird\n"); 
      break; 
     case 1: // Dog 
      printf("It\'s a dog\n"); 
      break; 
     case 3: // Horse 
      printf("It\'s a horse\n"); 
      break; 
     case -1: // Error 
      printf("It\'s an error :(\n"); 
      break; 
     default: // ? 
      printf("It\'s nothing..?\n"); 
      break; 
    } 
    system("pause"); 
    return 0; 
} 

Meine Frage: ist das leistungsfähig? Wie könnte ich es effizienter machen? Ich will das wissen, weil ich in zukünftigen Projekten diesen Code verwenden kann und will ich nicht die Leistung verlieren, weil einige dumme Fehler :)

+1

'Fall 3' ->' Fall 2'? – BLUEPIXY

+2

An dem Punkt, an dem Sie 'calloc()' aufrufen müssen und eine benutzerdefinierte Struktur verwenden müssen, um eine Übereinstimmung für drei Strings zu finden, sind Sie weit von der Spur entfernt. Der Zuweisungsaufruf ist wahrscheinlich teurer, als 'strcmp()' dreimal aufzurufen. Und warum die verknüpfte Liste bei der Vorabvergabe sowieso? – dhke

+1

Es scheint ineffizient zu sein, die Daten, die sich bereits auf dem Stapel befinden, in einer Liste zu rekonstruieren. – BLUEPIXY

Antwort

1

Sie sollten wahrscheinlich eine Datenstruktur wie ein set bauen, ein hashtable oder sogar ein trie. Oder mindestens qsort die Liste und eine bsearch, um den Index zu bekommen. Das größte Problem in Ihrem aktuellen Code ist, dass Sie bei jedem Anruf viel arbeiten.

Wenn Ihre Liste der Zeichenfolgen zur Kompilierungszeit bekannt ist, können Sie sogar eine perfekte Hashtable mit gperf generieren.

Eine andere Möglichkeit ist mit GTK+, die einen GQuark-Datentyp hat, der Ihnen eine 2-Wege-Verbindung zwischen einer Zeichenfolge und einem eindeutigen Integer-Bezeichner gibt.

Verwandte Themen