Зачем в scanf амперсанд
Перейти к содержимому

Зачем в scanf амперсанд

  • автор:

 

Ввод данных в языке Си. Функция scanf

Основная задача этого шага научиться получить данные от пользователя.

Для этого можно использовать функцию scanf . Она, так же как и функция printf , описана в заголовочном файле stdio.h . Т.к. он у нас уже подключен в первой строке, то мы можем свободно использовать функцию scanf в своей программе.

Чтобы считать данные, которые ввёл пользователь, и сохранить их в переменную, нужно вызвать функцию scanf со следующими параметрами:

Общий синтаксис функции scanf

Рис.1. Общий синтаксис функции scanf.

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

Основные спецификаторы формата:

%d — целые числа
%f — вещественное число типа float
%lf — вещественное число типа double (обозначение lf от long float)
%c — символ

Обратите внимание, что в функции scanf для типов float и double используются различные спецификаторы формата.

После формат-строки нужно указать адрес переменной, в которую нужно сохранить данные. Чтобы указать адрес переменной достаточно перед её именем записать знак & (амперсанд), как на рисунке выше.

Напишем, наконец-таки, программу сложения двух чисел.

Скомпилируйте и запустите эту программу. После того, как программа запущена она будет ждать пока вы введёте данные. Мы с вами знаем какие данные нужно вводить, т.к. мы писали эту программу. Для других пользователей, которые код программы не увидят, хорошо бы вывести на экран подсказку, какие данные нужно ввести. Посмотрите как это реализовано в следующем примере.

Эта программа будет полезна тем, кто следит за своим здоровьем. Данная программа подсчитывает уроверь базового обмена веществ по формуле Миффлина-Сан Жеора исходя из данных, которые вы введёте (возраст, рост и вес).

На самом деле, функция scanf – функция форматного ввода. Она устроена чуть ли не сложнее, чем printf . Но рассказывать новичку об особенностях её работы значит понапрасну грузить его лишней информацией. На данном этапе вам будет достаточно и этих знаний, а когда появится необходимость использовать что-то большее, вы с этим сможете сами разобраться. А может и я в каком-нибудь уроке расскажу.

Сохрани в закладки или поддержи проект.

Практика

Решите предложенные задачи. Для удобства работы сразу переходите в полноэкранный режим

Зачем в scanf амперсанд

Для ввода данных в консоли может использоваться функция scanf() . Эта функция определена в заголовочном файле stdio.h (там же, где и функция printf) и имеет следующее формальное определение:

И форматная_строка, и аргументы для функции scanf обязательны.

Форматная_строка содержит спецификации преобразования, которые определяют вводимые данные. Общий вид спецификаций преобразования:

Из этих элементов обязательны только два: знак процента % и спецификатор.

Спецификатор определяет тип вводимых данных:

%c : считывает один символ

%d : считывает десятичное целое число

%i : считывает целое число в любой системе (десятичной, шестнадцатеричной, восьмеричной)

%u : считывает положительное целое число

%e : считывает число с плавающей точкой в экспоненциальной форме

%E : считывает число с плавающей точкой в экспоненциальной форме с заглавным символом экспоненты

%f : считывает число с плавающей точкой

%F : считывает число с плавающей точкой

%g : считывает число с плавающей точкой

%G : считывает число с плавающей точкой

%o : считывает восьмеричное число

%x : считывает шестнадцатеричное число

%X : считывает шестнадцатеричное число

%s : считывает строку

%% : считывает символ процента

Символ звездочки * в спецификации преобразования позволяет пропустить при вводе водимые символы для типа, указанного через спецификатор.

Ширина_поля представляет целое положительное число, которое позволяет определить, какое количество байтов будет учитываться при вводе.

Модификаторы позволяют конкретизировать тип данных. В частности, есть следующие модификаторы:

h : для ввода значений типа short int ( %hd )

l : для ввода значений типа long int ( %ld ) или double ( %lf , %le )

L : для ввода значений типа long double ( %Lf , %Le )

В качестве аргументов в функцию scanf() передаются адреса переменной, которая будет получать введенное значение. Для получения адреса переменной перед ее именем ставится знак амперсанда & . Например, если переменная называется age , то ее адрес мы можем получить с помощью выражения &age .

Например, введем с консоли числовое значение:

Здесь вводится значение для переменной age, которая представляет тип int , поэтому в форматную строку в функции scanf передается спецификатор %d . Здесь не используется ни символ звездочки, ни ширина поля, ни модификаторы. Вторым параметром идет адрес переменной age — &age .

После ввода значения мы можем его использовать, например, вывести на консоль:

 

Аналогичен будет ввод данных других типов:

После ввода значения мы можем его использовать, например, вывести на консоль:

Можно сразу вводить несколько значений. В этом случае в качестве разделителя используется пробел:

При вводе данных в консоли функция scanf может использовать пробелы в качестве разделителей, чтобы выдернуть из ввода значения для определенных переменных. Консольный ввод-вывод:

Ввод строк

