Меню

Scanf c выдает ошибку

Здравствуйте. При попытке компиляции проекта возникает следующая ошибка:

Ошибка 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.
код программы:

#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "stdio.h"

int main()
{
    int a;
    scanf("%d", &a);
    return 0;
}

P.S: при использовании scanf_s компиляция проходит успешно, почему не работает с scanf? Среда разработки visual studio

Harry's user avatar

Harry

210k15 золотых знаков114 серебряных знаков224 бронзовых знака

задан 9 дек 2017 в 20:09

Вячеслав161's user avatar

Просто функция считается небезопасной, позволяющей в принципе привести к переполнению буфера (и сопутствующим неприятностям, вплоть до взлома программы хакерами :))

Поэтому вас предупреждают об использовании потенциально небезопасной функции.

Используя

#define _CRT_SECURE_NO_WARNINGS

вы говорите — да, я знаю и принимаю на себя всю ответственность.

ответ дан 9 дек 2017 в 20:16

Harry's user avatar

HarryHarry

210k15 золотых знаков114 серебряных знаков224 бронзовых знака

7

Это диагностическое сообщение является «ошибкой» только если у вас в установках проекта включены SDL Checks. Если выключить SDL Checks, то «ошибка» превратится в «предупреждение».

Чтобы избавиться от него полностью, определите макро _CRT_SECURE_NO_WARNINGS перед включением стандартных заголовочных файлов. Лучше всего сделать это глобально, в настройках проекта.

ответ дан 9 дек 2017 в 20:31

AnT stands with Russia's user avatar

0 / 0 / 0

Регистрация: 28.04.2011

Сообщений: 18

1

09.05.2011, 18:28. Показов 97686. Ответов 21


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

