为什么这个代码的三个数字是“-666 3289 1617”并且能够打印最后一行?
Why the three numbers for this code is "-666 3289 1617" and able to print the last line?
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
static int64_t arr[] = { 20047, 75106, 19594, 88069, 22445, 82238 };
const static int N = sizeof(arr)/sizeof(*arr);
static void fail(){
puts("Nope!");
exit(EXIT_FAILURE);
}
static void func_one(int64_t r, int64_t i, int64_t g){
if ( r - g / 7 + 3 * i / 11 )
fail();
}
static void func_two(int z, int64_t b){
int o = b;
for(; z<N; ++z) {
if ((z % 2) == 0)
continue;
o += arr[z];
}
if (o != 188394)
fail();
}
static void func_three(int d, int64_t e){
if (d<N) {
if (d % 2)
func_three(++d, e);
else func_three(d + 1, e * arr[d]);
} else if (e != 190100988)
fail();
}
int main(){
int64_t p, q, v;
printf("Please enter the right three numbers: ");
fflush(stdout);
if (scanf("%" SCNd64 " %" SCNd64 " %" SCNd64,&p,&q,&v) != 3)
fail();
arr[0] = p;
arr[5] = q;
arr[4] = v;
func_two(0, 21930);
func_three(1, 6);
func_one(p, q, v);
puts("Exactly! Good job.");
}
我传递了三个输入值:“-666 3289 1617”。这些输入对代码做了什么并且能够打印最后一行“Exactly!干得好。”?有什么办法可以找到其他输入值吗?这里到底发生了什么。
如果函数的测试未通过,func…
函数中的每一个都会调用 fail
,并且 fail
例程以“不!”终止程序。信息。因此,目标是获得“完全正确!做得好。”消息需要通过测试。
该程序尝试从输入中读取三个数字,分别称为 p
、q
和 v
。应该注意的是,如果存在各种错误,例如算术溢出或由于 scanf
未接收到合适的输入而使用未初始化的变量,则程序的行为未由 C 标准定义,所以程序可能会打印出“Exactly!做得好。”在这种情况下。但是,此答案的其余部分将在分析程序时排除未定义的行为。
读取数字p
、q
和v
后,程序将它们放在arr
中的特定位置,留下arr
值 p
、75106、19594、88069、v
和 q
.
然后程序调用func_two(0, 21930)
。 func_two
使用第一个参数 0 作为循环计数器,并使用第二个参数 21930 开始累加和。在循环中,它对循环计数器的偶数值 z
不执行任何操作。对于 z
的奇数值,它会将 arr[z]
添加到总和中。因此,对于 21930,它将 arr[1]
、arr[3]
和 arr[5]
相加,形成总和 21930 + 75106 + 88069 + q
。要通过,这个总和必须等于 188394。所以我们有 21930 + 75106 + 88069 + q
= 188394,其解决方案是 q
= 3289.
然后程序调用func_three(1, 6)
。 func_three
也使用它的第一个参数作为循环计数器,d
,并通过递归的方式使用 e
作为累加积,e
。当 d
为奇数时,func_three
仅使用递增的 d
调用自身,而 e
没有变化。当 d
是偶数时,func_three
以递增的 d
和 e
乘以 arr[d]
.
调用自身
由于d
从1开始,第一次偶数是2的时候。因此,func_three
从e
开始设置为6,然后乘以arr[2]
然后 arr[4]
,产生 6 • 19594 • v
。然后递归结束,因为 d
到达数组大小的末尾 N
,并且函数应用其测试:此乘积必须等于 190100988。所以我们有 6 • 19594 • v
= 190100988,其解为v
= 1617.
然后函数调用func_one(p, q, v)
,我们现在知道一定是func_one(p, 3289, 1617)
。它调用这些参数 r
、i
和 g
并计算 r - g / 7 + 3 * i / 11
,它必须为零才能通过测试。代入我们得到 p - 1617 / 7 + 3 * 3289 / 11
,它减少到 p - 231 + 897
并进一步减少到 p + 666
。显然,要使其为零,p
必须为 −666。
因此,产生输出“Exactly!做得好。”没有未定义的行为是 -666 3289 1617
或等价物,例如带有前导零的相同数字。
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
static int64_t arr[] = { 20047, 75106, 19594, 88069, 22445, 82238 };
const static int N = sizeof(arr)/sizeof(*arr);
static void fail(){
puts("Nope!");
exit(EXIT_FAILURE);
}
static void func_one(int64_t r, int64_t i, int64_t g){
if ( r - g / 7 + 3 * i / 11 )
fail();
}
static void func_two(int z, int64_t b){
int o = b;
for(; z<N; ++z) {
if ((z % 2) == 0)
continue;
o += arr[z];
}
if (o != 188394)
fail();
}
static void func_three(int d, int64_t e){
if (d<N) {
if (d % 2)
func_three(++d, e);
else func_three(d + 1, e * arr[d]);
} else if (e != 190100988)
fail();
}
int main(){
int64_t p, q, v;
printf("Please enter the right three numbers: ");
fflush(stdout);
if (scanf("%" SCNd64 " %" SCNd64 " %" SCNd64,&p,&q,&v) != 3)
fail();
arr[0] = p;
arr[5] = q;
arr[4] = v;
func_two(0, 21930);
func_three(1, 6);
func_one(p, q, v);
puts("Exactly! Good job.");
}
我传递了三个输入值:“-666 3289 1617”。这些输入对代码做了什么并且能够打印最后一行“Exactly!干得好。”?有什么办法可以找到其他输入值吗?这里到底发生了什么。
如果函数的测试未通过,func…
函数中的每一个都会调用 fail
,并且 fail
例程以“不!”终止程序。信息。因此,目标是获得“完全正确!做得好。”消息需要通过测试。
该程序尝试从输入中读取三个数字,分别称为 p
、q
和 v
。应该注意的是,如果存在各种错误,例如算术溢出或由于 scanf
未接收到合适的输入而使用未初始化的变量,则程序的行为未由 C 标准定义,所以程序可能会打印出“Exactly!做得好。”在这种情况下。但是,此答案的其余部分将在分析程序时排除未定义的行为。
读取数字p
、q
和v
后,程序将它们放在arr
中的特定位置,留下arr
值 p
、75106、19594、88069、v
和 q
.
然后程序调用func_two(0, 21930)
。 func_two
使用第一个参数 0 作为循环计数器,并使用第二个参数 21930 开始累加和。在循环中,它对循环计数器的偶数值 z
不执行任何操作。对于 z
的奇数值,它会将 arr[z]
添加到总和中。因此,对于 21930,它将 arr[1]
、arr[3]
和 arr[5]
相加,形成总和 21930 + 75106 + 88069 + q
。要通过,这个总和必须等于 188394。所以我们有 21930 + 75106 + 88069 + q
= 188394,其解决方案是 q
= 3289.
然后程序调用func_three(1, 6)
。 func_three
也使用它的第一个参数作为循环计数器,d
,并通过递归的方式使用 e
作为累加积,e
。当 d
为奇数时,func_three
仅使用递增的 d
调用自身,而 e
没有变化。当 d
是偶数时,func_three
以递增的 d
和 e
乘以 arr[d]
.
由于d
从1开始,第一次偶数是2的时候。因此,func_three
从e
开始设置为6,然后乘以arr[2]
然后 arr[4]
,产生 6 • 19594 • v
。然后递归结束,因为 d
到达数组大小的末尾 N
,并且函数应用其测试:此乘积必须等于 190100988。所以我们有 6 • 19594 • v
= 190100988,其解为v
= 1617.
然后函数调用func_one(p, q, v)
,我们现在知道一定是func_one(p, 3289, 1617)
。它调用这些参数 r
、i
和 g
并计算 r - g / 7 + 3 * i / 11
,它必须为零才能通过测试。代入我们得到 p - 1617 / 7 + 3 * 3289 / 11
,它减少到 p - 231 + 897
并进一步减少到 p + 666
。显然,要使其为零,p
必须为 −666。
因此,产生输出“Exactly!做得好。”没有未定义的行为是 -666 3289 1617
或等价物,例如带有前导零的相同数字。