这是我的第一篇文章,我必须承认,我在编程方面很糟糕。我是班上那个拼命工作的人,但似乎永远无法像其他同学那样掌握编程。所以请友善一点,我会在下面解释我的问题。
我有以下代码(删除了注释),但当我运行它时,我会收到类似于下面列出的警告。此外,当我运行程序时,第一个用户输入的值是允许的,但突然之间,它跳到程序的末尾,不允许我输入其他变量(例如变量"贝塔")的值。我有输出的图像(https://i.stack.imgur.com/yc3jq.jpg)你可以看到我输入了alpha,但是程序运行到最后。有什么想法吗?
非常感谢你的帮助!-Spencer
-----------------------------代码------------------
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
float alpha, beta, h;
float slope_k (float, float, float, float);
float slope_q (float, float, float, float);
float slope_p (float, float, float, float);
int main (void)
{
float t0=0, tf, h, S0, I0, R0, k1, k2, k3, k4, q1, q2, q3, q4, p1, p2, p3, p4;
int N;
char sim_file[1000];
FILE *out_file;
float *time_out, *s_out, *i_out, *r_out;
printf("Enter the value of the rate constant for infection (alpha) n");
scanf("&f", &alpha);
printf("Enter the value of the rate constant for recovery or death (beta) n");
scanf("&f", &beta);
printf("Enter the value of number of persons susceptible to the given contagion [S] at the initial time zero [i.e. S(t)=S(0) = ? ] n");
scanf("&f", &S0);
printf("Enter the value of the number of persons infected [I] at the intial time zero [i.e. I(t) = I(0) = ?] n");
scanf("&f", &I0);
printf("Enter the value of the number of persons that have already been infected but have recovered [or died] [R] at the initial time zero [i.e. R(t) = R(0) = ?] n");
scanf("&f", &R0);
printf("Enter the final time for solution n");
scanf("&f", &tf);
printf("Enter the solution step size (H) n");
scanf("&f", &h);
N = (int)(tf/h);
printf("Enter file solution to store solution to simulation n");
scanf("&s", sim_file);
out_file = fopen(sim_file, "w");
time_out = (float *)calloc(sizeof(float), N);
s_out = (float *)calloc(sizeof(float), N);
i_out = (float *)calloc(sizeof(float), N);
r_out = (float *)calloc(sizeof(float), N);
time_out[0]= 0;
s_out[0] = S0;
i_out[0] = I0;
r_out[0] = R0;
for(int i = 0; i < N; ++i);
{
int i = 0;
time_out[i+1] = (i+1)*h;
k1 = h*slope_k(time_out[i], s_out[i], i_out[i], r_out[i]);
q1 = h*slope_q(time_out[i], s_out[i], i_out[i], r_out[i]);
p1 = h*slope_p(time_out[i], s_out[i], i_out[i], r_out[i]);
k2 = h*slope_k(time_out[i]+(h/2), s_out[i]+(k1/2), i_out[i]+(q1/2), r_out[i]+(p1/2));
q2 = h*slope_q(time_out[i]+(h/2), s_out[i]+(k1/2), i_out[i]+(q1/2), r_out[i]+(p1/2));
p2 = h*slope_p(time_out[i]+(h/2), s_out[i]+(k1/2), i_out[i]+(q1/2), r_out[i]+(p1/2));
k3 = h*slope_k(time_out[i]+(h/2), s_out[i]+(k2/2), i_out[i]+(q2/2), r_out[i]+(p2/2));
q3 = h*slope_q(time_out[i]+(h/2), s_out[i]+(k2/2), i_out[i]+(q2/2), r_out[i]+(p2/2));
p3 = h*slope_p(time_out[i]+(h/2), s_out[i]+(k2/2), i_out[i]+(q2/2), r_out[i]+(p2/2));
k4 = h*slope_k((time_out[i] + h), (s_out[i]+k3), (i_out[i]+q3), (r_out[i]+p3));
q4 = h*slope_q((time_out[i] + h), (s_out[i]+k3), (i_out[i]+q3), (r_out[i]+p3));
p4 = h*slope_p((time_out[i] + h), (s_out[i]+k3), (i_out[i]+q3), (r_out[i]+p3));
s_out[i+1] = s_out[i] + (1.0/6)*(k1 + (2*k2) + (2*k3) + k4);
i_out[i+1] = i_out[i] + (1.0/6)*(q1 + (2*q2) + (2*q3) + q4);
r_out[i+1] = r_out[i] + (1.0/6)*(p1 + (2*p2) + (2*p3) + p4);
}
return 0;
}
float slope_k(float t, float s, float i, float r)
{
float slope_k_out;
slope_k_out = -alpha*s*i;
return slope_k_out;
}
float slope_q(float t, float s, float i, float r)
{
float slope_q_out;
slope_q_out = (alpha*s*i)-(beta*i);
return slope_q_out;
}
float slope_p(float t, float s, float i, float r)
{
float slope_p_out;
slope_p_out = beta*i;
return slope_p_out;
}
警告示例:
warning C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
编译器告诉您的是Microsoft认为scanf
不安全。
如果您小心的话,scanf
函数可以安全地使用。scanf
确实存在数字输入问题(溢出有未定义的行为),但scanf_s
并不能解决这些问题。
scanf_s
最初是Microsoft特有的扩展;它被添加为2011年ISO C标准的可选功能(N1570附录K)。许多C实现仍然没有提供scanf_s
。
引用C草案标准:
K.3.5.3.4p4:
scanf_s函数等效于参数为stdin的fscanf_s入到scanf_s的参数之前。
K.3.5.3.2p4:
fscanf_s函数等价于fscanf,和[转换说明符应用于一对参数(除非赋值抑制由*)。这些参数中的第一个与fscanf的参数相同。该参数在参数列表中紧跟第二个参数,其类型为rsize_t,并给出该对的第一个参数所指向的数组。如果第一个自变量指向标量对象,它被认为是一个元素。
对于这个特定的程序,使用scanf_s
而不是scanf
并不会使它更安全,但会降低它的可移植性。
使用_CRT_SECURE_NO_WARNINGS
并忽略警告。
编译器在这里告诉您的是函数scanf
不安全。scanf
有一个漏洞,如果被利用,可能会导致系统受损(称为缓冲区溢出攻击)。简而言之,错误在于没有告诉scanf
要读取多少字节进行输入。因此,scanf
将读取,直到它"相信"已完成读取输入。在char数组中,该末尾通常是空字符' '
。然而,如果从字符串中去掉' '
,scanf
将继续读取,直到找到该字节——通常,scanf
将到达其自己的虚拟内存空间之外的内存位置。此操作将导致操作系统向您的程序发送分段错误(seg错误),这将立即结束您的程序的存在。
更新的函数scanf_s
(_s
表示安全)允许您确定输入的最大大小,可以使用它更有效地防止缓冲区溢出攻击。如果这是一个硬件分配,看起来是这样的,你可以把scanf
留在那里。然而,要摆脱compilier警告并尝试成为一名更好的程序员,请修复它!使用sscanf_s
并有一个全局变量(或其他…)来确定最大输入大小(例如int SCANF_INPUT_SIZE = 1000
)。
祝你好运!
编辑--将这些"&f"
更改为"%f"
,这就是错误!
scanf将一个值读取到内存中,如果您读取的值比您给它的内存长(通常只是字符串的问题),它可能会覆盖其他内存并导致错误或病毒
scanfs是一个新版本,您可以告诉函数要读取的最大内存。
如果这只是只有您或受信任的用户才会使用的家庭作业代码,请不要担心