伪随机数生成器依赖种子来生成它们的随机数:如果您使用相同的种子,您将得到相同的"随机"数序列.
请看这里:
请考虑以下代码:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
srand(0);
printf("random number 1: %d\n", rand());
printf("random number 2: %d\n", rand());
printf("random number 3: %d\n", rand());
printf("random number 4: %d\n", rand());
return 0;
}
多次运行程序(a.out
)总是生成相同的数字:
marco@Marcos-MacBook-Pro-16 Desktop % ./a.out
random number 1: 520932930
random number 2: 28925691
random number 3: 822784415
random number 4: 890459872
marco@Marcos-MacBook-Pro-16 Desktop % ./a.out
random number 1: 520932930
random number 2: 28925691
random number 3: 822784415
random number 4: 890459872
marco@Marcos-MacBook-Pro-16 Desktop % ./a.out
random number 1: 520932930
random number 2: 28925691
random number 3: 822784415
random number 4: 890459872
marco@Marcos-MacBook-Pro-16 Desktop % ./a.out
random number 1: 520932930
random number 2: 28925691
random number 3: 822784415
random number 4: 890459872
当然,这exact个数字在用于生成数字的具体实现上会有所不同.因此,在您的系统中,数字序列可能会有所不同.然而,使用相同的种子将始终导致相同的序列.
真实系统使用"真实"(基于物理随机性)随机数和伪随机数生成器的组合,因为这样生成随机数的方式更有效.
这些数字通常是cryptographically secure pseudorandom number generators,因为这些数字用于加密操作(密码学在很大程度上依赖随机性来工作).
其基本思想是,只要初始种子是"秘密的"(未知的),您就不能将其返回并确定生成的预定义数字序列.
只需查看伪随机数生成器生成的数,就可以(并且已经完成)恢复初始种子.
Now on how to solve the exercise given by your professor:个
最简单的方法是"冻结"时间,为随机数设置一个固定的种子值(如上面的代码示例所示).
由于没有一种简单的方法来做到这一点,您可以通过运行另一个程序来打印当前种子,从而只输出生成的第一个随机数(因为这是"秘密"):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(0));
printf("the secret number is %d\n", rand());
return 0;
}
然后你可以用这个数字来"解锁"你教授给出的程序.
您必须在一秒或更短的时间内完成此操作,因为time()
将返回新值every秒.
更可靠的方法是让程序在生成"随机"数后立即输入它.
以下是如何实现这一点的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
// where to put the "random" number on disk
const char *tmp_file = "/tmp/input";
// where the executable of your professor is
const char *executable = "/path/to/your/professors/executable";
void writeRandomNumberToDisk(const char *path, int number) {
char buf[128];
// convert int to string
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%d\n", number);
FILE *fp = fopen(path, "w+");
fwrite(buf, strlen(buf), 1, fp);
fclose(fp);
}
int main(void) {
srand(time(0));
int secret = rand();
printf("the secret number is %d\n", secret);
writeRandomNumberToDisk(tmp_file, secret);
char buf[512];
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "/bin/sh -c 'cat %s | %s'", tmp_file, executable);
printf("Now executing %s\n", buf);
system(buf);
return 0;
}
本质上,它将第一个"随机"数写入磁盘,然后调用将把"随机"数提供给程序的shell 程序.
您也可以使用如下命令完全绕过文件系统:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
// where the executable of your professor is
const char *executable = "/path/to/your/professors/executable";
int main(void) {
srand(time(0));
int secret = rand();
printf("the secret number is %d\n", secret);
char buf[512];
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "/bin/sh -c 'printf \"%d\\n\" | %s'", secret, executable);
printf("Now executing %s\n", buf);
system(buf);
return 0;
}