Предупреждение Scanf_s? Пропускает пользовательский ввод (темы: Рунге-Кутта, моделирование эпидемий)

Это мой первый пост, и я должен признать, что я ужасен в программировании. Я тот парень в классе, который работает изо всех сил, но, кажется, никогда не может понять программирование так, как остальные мои одноклассники. Поэтому, пожалуйста, будьте любезны, я попытаюсь объяснить свою проблему ниже.

У меня есть следующий код (комментарии удалены), но когда я запускаю его, я получаю предупреждение, подобное приведенному ниже. Кроме того, когда я запускаю программу, первое введенное пользователем значение разрешено, но затем внезапно оно переходит в конец программы, не позволяя мне вводить значения для других переменных (например, переменная «бета» ). У меня есть изображение вывода (http://i.stack.imgur.com/yc3jq.jpg) и вы видите, что я ввожу альфу, но тогда программа работает до конца. Какие-нибудь мысли?

Большое спасибо за вашу помощь! -Спенсер

-----------------------------КОД----------------

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

person user1309448    schedule 03.04.2012    source источник


Ответы (3)


Здесь компилятор говорит вам, что функция scanf небезопасна. scanf содержит ошибку, которая, если ее использовать, может привести к компрометации системы (так называемая атака переполнения буфера). Вкратце, ошибка в том, что scanf не сообщается, сколько байт считывать для ввода. Таким образом, scanf будет читать до тех пор, пока не «поверит», что чтение ввода завершено. В массиве символов этим концом обычно является нулевой символ '\0'. Однако, если '\0' исключить из строки, scanf будет продолжать чтение до тех пор, пока не найдет этот байт — обычно scanf достигает области памяти, находящейся за пределами его собственного пространства виртуальной памяти. Это действие приведет к тому, что ОС отправит вашей программе ошибку сегментации (ошибку сегментации), которая в итоге прекратит существование вашей программы.

Более новая функция, scanf_s (_s для защиты), позволяет определить максимальный размер входных данных, который можно использовать для более эффективного предотвращения атак переполнения буфера. Если это для назначения HW, что выглядит так, вы можете оставить scanf там. Однако, чтобы избавиться от предупреждения компилятора И попытаться стать лучшим программистом, исправьте это! Используйте sscanf_s и создайте глобальную переменную (или что-то в этом роде...), которая определяет максимальный размер ввода (например, int SCANF_INPUT_SIZE = 1000 ).

Удачи!

РЕДАКТИРОВАТЬ. Измените эти "&f" на "%f", это ошибка!

person Malcolm    schedule 03.04.2012

Компилятор говорит вам, что Microsoft считает scanf небезопасным.

Функцию scanf можно безопасно использовать, если вы будете осторожны. У scanf действительно есть проблемы с числовым вводом (переполнение имеет неопределенное поведение), но scanf_s не устраняет эти проблемы.

scanf_s изначально было расширением Microsoft; он был добавлен в качестве дополнительной функции в стандарт ISO C 2011 г. (N1570 Приложение К). Многие реализации C до сих пор не предоставляют scanf_s.

Цитирование стандарта проекта C:

K.3.5.3.4p4:

Функция scanf_s эквивалентна fscanf_s с аргументом stdin, вставленным перед аргументами функции scanf_s.

K.3.5.3.2p4:

Функция fscanf_s эквивалентна fscanf, за исключением того, что функции c, s и [ > спецификаторы преобразования применяются к паре аргументов (если только подавление присваивания не указано знаком *). Первый из этих аргументов такой же, как и для fscanf. Сразу после этого аргумента в списке аргументов следует второй аргумент, который имеет тип rsize_t и дает количество элементов в массиве, на который указывает первый аргумент пары. Если первый аргумент указывает на скалярный объект, он считается массивом из одного элемента.

Использование scanf_s вместо scanf для этой конкретной программы не делает ее более безопасной, но делает ее менее переносимой.

Используйте _CRT_SECURE_NO_WARNINGS и игнорируйте предупреждение.

person Keith Thompson    schedule 09.12.2013

scanf считывает значение в память, если значение, которое вы читаете, длиннее, чем память, которую вы ему даете (обычно только проблема со строками), это может перезаписать какую-то другую память и привести к ошибке или вирусу

scanf_s — это новая версия, в которой вы сообщаете функции максимальную память для чтения.

Если это только домашний код, который будете использовать только вы или доверенный пользователь - не беспокойтесь.

person Martin Beckett    schedule 03.04.2012
comment
Спасибо чувак! Я понял, что это не имеет никакого отношения к scanf_s. Я поставил & вместо % для %f! ой! - person user1309448; 03.04.2012