我在为通用二进制搜索编写的代码时遇到问题。 当我尝试在字符串数组上执行搜索时,我注意到传递给binSearch函数的字符串数组不包含字符串。
有人可以暗示提示吗?
非常欣赏
#define SIZE 100
typedef unsigned char BYTE
请考虑这个主要内容:
void main()
{
char ** stringArr, stringToFind[SIZE];
int stringSize;
int res;
stringArr = getStringArr(&stringSize);
// string to find
gets(stringToFind);
res = stringBinSearch(stringArr, stringSize, stringToFind);
if (res == 1)
printf("The string %s was found\n", stringToFind);
else
printf("The string %s was not found\n", stringToFind);
}
char** getStringArr(int* stringSize)
{
int i, size, len;
char** arr;
char temp[SIZE];
scanf("%d", &size);
getchar();
arr = (char**)malloc(size * sizeof(char*));
checkAllocation(arr);
for (i = 0; i < size; i++)
{
gets(temp);
len = strlen(temp);
temp[len] = '\0';
arr[i] = (char*)malloc((len+1) * sizeof(char));
checkAllocation(arr[i]);
strcpy(arr[i], temp);
}
*stringSize = size;
return arr;
}
int stringBinSearch(char** stringArr, int stringSize, char* stringToFind)
{
return binSearch(stringArr, stringSize, sizeof(char*), stringToFind,compare2Strings);
}
int binSearch(void* Arr, int size, int ElemSize, void* Item, int(*compare)(void*, void*))
{
int left = 0, right = size - 1, place;
BOOL found = FALSE;
while (found == FALSE && left <= right)
{
place = (left + right) / 2;
if (compare(Item, (BYTE*)Arr + place*ElemSize) == 0)
found = TRUE;
else if (compare(Item, (BYTE*)Arr + place*ElemSize) < 0)
right = place - 1;
else
left = place + 1;
}
return found;
}
int compare2Strings(void* str1, void* str2)
{
char* elemA, *elemB;
elemA = (char*)str1;
elemB = (char*)str2;
return strcmp(elemA, elemB);
}
答案 0 :(得分:0)
您好问题是您将字符串数组发送到二进制搜索功能的方式。因为你需要传递一个字符串数组,你的Arr参数必须是void**
而不是void*
int binSearch(void** Arr, int size, int ElemSize, void* Item, int(*compare)(void*, void*))
在您的函数中,只要您想从数组中访问字符串,就可以像以下一样访问它:(char*) *(Arr+place*ElemSize)
答案 1 :(得分:0)
对int
数组进行排序时,传递的值是指向int
,拼写为int *
的指针。对字符串数组(拼写为char *
)进行排序时,传递的值是指向字符串的拼写,拼写为char **
。比较器没有用于比较字符串。作为无法模仿的BLUEPIXY said非常简洁的样式 - 您需要修改代码以将传递的void *
参数视为char **
而不是char *
。
通过通用排序,这通常是问题的结束。使用二进制搜索,还有另一个问题,你犯了错误。也就是说,被搜索项目的类型需要与数组中的一个条目相同,因此您需要将指针传递给项目,而不仅仅是项目。
因此,添加材料以允许代码以最小的更改进行编译,从gets()
更改为fgets()
的封面(因为gets()
is too dangerous to be used — ever!和使用它的程序会在其中生成警告用于macOS Sierra 10.12.5 - warning: this program uses gets(), which is unsafe.
),并打印出输入数据,以便您可以看到它是什么,我最终得到:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BOOL int
#define TRUE 1
#define FALSE 0
static inline char *sgets(size_t buflen, char *buffer)
{
char *result = fgets(buffer, buflen, stdin);
if (result)
buffer[strcspn(buffer, "\n")] = '\0';
return result;
}
#define checkAllocation(x) assert((x) != 0)
#define SIZE 100
typedef unsigned char BYTE;
char **getStringArr(int *stringSize);
int stringBinSearch(char **stringArr, int stringSize, char *stringToFind);
int binSearch(void *Arr, int size, int ElemSize, void *Item, int (*compare)(void *, void *));
int compare2Strings(void *str1, void *str2);
int main(void)
{
char **stringArr, stringToFind[SIZE];
int stringSize;
int res;
stringArr = getStringArr(&stringSize);
sgets(sizeof(stringToFind), stringToFind);
printf("Strings: %d\n", stringSize);
for (int i = 0; i < stringSize; i++)
printf("[%d] = [%s]\n", i, stringArr[i]);
printf("Search: [%s]\n", stringToFind);
res = stringBinSearch(stringArr, stringSize, stringToFind);
if (res == 1)
printf("The string %s was found\n", stringToFind);
else
printf("The string %s was not found\n", stringToFind);
return 0;
}
char **getStringArr(int *stringSize)
{
int i, size, len;
char **arr;
char temp[SIZE];
scanf("%d", &size);
getchar();
arr = (char **)malloc(size * sizeof(char *));
checkAllocation(arr);
for (i = 0; i < size; i++)
{
sgets(sizeof(temp), temp);
len = strlen(temp);
temp[len] = '\0';
arr[i] = (char *)malloc((len + 1) * sizeof(char));
checkAllocation(arr[i]);
strcpy(arr[i], temp);
}
*stringSize = size;
return arr;
}
int stringBinSearch(char **stringArr, int stringSize, char *stringToFind)
{
return binSearch(stringArr, stringSize, sizeof(char *), &stringToFind, compare2Strings);
}
int binSearch(void *Arr, int size, int ElemSize, void *Item, int (*compare)(void *, void *))
{
int left = 0, right = size - 1, place;
BOOL found = FALSE;
while (found == FALSE && left <= right)
{
place = (left + right) / 2;
if (compare(Item, (BYTE *)Arr + place * ElemSize) == 0)
found = TRUE;
else if (compare(Item, (BYTE *)Arr + place * ElemSize) < 0)
right = place - 1;
else
left = place + 1;
}
return found;
}
int compare2Strings(void *str1, void *str2)
{
char *elemA = *(char **)str1;
char *elemB = *(char **)str2;
return strcmp(elemA, elemB);
}
关键变化是:
compare2Strings()
- 比较char **
值中的数据。stringBinSearch()
- 传递stringToFind
。AFAICR,任何其他变化都是化妆品或“基础设施”。
请注意the return type of main()
should be int
- 您只能在允许使用的Windows上使用void
。
示例运行1:
数据:
5
Antikythera
albatross
armadillo
pusillanimous
pygmalion
pygmalion
输出:
Strings: 5
[0] = [Antikythera]
[1] = [albatross]
[2] = [armadillo]
[3] = [pusillanimous]
[4] = [pygmalion]
Search: [pygmalion]
The string pygmalion was found
示例运行2:
数据文件:
5
armadillo
pygmalion
Antikythera
pusillanimous
albatross
pygmalion
输出:
Strings: 5
[0] = [armadillo]
[1] = [pygmalion]
[2] = [Antikythera]
[3] = [pusillanimous]
[4] = [albatross]
Search: [pygmalion]
The string pygmalion was not found
两组数据之间的区别在于,在第一种情况下,字符串处于正确的排序顺序 - 成功(可靠)二进制搜索的先决条件 - 在第二种情况下,数据的排序顺序不正确。 (也就是说,我有一个未排序的订单,仍然发现'pygmalion' - 我使用了不同的shuffle来显示结果。但'可靠'的评论适用。)
答案 2 :(得分:-1)
您编写通用二进制搜索的方法是正确的。但是,尝试提前返回会减慢二进制搜索速度。这也意味着你不能使用&#34;小于&#34;的C ++约定。是比较运算符定义。等到左右相等,然后返回。