2011-03-04 42 views
10

Nếu tôi có một bộ giá trị chuỗi nhỏ và tôi muốn tìm nạp một giá trị số để đại diện cho chúng, cách tốt nhất để thực hiện điều này thông qua bảng tra cứu là gì?Bảng tra cứu giá trị bằng C theo chuỗi?

Nếu tôi được chỉ cần phải làm một cái nhìn thẳng lên, tôi biết giải pháp tối ưu sẽ chỉ được một loạt các câu lệnh if:

if (strcmp(str, "foo") == 0) 
    tmp = FOO; 
else if (strcmp(str, "bar") == 0) 
    tmp = BAR; 

Nhưng, tôi yêu cầu này vì những giá trị chuỗi nhỏ đại diện cho một thuộc tính trong một dự án nhỏ tôi đang viết trong C, và các thuộc tính có thể là chỉ đọc hoặc đọc-ghi (không có chỉ viết cho bây giờ, có thể không bao giờ). Vì vậy, những gì tôi hiện đang làm chỉ để đảm bảo mọi thứ hoạt động có chức năng tra cứu bao gồm mệnh đề if-then như trên để tra cứu giá trị nào là chỉ đọc và hàm thứ hai tra cứu giá trị nào được đọc -Viết. Nhưng điều này là lớn và xấu với tôi.

Tôi đang nghĩ, có ba hàm thay thế. Một hàm là hàm tra cứu, và nó trả về một giá trị int là dạng số của chuỗi. Nhưng chức năng tra cứu này cũng có thể lấy một lá cờ xác định xem nó có tìm nạp một giá trị chỉ đọc hay một giá trị đọc-ghi. Nếu một thao tác ghi được thực hiện trên một giá trị thực sự chỉ đọc, hàm sẽ trả về -EINVAL (hoặc một cái gì đó tương đương).

Hai hàm còn lại, bây giờ vẫn là đọc và ghi, chỉ cần gọi hàm tra cứu này, chuyển một chuỗi giá trị và cờ xác định xem chúng có đang đọc hoặc viết hay không.

Thing là, tôi không biết mô hình này được mô hình hóa như thế nào trong C (nếu nó có thể được mô hình hóa) và tìm kiếm Google đang mệt mỏi với tất cả các trang nội dung trích xuất địa điểm này (và cho tôi C++/C# câu trả lời) .

Vì vậy, đây là cách tôi nghĩ rằng nó sẽ xem xét:

int lookup_func(const char *name, const char *flag) { 
    int tmpval = 0; 

    /* code to do the lookup. */ 

    if (tmpval == 0) 
     return -EINVAL; 
    else 
     return tmpval; 
} 

int get_readonly_bit(const char *name) { 
    return lookup_func(name, "ro"); 
} 

int get_readwrite_bit(const char *name) { 
    return lookup_func(name, "rw") 
} 

Suy nghĩ? Ý tưởng là giảm kích thước mã bằng cách không lặp lại các nhánh if-then cho hai hàm này, chúng khác nhau một chút về thiết kế tổng thể và chỉ đơn giản là để một hàm tra cứu tìm ra hàm mà giá trị này phục vụ.

+0

+1 cho const-đúng đắn ... * nhưng cờ là tốt hơn như một int (hoặc enum) * – pmg

+0

Bạn muốn một [hàm băm] (http://en.wikipedia.org/wiki/Hash_function). Tùy thuộc vào giá trị chuỗi của bạn, nó có thể đơn giản như trả về giá trị của chữ cái đầu tiên ... – pmg

+0

@pmg: vẫn có khả năng xảy ra một số chuỗi với cùng một mã băm. Nhỏ, nhưng nó là :) –

Trả lời

6

Bạn không chỉ xem xét việc đặt bàn? Một bảng băm cũng tốt nếu có nhiều thuộc tính.

int lookup(const char *name) 
{ 
    typedef struct item_t { const char *name; int writable; int value; } item_t; 
    item_t table[] = { 
    { "foo", 0, FOO }, 
    { "bar", 1, BAR }, 
    { NULL, 0, 0 } 
    }; 
    for (item_t *p = table; p->name != NULL; ++p) { 
     if (strcmp(p->name, prop_name) == 0) { 
      return p->value; 
     } 
    } 
    return -EINVAL; 
}
+0

Giải pháp tốt. Nếu bạn chỉ quan tâm đến mã "lớn và xấu", điều này nên làm, phải không? Nếu bảng dài và chương trình của bạn thực hiện rất nhiều lần tra cứu, tôi sẽ cố gắng làm việc trên vòng lặp đó: ví dụ: hãy tìm một triển khai tìm kiếm nhị phân áp dụng cho các chuỗi và được viết bằng c, tất nhiên. – AudioDroid

+1

@AudioDroid: cái gì to và xấu về nó? Nó đơn giản và dễ hiểu và khá mạnh mẽ và tôi đã thấy nó được sử dụng ở nhiều nơi. Thuật toán là O (n) có thể là một vấn đề đối với các danh sách dài. Tuy nhiên, cho dù đó là một vấn đề cần được xác định với phân tích hiệu suất, không phải phỏng đoán. – JeremyP

+0

Cá nhân tôi không khuyến khích loại giải pháp này cho bất kỳ điều gì ngoài danh sách tầm thường. Khi sử dụng chuỗi theo cách này, vấn đề về vị trí và phân biệt chữ hoa chữ thường có thể có vấn đề. Hơn nữa, hiệu quả là nghi ngờ.Một strcmp ngụ ý một chuỗi các so sánh lặp lại khi so sánh một khóa băm sẽ đủ. Khi so sánh hiệu suất của băm với strcmp, phương thức băm thể hiện hiệu suất tốt hơn cho tất cả các danh sách tầm thường (theo kinh nghiệm của tôi). – Throwback1986

Các vấn đề liên quan