【问题标题】:Recursive binary searching function doesn't return -1 for value that's not existant in the array递归二进制搜索函数不会为数组中不存在的值返回 -1
【发布时间】:2018-03-07 03:49:42
【问题描述】:

我正在尝试使用递归进行二进制排序功能。它适用于 list[] 结构数组中存在的值。但是,当我输入一个我知道不在数组内的值时,它不是返回 -1,而是返回垃圾值。我在 MVS 中使用调试器跟踪了代码,但可能(事实上,肯定是)一些我看不到的东西。

谁能告诉我为什么它不返回 -1?

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

#define MAX 20

typedef struct
{
    char name[MAX] = "";
    char surname[MAX] = "";
    int id;
}patient;

int binarySearch(patient list[], char *target, int top, int bottom, int *comparisons)
{
    int center;
    center = (top + bottom) / 2;
    if (strcmp(list[center].surname, target) == 0)
        return center;
    (*comparisons)++;

    if (top == center || bottom == center)
        return -1;
    if (strcmp(list[center].surname, target) == 1)
        return binarySearch(list, target, center - 1, bottom, comparisons);
    if (strcmp(list[center].surname, target) == -1)
        return binarySearch(list, target, top, center + 1, comparisons);
}

int main(void)
{
    FILE *fi = fopen("patients.txt", "r");

    if (fi == NULL)
        printf("Problem opening file!");
    else
    {
        patient list[MAX];
        int i = 0, comparisons = 0, index;
        char target[MAX] = "";

        while (fscanf(fi, "%s %s %d", &list[i].name, &list[i].surname, &list[i].id) != EOF)
            i++;

        printf("Enter the surname of the patient (END to exit): ");
        scanf("%s", target);

        index = binarySearch(list, target, i, 0, &comparisons);

        printf("%-15s %-15s %-15d\n", list[index].name, list[index].surname, list[index].id);
        printf("%d comparisons\n", comparisons);

    }
}

【问题讨论】:

  • 通常,您必须提供 MCVE。请参阅网站指南,了解有关主题或离题的更多信息。
  • @UlrichEckhardt 你好。老实说,我认为这个问题有点 MCVE,但我完全可能是错的。请您指出您的建议,使其更合适,以便我尽快提供?
  • 要成为 MCVE,人们应该能够编译和运行您提供的内容,并让输出确认您陈述的问题。就目前而言,我不得不猜测你做了什么来驱动它并编写更多代码来运行它。
  • @pjs 哦。我认为发布整个代码会很浪费。让我更新一下问题。
  • 取决于“整个代码”是什么。 MCVE 的“最小”部分提供了足够的代码来说明问题。

标签: c recursion binary-search


【解决方案1】:

你得到一个垃圾值,因为你最后的条件不是详尽的。

strcmp表示第一个值在第二个值之后,不需要返回1。唯一的要求是它返回一个正数。同样适用于小于和负的-1。因此,您的函数可能最终到达终点而没有点击 return,这是未定义的行为。

您需要更改ifs 链以将返回值与零进行比较。作为一种优化,您应该存储一次比较结果,然后在整个条件中重复使用它:

int binarySearch(patient list[], char *target, int top, int bottom, int *comparisons)
{
    int center = (top + bottom) / 2;
    (*comparisons)++;
    int cmp = strcmp(list[center].surname, target);
    if (cmp == 0)
        return center;
    if (top == center || bottom == center)
        return -1;
    if (cmp > 0)
        return binarySearch(list, target, center - 1, bottom, comparisons);
    else // cmp < 0 here
        return binarySearch(list, target, top, center + 1, comparisons);
}

另请注意,为了准确计算比较次数,(*comparisons)++ 应该在strcmp 调用之前发生。

【讨论】:

  • 谢谢。这绝对是对代码的改进!但是,更新功能后问题仍然存在。
  • @SarpSTA 它非常适合我 (demo)。
  • 有趣。我会更多地研究它,尝试自己找到问题。感谢您的帮助!
  • @SarpSTA 只是为了确保您的 "patients.txt" 文件按字母顺序排序,对吗?
  • 是的。它按姓氏的字母顺序排列
【解决方案2】:

如何节省时间:1) 确保编译器警告完全启用。 2)使用好的编译器。

我希望下面会生成类似“警告:控制到达非无效函数的结尾”的警告,为您提供比堆栈溢出更好且更快的反馈。

  if (strcmp(list[center].surname, target) == -1)
    return binarySearch(list, target, top, center + 1, comparisons);
}

其他好的编译器反馈"error: expected ':', ',', ';', '}' or '__attribute__' before '='"

typedef struct {
  char name[MAX] = "";  // not valid to initialize.

“在 MVS 中使用调试器跟踪代码”--> 让我想知道您是否将 C 代码编译为 C++ 代码。

【讨论】:

  • 为什么char name[MAX] = ""; 无效?
  • @SarpSTA char name[MAX] = ""; 本身是有效的。它作为typedef 的一部分无效。你用的是什么 C 编译器?
  • 无论是 MVS2017 自带的那个。可能是你提到的 C++ 编译器。
猜你喜欢
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 2019-01-19
相关资源
最近更新 更多