подскажите как исправить =(

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

09.05.2011, 18:28

21

resource2008

111 / 112 / 18

Регистрация: 11.03.2011

Сообщений: 421

09.05.2011, 21:33

2

использовать

C++
1
scanf_s

и это не ошибка, а предупреждение.



2



600 / 568 / 104

Регистрация: 07.11.2010

Сообщений: 2,004

09.05.2011, 22:06

3

Цитата
Сообщение от Yuki
Посмотреть сообщение

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

подскажите как исправить =(

это майкрософт типа говорит использовать, но это не относится к стандарту, не юзайте



0



0 / 0 / 0

Регистрация: 28.04.2011

Сообщений: 18

10.05.2011, 00:30

 [ТС]

4

спасибо)



0



0 / 0 / 0

Регистрация: 13.09.2012

Сообщений: 13

12.10.2012, 07:45

5

Цитата
Сообщение от panicwassano
Посмотреть сообщение

это майкрософт типа говорит использовать, но это не относится к стандарту, не юзайте

таак, а если у меня из-за этой ошибки не компилируется? чо делать?

а, тьфу, дошло, спасибо



0



831 / 639 / 100

Регистрация: 20.08.2013

Сообщений: 2,524

20.09.2013, 20:35

6

А у меня почему-то в новом проекте VS2012 выдала

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

С какого перепуга оно стало ошибкой, а не предупреждением?

Да,

#define _CRT_SECURE_NO_WARNINGS решает проблему, но всё-таки весьма неприятно получить такую ошибку… Есть другие способы борьбы с ней?

Добавлено через 6 минут
Хм.. Предупреждения типа

error C4146: unary minus operator applied to unsigned type, result still unsigned

тоже стали ошибками

Похоже с настройками что-то…



0



5493 / 4888 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

20.09.2013, 20:39

7

Не знаю, как в 12, но в 10, в свойствах проекта — С++ — Общие, есть пункт: Обрабатывать предупреждения как ошибки.



1



831 / 639 / 100

Регистрация: 20.08.2013

Сообщений: 2,524

20.09.2013, 22:18

8

Цитата
Сообщение от alsav22
Посмотреть сообщение

Не знаю, как в 12, но в 10, в свойствах проекта — С++ — Общие, есть пункт: Обрабатывать предупреждения как ошибки.

В ПН проверю. А как он оказался включенным в только что созданном проекте? Это где-то в настройках студии?



0



5493 / 4888 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

20.09.2013, 22:32

9

Цитата
Сообщение от Qwertiy
Посмотреть сообщение

А как он оказался включенным в только что созданном проекте? Это где-то в настройках студии?

….

Цитата
Сообщение от alsav22
Посмотреть сообщение

Не знаю, как в 12

Цитата
Сообщение от alsav22
Посмотреть сообщение

в 10, в свойствах проекта — С++ — Общие, есть пункт: Обрабатывать предупреждения как ошибки.



0



831 / 639 / 100

Регистрация: 20.08.2013

Сообщений: 2,524

20.09.2013, 22:41

10

Цитата
Сообщение от alsav22
Посмотреть сообщение

в 10, в свойствах проекта — С++ — Общие, есть пункт: Обрабатывать предупреждения как ошибки.

Я спросил, как настраивается его состояние при создании нового проекта.



0



5493 / 4888 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

20.09.2013, 22:50

11

Цитата
Сообщение от Qwertiy
Посмотреть сообщение

Я спросил, как настраивается его состояние при создании нового проекта.

Всё что знаю — написал.



0



831 / 639 / 100

Регистрация: 20.08.2013

Сообщений: 2,524

13.12.2013, 17:32

12

Цитата
Сообщение от Qwertiy
Посмотреть сообщение

Я спросил, как настраивается его состояние при создании нового проекта.

Сам разобрался — см. скриншот.

PS: Перечислю тех, кого это может интересовать, чтобы они получили уведомления: alsav22, Oceloto, max_besheniy, Sveta073, ranebull.

Миниатюры

Ошибка в SCANF
 



6



5493 / 4888 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

13.12.2013, 17:37

13

Это при создании проекта консоль Win32? А если пустой создавать?



0



545 / 378 / 56

Регистрация: 23.06.2013

Сообщений: 1,181

Записей в блоге: 6

13.12.2013, 18:16

14

Цитата
Сообщение от alsav22
Посмотреть сообщение

Это при создании проекта консоль Win32? А если пустой создавать?

Да, это ситуация при создании проекта консоль Win32. При создании пустого проекта выдаются лишь предупреждения.



0



5493 / 4888 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

13.12.2013, 18:42

15

Цитата
Сообщение от ranebull
Посмотреть сообщение

При создании пустого проекта выдаются лишь предупреждения.

Это точно? 12 или 13 студия? Проверено?



0



545 / 378 / 56

Регистрация: 23.06.2013

Сообщений: 1,181

Записей в блоге: 6

13.12.2013, 18:47

16

Цитата
Сообщение от alsav22
Посмотреть сообщение

Это точно? 12 или 13 студия? Проверено?

Скриншоты

Миниатюры

Ошибка в SCANF
 

Ошибка в SCANF
 



1



5493 / 4888 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

13.12.2013, 19:18

17

А там нет, как в 10, создание пустого проекта (Общие — Пустой), без всяких окон мастера?



0



25 / 25 / 5

Регистрация: 21.11.2013

Сообщений: 208

13.12.2013, 19:18

18

Цитата
Сообщение от Qwertiy
Посмотреть сообщение

Сам разобрался — см. скриншот.

PS: Перечислю тех, кого это может интересовать, чтобы они получили уведомления: alsav22, Oceloto, max_besheniy, Sveta073, ranebull.

Почему я получил уведомление?



0



5493 / 4888 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

13.12.2013, 19:21

19

Интересует: эту настройку можно сделать только убрав галку в этом окне, или где-то ещё, в свойсвах проекта, можно сделать?



0



545 / 378 / 56

Регистрация: 23.06.2013

Сообщений: 1,181

Записей в блоге: 6

13.12.2013, 19:24

20

Цитата
Сообщение от alsav22
Посмотреть сообщение

А там нет, как в 10, создание пустого проекта (Общие — Пустой), без всяких окон мастера?

Есть, но тут выдает ошибку…
В самом проекте проверка SDL отключается следующим образом: Проект->Свойства: %имя проекта%->C/C++ ->Проверки SDL->Нет(/sdl-)

Миниатюры

Ошибка в SCANF
 

Ошибка в SCANF
 



3



2 Августа 2017

Время чтения: 5 минут

Visual Studio unsafe error скриншот

Компилятор в Visual Studio сильно отличается от привычных большинству программистов GCC или CLANG, из-за чего при написании кода на C или C++ очень часто возникают неожиданные проблемы в виде ошибки использования стандартных функций, например, scanf, fopen, sscanf и тому подобным. Студия предлагает заменять функции на безопасные (повезёт, если нужно просто добавить _s к функции с ошибкой, но нередко в этих функциях идёт иной набор аргументов, нежели в обычной программе). Если вы не готовы с этим мириться, то этот пост для вас!

Давайте для начала создадим обычный консольный проект в Visual Studio и напишем простенькую программу, которая запрашивает ввод двух чисел, вводит их и затем выводит на экран.

#include "stdafx.h"
#include <stdio.h>

int main() {
	int a, b;

	printf("Enter a: ");
	scanf("%d", &a);

	printf("Enter b: ");
	scanf("%d", &b);

	printf("a: %d, b: %dn", a, b);
	return 0;
}

Попробовав выполнить сборку проекта, обнаружим те самые ошибки.

Чтобы Visual Studio не тратила ваши нервы, сделаем следующее:

1. Выберем пункт «Проект» в верхнем меню

2. В открывшемся списке щёлкнем по «Свойства название_проекта»

Программа, вводящая два числа и выводящая их

Программа, вводящая два числа и выводящая их

Ошибка компиляции из-за небезопасности функций

Ошибка компиляции из-за небезопасности функций

Проект -> Свойства {навание проекта}

Проект — Свойства {навание проекта}

3. В появившемся окне выберем Свойства конфигурации, C/C++, Препроцессор

4. В строке Определения препроцессора допишем в самый конец строку ;_CRT_SECURE_NO_WARNINGS

5. Нажмём ОК

Свойства конфигурации

Свойства конфигурации

Определения препроцессора

Определения препроцессора

OK

Нажимаем OK

6. Попробуем заново выполнить сборку проекта:

Успешная сборка проекта

Успешная сборка проекта

Ошибки исчезли, сборка прошла успешно и программа прекрасно работает! Теперь можно писать код как обычно, не переживая о необычном поведении Visual Studio!

Фото Перминова Андрея, автора этой статьи

Программист, сооснователь programforyou.ru, в постоянном поиске новых задач и алгоритмов

Языки программирования: Python, C, C++, Pascal, C#, Javascript

Выпускник МГУ им. М.В. Ломоносова

For scanf, you need to check its return value to see if the conversion on the input worked. scanf will return the number of elements successfully scanned. If the conversion did not work, it will leave the input alone, and you can try to scan it differently, or just report an error. For example:

if (scanf("%d", &i) != 1) {
    char buf[512];
    fgets(buf, sizeof(buf), stdin);
    printf("error in line %d: got %s", j, buf);
    return 0;
}

In your program, since the input is left alone, your loop repeats trying to read the same input.

In C++, you check for failure using the fail method, but the input stream failure state is sticky. So it won’t let you scan further without clearing the error state.

    std::cin >> i;
    if (std::cin.fail()) {
        std::string buf;
        std::cin.clear();
        std::getline(cin, buf);
        std::cout
             << "error in line " << j
             << ": got " << buf
             << std::endl;
        return 0;
    }

In your program, since you never clear the failure state, the loop repeats using cin in a failure state, so it just reports failure without doing anything.

In both cases, you might find it easier or more reliable to work with the input if you would read in the input line first, and then attempt to parse the input line. In pseudocode:

while read_a_line succeeds
    parse_a_line

In C, the catch to reading a line is that if it is longer than your buffer, you will need to check for that and concatenate multiple fgets call results together to form the line. And, to parse a line, you can use sscanf, which is similar to scanf but works on strings.

    if (sscanf(buf, "%d", &i) != 1) {
        printf("error in line %d: got %s", j, buf);
        return 0;
    }

In C++, for quick low level parsing of formatted input, I also prefer sscanf. But, if you want to use the stream approach, you can convert the string buffer into a istringstream to scan the input.

    std::getline(cin, buf);
    if (std::cin.fail()) {
        break;
    }
    std::istringstream buf_in(buf);
    buf_in >> i;
    if (buf_in.fail()) {
        std::cout << "error in line " << j
             << ": got " << buf
             << std::endl;
        return 0;
    }

For scanf, you need to check its return value to see if the conversion on the input worked. scanf will return the number of elements successfully scanned. If the conversion did not work, it will leave the input alone, and you can try to scan it differently, or just report an error. For example:

if (scanf("%d", &i) != 1) {
    char buf[512];
    fgets(buf, sizeof(buf), stdin);
    printf("error in line %d: got %s", j, buf);
    return 0;
}

In your program, since the input is left alone, your loop repeats trying to read the same input.

In C++, you check for failure using the fail method, but the input stream failure state is sticky. So it won’t let you scan further without clearing the error state.

    std::cin >> i;
    if (std::cin.fail()) {
        std::string buf;
        std::cin.clear();
        std::getline(cin, buf);
        std::cout
             << "error in line " << j
             << ": got " << buf
             << std::endl;
        return 0;
    }

In your program, since you never clear the failure state, the loop repeats using cin in a failure state, so it just reports failure without doing anything.

In both cases, you might find it easier or more reliable to work with the input if you would read in the input line first, and then attempt to parse the input line. In pseudocode:

while read_a_line succeeds
    parse_a_line

In C, the catch to reading a line is that if it is longer than your buffer, you will need to check for that and concatenate multiple fgets call results together to form the line. And, to parse a line, you can use sscanf, which is similar to scanf but works on strings.

    if (sscanf(buf, "%d", &i) != 1) {
        printf("error in line %d: got %s", j, buf);
        return 0;
    }

In C++, for quick low level parsing of formatted input, I also prefer sscanf. But, if you want to use the stream approach, you can convert the string buffer into a istringstream to scan the input.

    std::getline(cin, buf);
    if (std::cin.fail()) {
        break;
    }
    std::istringstream buf_in(buf);
    buf_in >> i;
    if (buf_in.fail()) {
        std::cout << "error in line " << j
             << ": got " << buf
             << std::endl;
        return 0;
    }

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Scan failed with code 10h afterburner ошибка
  • Scad ошибка при разложении матрицы