Scanf_s предупреждение? Пропускает вводимые пользователем данные (темы: Рунге-Кутта, Эпидемическое моделирование) - PullRequest
2 голосов
/ 03 апреля 2012

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

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

Большое спасибо за вашу помощь! -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.

Ответы [ 3 ]

5 голосов
/ 09 декабря 2013

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

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

scanf_s изначально было расширением Microsoft;он был добавлен в качестве дополнительной функции в стандарт ISO C 2011 года ( N1570 Приложение K).Многие реализации 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 и игнорируйте предупреждение.

2 голосов
/ 03 апреля 2012

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

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

Удачи!

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

0 голосов
/ 03 апреля 2012

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

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

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

...