编写一个在c中分割间隔的函数

时间:2018-12-19 17:55:28

标签: c

我正在编写一个函数,该函数应该根据需要使用的参数来增加或减少1到100之间的间隔。

它从(0,100)开始,然后,如果parameter=-1变成(0,50),如果之后parameter=1,它变成(25, 50)。它存储最后一个“猜测”,并根据该猜测给出下一个。

我想知道当parameter=-1(应该减少间隔的部分)时我在做什么错。其他部分工作正常,您不必查看它们,它们给出的预期输出为(-1)一个为25 12 6 3 2而不是25 12 6 3 1

代码如下:

#include <stdio.h>

int NextGuess(int  param) {

    int num;
    static int a=1, b=99;

    //this part is where it goes wrong (the output doesn't match with the expected one)//
    if (param==-1) //less
    {
        b-=(a+b)/2 - a+1;
        num=(a+b)/2;
    }
    //these below are doing fine//

    if (param==1) //greater
    {
        a+=(a+b)/2 - a+1;
        num=(a+b)/2;
    }

    if (param==0) //equal
    num=(a+b)/2;

    return num;
}
//main isn't important, it's just for testing the output//
int main() {
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
//output should be: 25 12 6 3 1  but this gives: 25 12 6 3 2    
    return 0;
}

如果有人可以指出我在那部分做错了什么,那么我考虑这个简单的事情已经太久了...

该函数在调用时应输出的其他示例:

printf ("%d ", NextGuess(1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(-1));
printf ("%d ", NextGuess(1));
//output: 75 62 56 59

2 个答案:

答案 0 :(得分:1)

让我们做一些数学运算。您可以将数学分解成几行,然后通过调试器进行确认。

对于返回2的猜测的调用,您的静态变量为a == 1b == 6

因此,(清理后的)代码

b-=(a+b)/2 - a + 1;
num=(a+b)/2;

我们得到:

`a` + `b` == 7
7 / 2 == 3 (integer math)
3 - 1 + 1 == 3
6 - 3 == 3
num = (1 + 3) / 2 == 2

编辑:这是返回所需序列的代码。虽然不能保证我没有破坏您的+1序列:)

int NextGuess(int  param) {
    int num;
    static int a=0, b=100;
    static int lastGuess = 50;

    //printf("%d %d %d %d\n", a, b, interval, lastGuess);
    if (param==-1) //less
    {
        b = lastGuess;
    }
    else if (param==1) //greater
    {
        a = lastGuess + 1;
    }

    lastGuess = (a+b) / 2;

    return lastGuess;
}

答案 1 :(得分:0)

让我展示一些反例,而不是批评。请考虑以下内容:

struct intrange {
    int   minimum;
    int   maximum;
};

这些限制包括在内。您可以按值传递结构,并像其他任何类型一样分配它们。要拆分这样的结构,您可以使用

struct intrange  intrange_split(const struct intrange  range,
                                const int              half)
{
    /* Midpoint of the range, rounding towards zero */
    const int        midpoint = (range.minimum + range.maximum) / 2;
    struct intrange  result;

    if (half > 0) {
        /* Upper half, including midpoint. */
        result.minimum = midpoint;
        result.maximum = range.maximum;
    } else
    if (half < 0) {
        /* Lower half, excluding midpoint. */
        result.minimum = range.minimum;
        result.maximum = midpoint - 1;
    } else {
        /* No change. */
        result = range;
    }

    return result;
}

上面的intrange_split()函数采用一个不完整的结构range作为参数,并使用一个整数half来指示如何对其进行拆分。没有错误检查。

如果要对通过引用传递的结构进行操作,可以使用say

int intrange_split(struct intrange *range, int half)
{
    int midpoint;

    /* No range? Invalid range? */
    if (!range || range->maximum < range->minimum)
        return -1; /* Invalid range. */

    /* Note: This could overflow. */
    midpoint = (range->minimum + range->maximum) / 2;

    if (half == 1) {
        /* Upper half, including midpoint. */
        range->minimum = midpoint;
    } else
    if (half == -1) {
        /* Lower half, excluding midpoint. */
        range->maximum = midpoint - 1;
    } else {
        /* Invalid operation. */
        return -1;
    }

    /* Verify range is valid (non-empty). */
    if (range->maximum < range->minimum)
        return -1;

    /* Range is valid, and not empty. */
    return 0;
}

更常见的是使用返回值来表示C中的成功/错误,因为与C ++不同,它没有例外。 (您也可以使用断言,或显示错误消息,然后显示abort()exit(EXIT_FAILURE),这取决于该错误是否可恢复。)

在以上所有情况下,我都使用midpoint介于minimummaximum之间的逻辑,四舍五入为零;并且midpoint属于上限范围。您可以选择如何定义定义,只要您明确做出选择并记录下来即可。看看这些方法要简单多少?

使用预处理器宏或静态内联函数初始化变量也很常见。例如,在这种情况下

#define  INTRANGE_INIT(min, max)  { min, max }

static inline struct intrange intrange_define(const int minimum,
                                              const int maximum)
{
    struct intrange  result = { minimum, maximum };
    return result;
}

,以便您可以在代码中使用例如struct intrange my_range = INTRANGE_INIT(0, 100);。当然,您也可以使用struct intrange my_range = { 0, 100 };甚至struct intrange my_range; my_range = intrange_define(0, 100);对其进行初始化。

只要实现可读且易于理解,就可以了。我倾向于自己更喜欢预处理器宏样式,但这纯粹是样式问题。

请记住写注释来描述您的设计和意图,而不是描述代码的作用。该技能与编程本身一样重要。您会发现,在大多数情况下,只能编写但无法维护的代码不值得花很多钱来运行它。

(并且永远不要养成以为以后再添加错误检查和安全性内容的习惯。因为您不会这样做。没人会这样做。如果他们尝试,它们总是会失败。这是因为健壮性和安全性只能进行设计,之后再添加。)