2015-04-27 8 views
6

Więc staram się, aby program całkowicie od zera (brak biblioteki w zestawie) i mam funkcji, która jest bardzo brzydki:W prostym C, jak zrobić ekwiwalent "mapy"?

int parseUnsignedInt (char * ch, unsigned int * ui) 
{ 
/* Starting at character ch, reads the unsigned int into the 
     variable ui, returns the number of characters read. 
*/ 
    ui = 0; // unsigned integer into which the string representation is read 
    int m = 1; // multiplier 
    int ncp = 0; // # of characters parsed 
    while (*ch) 
    { 
     bool chid = false; // ch is a decimal 
     for (int k = 0; k < decmapLength; ++k) 
     { 
      if (decmap[k].cval == *ch) 
      { 
       ui += decmap[k].ival * m; 
       m *= 10; 
       chid = true; 
       break; 
      } 
     } 
     if (!chid) break; 
     ++ncp; 
     ++ch; 
    } 
    return ncp; 
} 

Część jego brzydoty wynika z faktu, że muszę sposób powiązać char acters.Prosimy do int egers ('0' -> 0 '1' -> 1, ..., '9' -> 9), z wytworzeniem tablicę lub konstrukcjom

typedef struct icpair 
{ 
    char cval; 
    int ival; 
} icpair; 

icpair decmap [10] = {{'0',0}, {'1',1}, {'2',2}, {'3',3}, {'4',4}, {'5',5}, {'6',6}, {'7',7}, {'8',8}, {'9',9}}; 
int decmapLength = sizeof(decmap)/sizeof(icpair); 

do tego celu. Ale szukanie wartości, jeśli nawet istnieje, uwzględnia nieestetyczną liczbę linii, które mogłyby być skondensowane, gdyby był lepszy sposób na to w czystym C. Ja też chcę, żeby to było niezawodne, więc nie odejmowanie wartości ASCII jak '9'-'ch'. Czy jest to możliwe w czystym C, a jeśli tak, to w jaki sposób jest on realizowany?

+0

'ui = 0;' jest błędne. – BLUEPIXY

+2

zamień 'ui = 0' na' * ui = 0' i 'ui + = decmap [k] .ival * m' z' * ui + = decmap [k] .ival * m'. w przeciwnym razie nic nie jest zwracane – Diego

+0

Whoops! Dzięki. –

Odpowiedz

1

Prosta mapa API w C może wyglądać następująco:

Map * map_create(void); 
void map_insert(Map * map, char key, int value); 
int map_find(Map * map, char key); 
void map_destroy(Map * map); 

Wtedy byłbyś w stanie zrobić map_find(map, '0') aby uzyskać wartość całkowitą, być może z semantyki powrocie -1 jeśli nie zostanie znaleziony.

Wdrożenie tego można wykonać za pomocą wielu różnych struktur danych, w zależności od potrzeb. Jeśli nie zależy ci na utrzymaniu zamówienia, prawdopodobnie najlepiej będzie użyć tabeli mieszającej. Jeśli potrzebujesz utrzymać porządek na podstawie klucza, na przykład binarne drzewo może być lepszym pomysłem (być może czerwono-czarne drzewo).

Można zmodyfikować interfejs API, aby uzyskać void * dla klucza i wartości, aby uogólnić ją nieco (w przypadku braku generycznych, których C nie ma). Pojawi się dodatkowa złożoność, taka jak zapewnienie funkcji mieszania dla tabeli mieszania lub funkcja porównania dla drzewa binarnego.

Mimo to wykonanie *ch - '0' jest bezpieczne i działa dobrze.

0

Jeśli chcesz mapować żadnych 10 losowo wybranych znaków do 0..9, nie trzeba oddzielnego elementu struct ival - The „zamówić naturalny” już indeksuje prawidłową cyfrę od razu. Możesz więc użyć pojedynczej tablicy char o długości 10 losowych znaków jako odnośnika.

Jeśli znaki w tej tablicy są stopniowo zwiększane o 1, w ogóle nie potrzebujesz tablicy. W takim przypadku można odjąć kod pierwszy, sprawdzić, czy wynik zawiera się w przedziale od 0 do 9, wskazując na sukces, lub odrzucić ten znak w inny sposób.

Dotyczy to zbiór cyfr w C, ponieważ specyfikacja C wymaga:

zarówno w podstawowe zestawy znaków źródłowych i wykonanie, wartość każdego znaku po 0 w powyższa lista będzie o jeden większa od wartości poprzedniej. (5.2.1 Zestawy znaków w ISO/IEC 9899:201x Normative Draft 2011 (PDF))

Dlatego, aby uzyskać wartość liczbową dla każdej cyfry, character - '0' jest zawsze prawda.

Na marginesie nie jest to zdefiniowane dla zakresów A..Z i a..z. Oznacza to, że jeśli traktujesz 'A' jako 0, nie ma gwarancji, że 'J'-'A' == 9. Do tego potrzebna jest ponownie prosta tablica znaków.