2013-04-05 28 views
5

Tôi đang nhận được một số hành vi khó hiểu đang cố gắng sử dụng công cụ tìm kiếm dựng sẵn c trên một chuỗi các chuỗi trong C. Đây là mã. Tôi biết bạn có thể sử dụng strcmp dựng sẵn để tìm kiếm chuỗi các chuỗi, nhưng tôi đã bao gồm myStrCmp cho mục đích gỡ lỗi vì tôi không biết tại sao nó không hoạt động.Gặp sự cố khi sử dụng bsearch với một chuỗi các chuỗi

const char *stateNames[] = {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "Washington DC", "West Virginia", "Wisconsin", "Wyoming"}; 

int myStrCmp(const void *s1, const void *s2) { 
    printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, (char *)s1, s2, (char *)s2); 
    return strcmp(s1, s2); 
} 

int determineState(char *state) { 
    printf("state: %s\n", state); 
    for(int i = 0; i < 51; i++) 
    printf("stateNames[%i](%p): %s\n", i, &(stateNames[i]), stateNames[i]); 

    char *found = (char *) bsearch(state, stateNames, 51, sizeof(char *), myStrCmp); 

    if(found == NULL) 
    return -1; 

    return 0; 
} 

và đây là một số đầu ra khi chức năng này được gọi để tìm Alabama.

stateNames[0](0x618440): Alabama 
stateNames[1](0x618448): Alaska 
stateNames[2](0x618450): Arizona 
... 
stateNames[24](0x618500): Missouri 
stateNames[25](0x618508): Montana 
stateNames[26](0x618510): Nebraska 
stateNames[27](0x618518): Nevada 
stateNames[28](0x618520): New Hampshire 
stateNames[29](0x618528): New Jersey 
stateNames[30](0x618530): New Mexico 
stateNames[31](0x618538): New York 
stateNames[32](0x618540): North Carolina 
stateNames[33](0x618548): North Dakota 
stateNames[34](0x618550): Ohio 
stateNames[35](0x618558): Oklahoma 
stateNames[36](0x618560): Oregon 
stateNames[37](0x618568): Pennsylvania 
stateNames[38](0x618570): Rhode Island 
stateNames[39](0x618578): South Carolina 
stateNames[40](0x618580): South Dakota 
stateNames[41](0x618588): Tennessee 
stateNames[42](0x618590): Texas 
stateNames[43](0x618598): Utah 
stateNames[44](0x6185a0): Vermont 
stateNames[45](0x6185a8): Virginia 
stateNames[46](0x6185b0): Washington 
stateNames[47](0x6185b8): Washington DC 
stateNames[48](0x6185c0): West Virginia 
stateNames[49](0x6185c8): Wisconsin 
stateNames[50](0x6185d0): Wyoming 
myStrCmp: s1(0x415430): Alabama, s2(0x618508): 
               UA 
myStrCmp: s1(0x415430): Alabama, s2(0x618570): A 
myStrCmp: s1(0x415430): Alabama, s2(0x618540): PUA 
myStrCmp: s1(0x415430): Alabama, s2(0x618528): 1UA 
myStrCmp: s1(0x415430): Alabama, s2(0x618538): GUA 
myStrCmp: s1(0x415430): Alabama, s2(0x618530): <UA 

Như bạn có thể thấy, các địa điểm viếng thăm bởi bsearch trong quá trình tìm kiếm của mình nên có các chuỗi giá trị (như đã được chỉ cần kiểm tra trước khi gọi bsearch), nhưng sản lượng nếu bạn cố gắng in char * ở đó vị trí là rác. Có ai có thể thấy sai lầm của tôi không? Ngẫu nhiên tôi nhận được cùng một hành vi xấu (nhưng không được theo dõi nó rõ ràng) khi tôi gọi bsearch với tham số cuối cùng được đặt thành:

(int(*)(const void*, const void*))strcmp 

Cảm ơn!

Trả lời

7

Vì bạn đang sử dụng một mảng const char *, bsearch() sẽ chuyển đến hàm so sánh một con trỏ tới các phần tử đó. Nói cách khác, nó sẽ nhận được const char * const * trong đối số thứ hai của nó.

int myStrCmp(const void *s1, const void *s2) { 
    const char *key = s1; 
    const char * const *arg = s2; 
    printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, key, s2, *arg); 
    return strcmp(key, *arg); 
} 
+0

Thú vị: hoạt động mà tôi không mong đợi được đảm bảo theo tiêu chuẩn. Tuy nhiên, đọc ISO/IEC 9899: 2011, '§7.22.5.1 Chức năng 'bsearch'', nó nói: _¶3 Hàm so sánh được trỏ đến bởi' so sánh' được gọi với hai đối số trỏ tới đối tượng khóa và thành phần tử mảng, theo thứ tự đó._ Vì vậy, hành vi là xác định. Tuy nhiên, bạn không thể sử dụng hàm 'myStrCmp()' đó với 'qsort()'. –

+0

@JonathanLeffler: Vâng, API được định nghĩa khác một chút so với 'qsort()' để bạn có thể chuyển một chuỗi cho khóa, nhưng có một mảng cấu trúc để tìm kiếm thông qua. – jxh

1

Tên tiểu bang (hoặc khóa) cần phải là con trỏ trỏ đến con trỏ. Không phải thêm/xóa const ở mọi nơi. myStrCmp cần phải cân nhắc một để so sánh các chuỗi. Mã dưới đây làm những gì bạn muốn tôi nghĩ. Xin vui lòng cho tôi biết nếu không, cảm ơn.

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


const char *stateNames[] = {"Alabama", "Alaska", "Arizona", "Arkansas","California", "Colorado", "Connecticut", "Delaware", "Florida","Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "Washington DC", "West Virginia", "Wisconsin", "Wyoming"}; 

int myStrCmp(const void *s1, const void *s2) { 
    printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, *(char **)s1, s2, *(char**)s2); 
    return strcmp(*(char **) s1, *(char **) s2); 
} 

int determineState(char *state) { 
    printf("state: %s\n", state); 

    for(int i = 0; i < 51; i++) 
     printf("stateNames[%i](%p): %s\n", i, &(stateNames[i]), stateNames[i]); 

    char **found = (char **) bsearch(&state, stateNames, 51, sizeof(char *), myStrCmp); 

    if(found == NULL){ 
     return -1; 
    } else { 
     printf("Found it!: %s\n", *found); 

    } 

    return 0; 
} 

int main(int argc, const char * argv[]) { 
    determineState("Alabama"); 

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