我正在编写一个函数,该函数应该根据需要使用的参数来增加或减少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
答案 0 :(得分:1)
让我们做一些数学运算。您可以将数学分解成几行,然后通过调试器进行确认。
对于返回2的猜测的调用,您的静态变量为a == 1
和b == 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
介于minimum
和maximum
之间的逻辑,四舍五入为零;并且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);
对其进行初始化。
只要实现可读且易于理解,就可以了。我倾向于自己更喜欢预处理器宏样式,但这纯粹是样式问题。
请记住写注释来描述您的设计和意图,而不是描述代码的作用。该技能与编程本身一样重要。您会发现,在大多数情况下,只能编写但无法维护的代码不值得花很多钱来运行它。
(并且永远不要养成以为以后再添加错误检查和安全性内容的习惯。因为您不会这样做。没人会这样做。如果他们尝试,它们总是会失败。这是因为健壮性和安全性只能进行设计,之后再添加。)