Функция scanf() также позволяет вводить строки. Например:

Здесь для имени выделяется 10 символов. Теоретически мы можем ввести и большее количество символов, но чтобы только 10 из них учитывались, в строку форматирования передается ширина поля, которая представляет 10 символов — %10s . Когда функция считает достаточное количетсво символов, она прекратит считывание.

Обратите внимание, что для ввода строки перед названием переменной не указывается символ адреса.

Потому что название массива уже само по себе представляет адрес на первый элемент массива.

Возможный консольный вывод:

Однако при использовании этой функции мы можем столкнуться с рядом проблем. Прежде всего попробуйте ввести в предыдущем примере составное имя, в которм подстроки разделены пробелами, например, «Tom Smith».

Для решения этой проблемы можно использовать один хак:

Спецификатор %10[^\n] указавает, что мы по прежнему считываем неболее 10 символов. Квадратные скобки [] представляют позволяют определить набор символов, которые будут извлекаться из ввода или, наоборот, игнорироваться. Так, выражение [^\n] говорит, что надо считать ввод до тех пор пока не встретиться символ перевода строки ‘\n’, то есть пока пользователь не нажмет на клавишу Enter.

When should I use ampersand with scanf()

What are the rules for using ampersand in c while using scanf() ?

Why for String do I not need to use the the ampersand and for int I have to use it?

Is there a rule on when to use the ampersand sign?

Antti Haapala -- Слава Україні's user avatar

Dkova's user avatar

3 Answers 3

scanf reads particular types of data into addresses which are passed as second, third, fourth and so on arguments.

Here var is value and &var is address. The above statement says: read %d (integer) type of data into &var address.

Here s is address not the value because s is a character array (string). An array name itself indicates its address. s == &s[0], these are both the same.

The above statement says: read %s (array of characters) type of data into address location starting from s .

There is no single format specifier to scan group of integers at a time as like scanning group of characters at time with the help of %s.

And here a=&a[0]; you can scan single integer value directly to the address which is pointed by a .

if you enter 10 then prints a[0]=10 .

Usage of Pointers:

if you use pointers as shown below, then you will come to know how to increment the pointer and get the values into different locations of array.

You can move the pointer location to read arrays. You can read arrays without moving pointer location.

Reading arrays by moving pointer locations

Reading arrays with out moving pointer locations.

When a pointer is incremented then the increment is dependent on the type of pointer. Here ptr is an integer pointer so ptr+1 will increment ptr+sizeof(int) locations.

This is two dimensional array so you require 5 pointers to scan so I was declared pointer array.

Как работает функция scanf в C?

Зачем нужен амперсанд (&) в scanf функция. Какой будет вывод или тип ошибки (компиляция или время выполнения) в следующем коде C?

Как в сторону, main Возвращает int , Не void . — Alok Singhal

7 ответы

Компания & в C — оператор, возвращающий адрес операнда. Подумайте об этом так, если бы вы просто дали scanf переменная a без & , он будет передан ему по значению, что означает scanf не сможет установить его значение, чтобы вы его увидели. Передача по ссылке (с использованием & фактически передает указатель на a ) позволяет scanf чтобы установить его так, чтобы вызывающие функции тоже увидели изменение.

Что касается конкретной ошибки, вы не можете точно сказать. Поведение не определено. Иногда он может продолжать работать беззвучно, без вашего ведома. scanf изменил какое-то значение где-то в вашей программе. Иногда это приводит к немедленному сбою программы, как в этом случае:

Компиляция показывает следующее:

И выполнение показывает ошибку сегментации:

В C все аргументы функции передаются по значению; любые изменения формального параметра функции не отражаются в фактическом параметре. Например:

Вывод программы будет

, так как: bar получает значение x (0), а не ссылка на x сам. Изменение bar не влияет на x .

В C способ обойти это — передать указатель к переменной:

Теперь вывод программы

На этот раз формальный параметр bar не int, а указатель в int, и он получает адрес of x (задается выражением &x в призыве к foo ), а не значение, содержащееся в x. Выражение *bar означает «получить значение в адресной строке» указывает на«, так *bar = *bar + 1 соответствует x = x + 1 .

С scanf() должен писать в свои аргументы, он ожидает, что эти аргументы будут набраны как указатели. Спецификатор преобразования «% d» ожидает, что соответствующий аргумент будет указателем на int ( int * ) спецификатор преобразования «% u» ожидает указатель на unsigned int ( unsigned * ), «% s» ожидает указатель на char ( char * ), «% f» ожидает указатель на float ( float * ) и т.д. В вашем примере, поскольку a набирается int , вам нужно использовать выражение &a чтобы получить указатель.

Обратите внимание, что если a уже были типом указателя, вам не нужно было бы использовать & оператор при звонке на scanf() :

Также обратите внимание, что при передаче массива в функцию (например, при использовании спецификатора преобразования «% s» для чтения строки) вам не нужно использовать & оператор; выражение массива будет неявно преобразовано в тип указателя:

 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *