- Ввод данных с клавиатуры в Си
- Для форматированного ввода данных в Си используется оператор scanf
- Урок 2 — Ввод/вывод, операции над числами
- 1 Потоковый ввод/вывод
- 2 Основные операции над числами
- 3 Справочный материал
- 3.1 Переменные и типы данных
- 3.2 Битовые операции
- 3.3 Приведение типов
- 3.4 Составное присваивание, инкремент/декремент
Ввод данных с клавиатуры в Си
Для форматированного ввода данных в Си используется оператор scanf
Чтобы ввести записать информацию в переменную с клавиатуры в си с помощью оператора scanf необходимо указать сообщение и переменную, в которую будет записываться с клавиатуры з начение
scanf (“формат ввода”,&имя переменной )
В формате ввода используется
%d ввод целого числа (переменная типа int)
%f ввод вещественного числа (переменная типа float)
%с ввод одного символа (переменная типа char)
Например:
scanf (“%d”, &a); // ввод с клавиатуры значения для целочисленной переменной a
Пример программы 3. Программа в си запрашивает ввод с клавиатуры двух целых чисел, выводит их сумму на экран
#include
#include
main()
<
int a,b,c;
printf(«Введите первое целое число\n»);
scanf(«%d», &a); // ввод переменной a с клавиатуры
printf(«Введите второе целое число\n»);
scanf(«%d», &b); // ввод переменной b с клавиатуры
c=a+b; // присваиваем переменной с значение a+b
printf(«%d+%d= %d\n», a,b,c); // форматированный вывод выражения a+b =c
getch(); // ждем нажатия кнопки
>
Для ввода строки в си с помощью оператора scanf необходимо объявить строку и считать ее с помощью scanf()
char имя строки[ длина строки];
scanf(“%s”, имя строки);
Пример программы 4. Программа запрашивает ввод имени и отчества с клавиатуры и выводит на экран приветствие с обращением по имени и отчеству
#include
#include
main()
<
char n[50];// объявляем строковую переменную n для имени
char sn[50];// объявляем строковую переменную sn для отчества
printf(«Как Ваше имя ?\n»);
scanf(«%s», n); // ввод строки n имени
printf(«Как Ваше отчество ?\n»);
scanf(«%s», sn);// ввод строки sn отчества
printf(«Здравствуйте, %s %s!\n», n, sn); // форматированный вывод Здравствуйте, n sn!
getch();
>
Вернуться к содержанию Перейти к следующему уроку Условия в Си.
Урок 2 — Ввод/вывод, операции над числами
В прошлом уроке мы выводили на экран текстовое сообщение, а сейчас займемся также вводом данных и заставим нашу программу что-нибудь посчитать. Содержание:
1 Потоковый ввод/вывод
В файле iostream.h находятся глобальные объекты std::cin и std::cout , позволяющие вводить данные с клавиатуры и выводить их на экран. Мы подключаем этот файл командой:
#include
Эти объекты называются потоками ввода/вывода. В дальнейших уроках мы узнаем и о других разновидностях таких потоков. Потоковый ввод/вывод осуществляется операциями >> и соответственно. Использовать их можно следующим образом:
В этой программе создается 3 переменных целого типа данных ( int ), в конце урока приведена более подробная информация об этом и других стандартных типах. Тут, как и в hello world использолся вызов функции std::cin.get() для задержки закрытия окна. На самом деле эта функция ( get ) ожидает ввода символа пользователем.
Также, в этом примере вы должны заметить комментарии к коду. Комментарием считается часть строки, расположенная правее двух слешей , а тажке текст (возможно многострочный), расположенный между символами /* и */ . Комментарии удаляются во время работы препроцессора (если забыли что это такое — освежите память) и, следовательно, не влияют на результаты компиляции. Используются комментарии только в качестве «подсказок» программисту.
Объект std::cin является потоком ввода, к нему можно применять оператор >> для получения значений переменных с клавиатуры:
Теперь значения переменных задаются не программистом, а пользователем (в процессе использования программы).
С помощью объекта cin и операции >> можно присвоить значение любой переменной. Например, если переменная x описана как целочисленная, то команда cin>>x; означает, что в переменную x будет записано некое целое число, введенное с клавиатуры. Если необходимо ввести несколько переменных, то можно написать:
cin >> x >> y >> z; .
2 Основные операции над числами
Чтобы быть полезной — наша программа должна делать что-то кроме ввода и вывода. В языке С++ поддреживается стандартный набор арифметических операций (для сложения, вычитания, деления и т.д.). Я рекомендую запустить следующий пример:
Директива using namespace std; сообщает компилятору, что в этом месте вы используете имена из пространства имен std , за счет нее вы, в частности, можете писать cout или cin вместо std::cout и std::cin . Тему пространств имен мы подробно изучим в следующих уроках.
Поиграйтесь с исходными числами, обратите внимание, что в результате деления вы получаете целое число (округляется вниз — как при выполнении операции div в Паскале). Очень часто вам будет пригождаться операция получения остатка от деления ( a%b ) — разберитесь с тем, что она возвращает.
Остальные приведенные тут операторы рядовым программистом используются значительно реже и более подробно рассмотрены в «справочнике», приведенном в конце урока.
Помимо целых чисел, компьютер может обрабатывать дробные — замените тип int в нашей программе на float или double , при попытке собрать программу вы получите ошибки, т.к. не все используемые тут операторы могут применяться к дробным числам. Изучите сообщения об ошибках — вам нужно научиться их читать. Запустите следующую программу:
Обратите внимание, что теперь даже если на вход будут поданы целые числа — результат операции деления будет дробным. Различия между типами данных double и float в данный момент для нас несущественны — достаточно помнить, что float обычно занимает 4 байта, а double — 8, за счет этого при вычислениях над переменными double мы можем получить более высокую точность и диапазон значений (см. справочный материал в конце урока).
Теперь рассмотрим изученное на примере более сложной задачи (наконец, заставим наш компьютер посчитать что-нибудь полезное):
Известны плотность p , высота h и радиус основания R цилиндрического слитка.
Найти объем V , массу m и площадь S основания слитка.
Составим текст программы, учитывая что:
$$S = \pi \cdot R \cdot R, \\
V = S \cdot h,\\
m = p \cdot V.$$
Результаты работы программы:
Исследуя эту программу, обратите внимание на:
- описание констант с помощью ключевого слова const . Константе значение присваивается лишь один раз, если вы попробуете сделать это еще раз — программа не скомпилируется. Очень хорошая практика — явно указывать константность везде, где это возможно. Это с одной стороны защитит вас от ошибок в дальнейшем (при попытке изменить константу вы сразу получите ошибку), а с другой — позволит генерировать более оптимальный код компилятору.
- в конце программы мы написали cin.get() дважды. Дело в том, что:
- функция get извлекает из потока cin один символ. Символы попадут в поток после нажатия пользователем кнопки Enter;
- оператор >> считывает из потока слово и, в нашем случае, преобразует его в число. Исследуя программы, вы должны были заметить, что если ввести в одной строке несколько чисел — то «сработают» сразу несколько последовательных операторов ввода. Мы пользовались этим, например, при исследовании математических операторов;
- считав первое слово с потока — оператор >> не «трогает» остальные символы. В результате, в потоке остается символ-разделитель — в нашем случае — символ перевода строки (соответствующий клавише Enter). Этот символ и будет считан первым вызовом функции get() ;
- таким образом, если оставить только один вызов get() программа отобразит на экран результаты вычислений и сразу завершится. Второй вызов get() ожидает еще одного нажатия клавиши Enter пользователем;
- вам нужно помнить об этом всякий раз, когда вы используете get после оператора >> .
- в этой программе не так легко разобраться, как хотелось бы и очень легко запутаться. Проблема заключается в «плохих» именах переменных. По мере усложнения ваших программ эта проблема станет более очевидной. Заведите правило — давать переменным имена, которые отражают суть. Более подробно про это можно прочитать в статье «Теория чистого кода. Стиль кодирования«. Попробуйте переписать эту программу, используя более понятные имена.
3 Справочный материал
3.1 Переменные и типы данных
Переменная это область памяти заполненная данными, которые называются значением переменной. У каждой переменной должно быть своё уникальное имя на латинице с учетом регистра. Переменные делятся на целочисленные, дробные, символьные, логические (т.е «да» или «нет»).
Для решения задачи в любой программе выполняется обработка каких-либо данных. К основным типам данных языка C++ относят:
- char — символьный;
- int — целый;
- float — дробное число с плавающей точкой;
- double — дробное число двойной точности;
- bool — логический.
- void — неполный тип и спецификатор типа. Множество значений этого типа пусто (поэтому его нет в таблице ниже). Он используется для определения функций, которые не возвращают значения, а также как базовый тип для указателей. Вы не можете создать переменную этого типа, позже станет понятно как им пользоваться.
Для формирования других типов данных используют основные и так называемые спецификаторы:
- short — короткий;
- long — длинный;
- signed — знаковый;
- unsigned — беззнаковый.
- const — константа.
В таблице приведена справочная информация о различных комбинациях типов данных с учетом спецификаторов для операционной системы Windows:
Имя типа | Размер (в байтах) | Диапазон значений |
---|---|---|
int (signed int) | 4 | От -2 147 483 648 до 2 147 483 647 |
unsigned int | 4 | От 0 до 4 294 967 295 |
bool | 1 | false или true |
char (unsigned char) | 1 | -128 до 127 знаков по умолчанию |
signed char | 1 | От -128 до 127 |
unsigned char | 1 | От 0 до 255 |
short (signed short) | 2 | От -32 768 до 32 767 |
unsigned short | 2 | От 0 до 65 535 |
long (signed long) | 4 | От -2 147 483 648 до 2 147 483 647 |
unsigned long | 4 | От 0 до 4 294 967 295 |
long long (signed long long) | 8 | От -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 |
unsigned long long | 8 | От 0 до 18 446 744 073 709 551 615 |
float | 4 | 3,4E +/- 38 (7 знаков) |
double (long double) | 8 | 1,7E +/- 308 (15 знаков) |
wchar_t | 2 | От 0 до 65 535 |
Тип char предназначен для хранения символов, обрабатывать строки (состоящие из символов) мы научимся в следующих уроках, сейчас нужно знать, что внутри компьютера символы хранятся в виде целых чисел в небольшом диапазоне. Преобразование символов в числа и назад производится на основе кодовых таблиц, которые можно менять (в зависимости от языка — русский, английский, китайский, …). Строка записывается в двойных кавычках («hello world»), а одиночный символ — в одинарных (‘a’).
Тип wchar_t также используется для хранение символов, однако занимает 2 байта (в Unix — 4 байта) и хранит данные в формате Юникода.
Переменная типа bool может принимать только два значения true (истина) или fasle (ложь), тем не менее, в памяти занимает не 1 бит, а 1 байт. Любое значение, не равное нулю, интерпретируется как true .
3.2 Битовые операции
Битовые операции применяются к числам в двоичном коде. При необходимости вы можете узнать больше о двоичном коде и правилах перевода чисел из одной системы счисления в другую из статей:
Ниже показано как выполняется операция логического ИЛИ для такого фрагмента кода:
Подобным образом работают операции — И ( a & b ), исключающее ИЛИ ( a ^ b ). Операции и >> , примененные для чисел, осуществляют битовый сдвиг двоичного представления числа влево и вправо на заданное число разрядов.
$$
Ниже: 20_<10>\;-\;число\;20\;в\;десятичной\;системе\;счисления, \\
10001_<2>\;-\;число\;20\;в\;двоичной\;системе\;счисления. \\
20_<10>\;|\;17_ <10>= 10001_2\;|\;10100_2 = 10101_2 = 21_<10>. \\
20_<10>\;\&\;17_ <10>= 10001_2\;\&\;10100_2 = 10000_2 = 16_<10>. \\
20_<10>\;\hat<>\;17_ <10>= 10001_2\;\hat<>\;10100_2 = 00101_2 = 5_<10>. \\
47_ <10>> 2 = 101111_2 >> 2 = 1011_2 = 11_<10>.
$$
3.3 Приведение типов
В C++ различают два вида преобразования типов данных: явное и неявное.
Неявное преобразование происходит автоматически. Это выполняется во время сравнения, присваивания или вычисления выражения различных типов. Например, следующая программа выведет на консоль значение типа float .
Наивысший приоритет получает тот тип, при котором произойдет минимальная потеря информации (в результате округления). Не стоит злоупотреблять неявным преобразованием типов, так как могут возникнуть разного рода непредвиденные ситуации.
В этом примере при присваивании выполнится неявное приведение переменной типа float к типу int . В результате работы программы на экран будет выведено число 123 .
Явное преобразование в отличие от неявного осуществляется программистом. Записать это можно следующим образом:
b = (int) a;
или
b = int(a);
Тут мы явно указываем, что переменной b нужно присвоить значение a, приведенное к типу int .
Приведенные ниже конструкции могут встретиться вам при просмотре чужого исходного кода, вам нужно иметь представление о них, при необходимости — более подробно прочитайте в статье «Явное приведение типов в C++«.
В С++ определены следующие операторы:
- static_cast<> () — осуществляет преобразование связанных типов данных. Этот оператор приводит типы по обычным правилам, что может потребоваться в случае, когда компилятор не выполняет автоматическое преобразование. Синтаксис будет выглядеть так:
Тип static_cast (объект);
С помощью static_cast нельзя убрать константность у переменной, но это по силам следующему оператору.
const_cast<> () — применяется только тогда, когда нужно снять константность у объекта. Синтаксис будет выглядеть следующим образом:
Тип const_cast (объект);
reinterpret_cast<> () — применяется для преобразования указателей разных типов, целых к указателю и наоборот. Если вы увидели новое слово «указатель» — не пугайтесь! это тоже тип данных, но работать с ним Мы будем не скоро. Синтаксис тут такой же как, у ранее рассмотренных операторах:
Тип reinterpret_cast (объект);
Тип dynamic_cast (объект);
3.4 Составное присваивание, инкремент/декремент
В ваших программах часто нужно выполнить что-то типа
a = a+b;
вместо такой конструкции можно использовать специальный вид оператора:
a += b;
Еще чаще в программах нужно увеличивать или уменьшать значение переменной ровно на единицу:
Для таких случаев в С++ тоже определены специальные операторы: ++ и — . Каждый из которых имеет две формы — префиксную и постфиксную, понять которые можно изучив пример:
В этом примере оба вида оператора применяются к переменной a и оба они приводят к увеличению значения переменной на единицу. Однако, постфиксная форма возвращает старое значение пеерменной (до инкремента), а префиксная — новое значение. Поэтому на экран будет выведено:
Аналогично работает постфиксный и префиксный декремент (оператор — ).
Здравствуйте!
Интересно, когда нужно использовать целую переменную, часто ли пишут что-то кроме int? Когда на практике это бывает нужно?
В каком-нибудь небольшом цикле, к примеру, от 0 до 9, в учебниках обычно используют тип int.
Нечасто. Если эта переменная будет создана одна — то смысла оптимизировать (заменять ее на short или char) — нет. Мало того, это называется преждевременной оптимизацией и это плохо, т.к. реально усложняет восприятие кода.
На практике бывает нужно. Ну например, пишите вы игру, в которой перемещаются миллионы объектов. При этом объекты распределяются по слоям — наземные, летающие (ну может быть в будущем вы добавите подземеные). Также объектами являтся природа (трава, горы, деревья). Если объекты другом не пересекаются, то реально вам нужно только 4-5 слоев. Ну может быть незначительно больше (например для анимаций падающих или идущих на посадку самолетов и т.п.). И в силу того, что таких объектов миллионы и каждый из них мог бы хранить номер слоя — тут стоит использовать char для этого номера. На каждом миллионе объектов мы пр этом сэкономили бы примерно 3Мб оперативной памяти.
Хотя, опять же, заморачиваться с этим на ранних этапах разработки не стоит. Лучше пораньше выпустить программу, а потом уже заниматься ее профилированием.