2012-04-03 22 views
2

这是我的第一篇文章,我不得不承认,编程时我很糟糕。我是班上的那个人,尽管他的尾巴已经消失,但似乎永远无法掌握编程以及其他同学。所以请保持好心情,我会尽力在下面解释我的问题。Scanf_s警告?跳过用户输入(主题:龙格库塔,流行模拟)

我有下面的代码(评论删除),但是当我运行它时,我收到类似于下面列出的警告。另外,当我运行程序时,第一个用户输入的值是允许的,但是突然之间,它跳转到程序结束,不允许我输入其他变量的值(例如变量“beta” )。我有一个输出图像(http://i.stack.imgur.com/yc3jq.jpg),你可以看到我输入了alpha,但是程序运行到最后。有什么想法吗?

非常感谢您的帮助! -Spencer

----------------------------- CODE ------------- ---

#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. 

回答

2

什么编译器在这里告诉你的是,该功能scanf是不是安全。 scanf有一个错误,如果被利用,可能会导致系统受到攻击(称为缓冲区溢出攻击)。简而言之,这个错误是一个人不会告诉scanf要输入多少个字节。因此scanf将会读取,直到它“完全”读完输入。在一个char数组中,这个结尾通常是空字符'\0'。但是,如果从字符串中除去'\0',则scanf将继续读取,直至找到该字节 - 通常,scanf将到达其自己的虚拟内存空间之外的内存位置。此操作将导致操作系统向您的程序发送一个分段错误(seg fault),该错误一般会结束程序的存在。

更新的函数scanf_s_s用于安全)可让您确定输入的最大大小,您可以使用该大小更有效地防止缓冲区溢出攻击。如果这是HW分配,它看起来就是这样,您可以在那里离开scanf。但是,要摆脱compilier警告并尝试成为更好的程序员,请修复它!使用sscanf_s并有一个全局变量(或其他...)来确定最大输入大小(例如int SCANF_INPUT_SIZE = 1000)。

祝你好运!

编辑 - 将那些"&f"更改为"%f"这就是错误!

0

scanf函数读取值到内存中,如果你正在阅读的价值比你给它的内存(通常只有一个较长的问题与字符串)它可能覆盖一些其他内存并导致错误或病毒

scanf_s是一个新版本,您可以告诉函数需要读取的最大内存。

如果这是只有你或受信任的用户将只使用功课码 - 别担心

+0

谢谢你!我意识到它与scanf_s无关。我为“%f”放了一个&而不是%!哎呀! – user1309448 2012-04-03 04:16:54

4

什么编译器告诉你的是微软认为scanf是不安全的。

scanf功能可以如果您小心使用可以安全使用。 scanf确实有数字输入问题(溢出具有未定义的行为),但scanf_s不能解决这些问题

scanf_s最初是Microsoft特定的扩展;它被添加为2011 ISO C标准(N1570附件K)的可选功能。许多C实现仍然不提供scanf_s

引用标准C草案:

K.3.5.3.4p4:

scanf_s函数等效于fscanf_s用参数标准输入 参数之前插入到scanf_s

K.3.5.3.2p4:

fscanf_s函数等效于的fscanf除了Ç小号, 和[转换说明适用于一对参数(除非 分配抑制由 表示*)。这些论点中的第一个与fscanf相同。该参数紧接在参数列表中,第二个 参数的类型为rsize_t,并给出该对的第一个参数指向的数组 中的元素数。如果第一个参数指向标量对象,则它被认为是一个元素的数组。

使用scanf_s而不是scanf这个特定程序使得没有安全,但导致其便携性较差。

使用_CRT_SECURE_NO_WARNINGS并忽略警告。