HTML, Excel, Word, SEOОсновы JavaScript ⇒ Переменные, операторы, операции

ОСНОВЫ JavaScript

Учебник JavaScript
·Знакомство с JS. Переменные, операторы, операции
·Функции
·Модель HTML документа
·Иерархия документов в бразуере
·Формы
·Окна и фреймы
·Ссылки, заголовок, статус
·События
·События клавиатуры и мыши
·События. Таймер
·Стили. Управление стилями
·Слои и блоки. Управление видимостью
·Объекты JS
·Внешние объекты
·Внутренние объекты
·Массивы
·Регулярные выражения
·Математика в JS
·Пример простого калькулятора
·Дата и время
·Cookies и хранение состояния
·Немного об AJAX
·Работа с WebMoney

 
Сабмит сайта в каталоги

Знакомство с JS. Переменные, операторы, операции



Типы и значения в JS

Переменная в JS

Операции - арифметические, логические

Операторы - циклы, сравнения. Ветвление программ

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


Если не считать «обертку» из html-кода, то ее текст будет вот таким: 


	<script language="javascript"> 
		alert("Здесь был JavaScript");
	</script> 

Рассмотрим этот текст построчно. 


Строка  


        <script language="javascript">


говорит браузеру о том, что все что находится дальше (то есть, до закрытия тэга) будет скриптом. Причем скрипт будет написан на языке JavaScript.


Вообще, язык часто не указывается, и по умолчанию большинство браузеров считает, что это будет именно Javascript, но скрипты также могут быть написаны на языке VisualBasic, Tcl, PerlScript — в общем, на любом встраиваемом языке, который поддерживается браузером.


Для того же, чтобы браузер был уверен в языке скрипта, этот язык явно указывается в теге.  

По правде говоря, указание языка в виде language="LanguageName" считается устаревшей, и вместо нее рекомендуется использовать, например, такое объявление скрипта:


	<script type="text/javascript">

То есть вместо объявления языка указывается MIME-тип содержимого тега. 


Следующая строка —  


	alert("Здесь был JavaScript");

— собственно, и есть сам скрипт. Пока что это одна команда — вызов встроенной функции alert(). Эта функция поддерживается всеми браузерами, хотя каждый браузер реагирует на нее по-своему. Так, браузер Opera, например, обязательно кроме самого текста выводит еще и URL сайта, который вызвал открытие окна уведомления, и еще немного дополнительной информации. Internet Explorer выводит окно уведомления с заголовком «Internet Explorer», а Mozilla Firefox — с заголовком «Javascript application».


Это простейший пример того, о чем было сказано в первой главе — а именно, различиям в выполнении одного и того же кода. 


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


Если бы в скобках стояла строка "Здесь не было JavaScript" (что, конечно, было бы неправдой) — то браузер показал бы окно с надписью «Здесь не было Javascript». 


Третья строка скрипта — </script>


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


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


Первый способ мы только что разобрали буквально по строчке. Второй мало чем от него отличается, кроме того, что самого скрипта в HTML-документе не будет. 


Этот скрипт будет где-нибудь в отдельном файле, например, в файле script.js, находящимся рядом с главным HTML-скриптом.


Для того чтобы браузер знал, где лежит этот скрипт, нужно написать, например, такой код: 


	<script type="text/javascript" src="script.js"></script> 

Здесь внутри тегов <script> пусто, а сам код скрипта загружается из указанного файла. 


Есть еще два способа, которые редко упоминаются в литературе, и используются очень ограниченно (поэтому я называл два способа, а не четыре — именно первыми двумя способами мы в основном будем пользоваться). 


Один из них — это написание скрипта в параметре обработчика события какого-либо HTML элемента (например, onLoad у элемента <body>) — обычно используется исключительно для привязки события к скрипту, уже подключенного любым из предыдущих способов.


Второй — это размещение скрипта прямо в строке браузера (т.е. В строке, в которой вводится адрес сайта, можно написать «javascript:alert('Этотоже Js');», и такой код будет работать.


Но подобная практика, как я уже говорил, используется очень редко, только в отдельных немногочисленных случаях. 


Типы и значения в JS

Вернемся к нашим alert'ам. То есть, к строке alert("Здесь был JavaScript");


Как вы думаете, что будет , если написать alert(123.45); ?


Правильно, браузер выведет окошко с текстом «123.45».


То, что мы передавали в функцию, принято называть значениями. 


И «"Здесь был JavaScript"», и «123.45», и «true» — все это значения. Имеются в виду строки, числа, логические константы, массивы — все, чем может оперировать JavaScript. Каждое значение имеет свой, четко определенный тип.


Так, «"Здесь был JavaScript"» — это строка. «123.45» — число с плавающей точкой. «true» — логическое значение.  


В целом Javascript  умеет обращаться с 5 примитивными типами (их иногда называют простыми), а также с объектами, массивами и функциями.


Вот простые типы: 


Number (Числа), Boolean (логические значения), String (строки), null (это специальный тип — «ничто») и undefined (еще более специальный тип — «неопределенность», но о нем позже).


Стоит заметить, что у специальных типов название и значение совпадают. То есть у значения null тип null, а у значения undefined тип undefined.


Я упомянул об объектах и массивах. Да, можно записать целый массив (то есть — последовательность разных значений) в виде одного значения. Делается это так: 


[1, "Здесь был JavaScript", true]— теперь у нас есть массив, содержащий число, строку и логическую константу. И его, как и любое другое значение, можно вывести при помощи функции alert.


Для того чтобы понять, что такое массив, можно представить себе маленькую картотеку с множеством ящиков. Картотека — такой же предмет, как и ящик (в нашем случае и то, и другое — значения), но картотека сама по себе содержит внутри множество значений. Каждое из этих значений (ящиков) имеет свой номер, и получить содержимое ящика можно зная этот номер. 


И, конечно, к картотеке можно добавлять ящики, убирать их, переставлять местами... Массив позволяет делать то же самое со значениями, которые находятся у него внутри. А ведь внутри ящика может быть еще одна, маленькая картотека (внутри которой еще парочка картотек поменьше). Массивы тоже могут содержать внутри себя массивы, а те — еще одни массивы, и так почти до бесконечности (точнее, до тех пор, пока браузер сможет разбираться со всеми этими массивами). 


Объекты очень похожи на массивы, с одним отличием — вместо номеров на «ящиках» используются названия. И, соответственно, объекты пишутся немного по-другому, например, так: {'a':1, 'b':2}


Каждое значение, которое входит в объект, называют свойством (то есть у объекта из примера будут два свойства с именами «a» и «b», и значениями 1 и 2). 


У массивов же номера значений, которые в него входят, называются индексами, а сами значения — элементами. 


Когда я говорю «пишутся», я имею ввиду способ, которым различные значения записываются в тексте скрипта. Тот текст, которым записывается значение, называется литералом. 


Не нужно путать значение и литерал. Так, строка true (без кавычек) — это литерал, а логическое значение «Истина» — это и есть значение данного литерала.


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


Эти способы я уже показывал — для записи чисел могут использоваться цифры, десятичная точка и показатель экспоненты (то есть число 1000000 можно записать как 1.0e6). Кроме этого, можно использовать не десятичную, а, например, шестнадцатеричную запись — тогда число 12, к примеру, будет записано как 0x0C


Логические значения записываются строчками true и false, без кавычек.


Текст внутри кавычек образует строковый литерал — то есть считается значением типа «строка». 


Массивы записываются с использованием квадратных скобок, а объекты — фигурных. 


Теперь вы понимаете, почему строка "Здесь был JavaScript", которую выводил alert, была записана в кавычках, а число — без них.


Переменная в JavaScript

Само по себе значение, конечно, вещь полезная, но в реальном мире значение само по себе редко существует. Чаще всего оно где-то записано. 


Возьмем, к примеру, обычную записную книжку. В ней множество страниц, и на каждой что-то записано. Записи на каждой странице можно изменять — например, попросить записную книжку у друга и переписать телефонный номер девушки, с которой вы вчера познакомились, или вычеркнуть из своей книжки номер этой девушки (после того как познакомились с ее парнем).  


Или, к примеру, школьная доска — на ней можно писать что угодно, стирать, переписывать на нее текст из учебника, а потом с нее — в тетрадь.  


Для того, чтобы хранить значения, а также обмениваться ими, в языке JavaScript есть переменные.


Суть переменной проста — это такая сущность, которая может содержать какое-либо значение. Самое главное, что значение можно туда заносить и просматривать, какое значение там находится. 


Для того чтобы использовать переменную, нужно написать ее имя. Имя переменной в JavaScript может состоять из букв (латинских), цифр, знака подчеркивания и знака доллара (при этом цифра не может быть первым символом).


Например, такие строки, как qwerty, $_, a1b2c3$$ могут быть именами переменных в JS, а 123a — нет. При этом нужно учитывать, что регистр знаков важен — то есть


abcd и aBcD будут разными переменными.


Последние версии JavaScript позволяют использовать любые национальные символы (русский, шведский, тибетский и так далее алфавиты), но для этого они должны быть записаны в Unicode.


Перед тем как переменную использовать, ее нужно объявить (то есть сказать браузеру, что такая переменная будет использоваться). 


Делается это при помощи специального слова var:


	var x, y, z = 3; 

В этом примере мы объявили три переменные — x, у и z, причем переменная z сразу получила значение 3.


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


Использование же необъявленной переменной может вызвать сообщение об ошибке. 


Существуют и переменные, которые объявлять не нужно — это так называемые предопределенные переменные (о которых браузер знает с момента запуска). Любой браузер знает о таких переменных, как window, document, location, navigator и множестве других.


Бывает и так, что переменная уже объявлена, но в нее ничего не занесли? В том примере объявления переменных, который я показал, значение занесено только в переменную z. А что находится в x и y?


Правильно, значение переменной не определено. Именно для этого и служит «очень специальный» тип undefined. Все не определенные переменные имеют этот тип и содержат это значение.


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


  1. Можно ли создать массив объектов? А объект, содержащий массивы? 


  2. Какого типа будет литерал 12, если записать его в кавычках?


  3. Работа с каким типом не была описана в этой главе? Как вы думаете, почему? 


Операции - арифметические, логические

Переменные обычно как-то взаимодействуют друг с другом. Можно взять значение одной переменной, прибавить ее к значению другой, а потом проверить, что получилось. Такие действия называются операциями, а конструкции языка, которыми операции записываются — операторами.  


Самая простая, и самая главная операция — присваивание. В Javascript эта операция записывается оператором «=». Например,


	var a, b; 
	a = 1; 
	b = a; 

Здесь мы объявили две переменные, после этого занесли в переменную a значение 1, а после этого занесли в переменную b то же, что находилось на этот момент в a.


Нужно заметить, что значение из переменной a никуда не исчезло.


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


Язык JavaScript позволяет выполнять множество операций. Привычные всем сложение, вычитание, умножение, и немного непривычный остаток от деления (или деление по модулю), а также логические — AND, OR, NOT, операции сдвигов, сравнения... Все эти операции можно свести в небольшую табличку:


. [] ()
++ -- - ~ ! delete new typeof void
* / %
+ -
<< >> >>>
< <= > >= instanceof
== != === !==
&
^
|
&&
||
?:
= += -= *= /= %= <<= >>= >>>= &= ^= |=
,

В этой таблице представлены все операторы для всех операций, которые может выполнять JavaScript, причем те операции, которые в таблице находятся выше, будут выполняться раньше.


Все операции делятся на несколько групп: 


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


Каждая операция получает один, два или три операнда (это могут быть как литералы, так и переменные), а в результате своего действия отдает значение. Так, операция 1+2 отдаст значение 3, которое может быть записано в переменную:


	a = 1 + 2;

(теперь в a находится значение 3).


При желании, результат операции можно никуда не записывать — например,  


	2 + 3;

(результат операции — число «5», но этот результат нигде не сохранен). 


Операция присваивания не является исключением, и тоже возвращает значение. 


Например, можно записать: 


	a = 1;  
	d = 1 + c = 2 + b = 3 + a;

Эта странная, на первый взгляд, запись, тем не менее нормально выполняется. 


Но, для сохранения вашего спокойствия (не очень-то легко читать такой код) я бы советовал воздержаться от подобной записи. Вместо нее лучше писать 


	a = 1; 
	b = 3 + a; 
	c = 2 + b; 
	d = 1 + c; 

Просто и понятно. 


Иногда бывает так, что операция применяется к двум значениям, или иначе — операндам разного типа. Например, кто-нибудь может попытаться написать  


	var a = "13" - 1;

В таком случае JavaScript делает то, что называется «приведением типов», если, конечно, это возможно. То есть, у операндов (обычно одного) меняется тип, при возможности — сохраняя значение, и после замены типа выполняется операция над двумя операндами теперь уже одного типа.


Подобные приведения очень часто ставят в тупик начинающих программистов — потому что поведение скрипта становится непонятным. 


Вот, к примеру, две инструкции: 


  1. var a = "13" - 1; 


  2. var a = "13" + 1; 


Первая инструкция занесет в переменную a число «12», а вторая — строку «131» 


Это происходит потому что для строк (а первый операнд — строка) нет операции вычитания. Поэтому при вычитании строка преобразуется в число, и результат будет  результатом вычитания числа из числа.


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


Есть еще один интересный пример —  


	var a = true + false; 

Хотя в этом примере оба операнда — логические, но для них операции сложения не существуют. Поэтому оба операнда преобразуются в числа, и после этого складываются, поэтому результатом будет единица (так как true преобразуется к единице, а false — к нулю).


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


Инструкции

Любая программа, и программа на Javascript — не исключение, состоит из списка команд, которые выполняются друг за другом. Обычно это операции над переменными и вызовы функций. Но чаще всего последовательное выполнение каждой команды — не совсем то, что требуется от программы. Одно из полезнейших свойств программ — способность выполнять различные действия в зависимости от состояния переменных.


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


Для того чтобы программа работала по-разному в разных условиях, существуют инструкции. 


Самые употребляемые инструкции — это инструкции циклов и условные инструкции. 


Первые позволяют выполнять какое-либо действие до тех пор, пока некоторое условие верно (то есть, равно true). Вторые позволяют, в зависимости от условия, выполнять различные части кода.


Также имеются инструкции для работы с объектами (например, обхода всех элементов объекта), инструкции для исключений и блочная инструкция. 


Для начала, рассмотрим блочную инструкцию, или блок. 


Она записывается при помощи двух фигурных скобок: { } (не стоит путать эту запись с литералом объекта).


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


Для циклических действий в языке JavaScript существуют, во-первых, операторы циклов — это операции for, while и do .. while.


Оператор for записывается таким образом: 


for (выражение инициализации; условие; выражение итерации) тело цикла; 


Выражение инициализации — это выражение, которое вычисляется перед началом выполнения тела цикла (вы помните, что операция присвоения тоже вычисляется).  


Обычно в этом месте объявляется переменная-счетчик.  


Условие — логическое выражение. Цикл выполняется до тех пор, пока это условие истинно. 


Выражение итерации вычисляется каждый раз после очередного выполнения тела цикла. 


Тело цикла — одна (и только одна) инструкция. Для того чтобы в теле цикла можно было использовать несколько инструкций, и используется блок.  


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


Например, объявим цикл, который выполняется 30 раз: 


	for (var i = 0; i < 30; i++) {} 

Перед стартом цикла мы объявляем переменную i и присваиваем ей ноль.


Перед каждой итерацией проверяем условие — i должно быть меньше тридцати.


И после каждой итерации увеличиваем значение i на единицу.


Таким образом, переменная i последовательно принимает значения от 0 до 29 (как только в переменной i будет число 30, выполнение цикла прекратится).


В случае, если условия или выражения не нужны, их можно не записывать. 


Например,  


	for (;;){} 

Этот цикл будет выполняться «вечно» (то есть до тех пор, пока не произойдет внешнее событие, которое принудительно остановит цикл — например, пользователь закроет браузер). 


Инструкция while в некотором роде может рассматриваться как упрощенный цикл. Эта инструкция имеет только параметр условия.


То есть, инструкция  


	while (someExpression) {} 

полностью аналогична 


	for (; someExpression;) {} 

Оба этих цикла называются циклами с предусловием — то есть условие проверяется до того, как выполняется тело цикла. Если условие ложно до первого выполнения цикла, тело цикла никогда не выполнится 


	for (; false; ) { 
		alert ('Это сообщение никогда не выводится');
	} 
	alert ('A это — выведется'); 

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


Например, 


	do { 
		alert ('Всего один раз!');
	} while (false); 

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


Записывается она в виде 


	for (variable in object) инструкция; 

Например,  


	var a = {'a':10, 'b':20, 'c':30}; 
	for (var index in a) { 
		alert ('Просматриваем индекс ' + index);
	} 

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


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


Таких выражений два — if и switch.


Выражение if записывается в виде 


	if (условие) { 
		инструкция если значение верно
	} else { 
		инструкция если значение ложно
	}

Обе инструкция (для верного и ложного значений условия) называются ветками условия. 


В некоторых случаях ветка else просто не используется, тогда оператор принимает такой вид:


	if (условие) { 
		инструкция если значение верно
	} 

Для того, чтобы проверить несколько условий, можно каскадировать (то есть поставить друг за другом) инструкции if: 


	if (выражение 1) { 
	} else if (выражение 2) { 
	} else if (выражение 3) { 
	... 
	}else if (выражение n) { 
	} 

Для случая когда нужно использовать выбор из нескольких вариантов такое каскадирование получается громоздким. Вместо него можно использовать инструкцию switch. Она записывается так:


	switch(выражение) { 
		case значение1: инструкция1;
		case значение2: инструкция2;
		default: инструкция;
	} 

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


Если же ни одно из значений не подходит, то выполняется блок после default (если он есть). Очень часто блок default не используется.


Впрочем, эта инструкция хранит в себе подводные камни. А именно — после того, как switch начнет выполнение тех инструкций, которые находятся после case с соответствующим значением, выполнение продолжится до конца инструкции switch.


Например, код  


	var a = 1, b; 
	switch (a) { 
		case 1: b = 1;
		case 2: b = 2;
		default: b = 0;
	} 
	alert(b); 

выведет окно с текстом «0». 


Для того чтобы в b содержалось правильное значение, нужно после каждого присваивания писать инструкцию break:


	var a = 1, b; 
	switch (a) {
		case 1: b = 1;
			break;
		case 2: b = 2;
			break;
		default: b = 0;
		} 
	alert(b); 

Теперь в переменной b будет именно то значение, которое мы ожидали.


Раз уж пошел разговор про инструкцию break, стоит упомянуть об инструкциях этого типа (вы уже устали читать на каждой строчке слов «инструкция»? Потерпите немного, скоро они закончатся).


Это инструкции прерывания и продолжения циклов. 


Инструкция break используется для того, чтобы завершить выполнение инструкции switch, и для прерывания циклов. Чаще всего это прерывание совершается по условию — к примеру, бесконечный цикл может завершаться при достижении переменной определенного значения (теперь вы понимаете, зачем могут понадобиться бесконечные циклы).


Например, 


	var a = 2; 
	while (true) { 
		a+=32;
		a %= 123;
		if (a == 0) {
			break;
		}
	} 

В этом случае мы не знаем точно, сколько раз нужно выполниться циклу, но у нас есть четкое условие. Именно при достижении этого условия цикл завершится. 


Инструкция continue похожа на break с той разницей, что break завершает выполнение цикла (причем все что находится в теле цикла ниже инструкции break не выполняется), а continue просто начинает новую итерацию цикла — как бы пропускает все операции идущие ниже, как будто их нет.


Есть еще одна инструкция — это так называемая пустая инструкция. 


Записывается она в виде обычной точки с запятой — «;». Такая инструкция используется там, где ничего выполнять не нужно.


Кроме того, этим же символом одна инструкция (или выражение) отделяется от другого. Например, можно писать 


	var a = 1 
	a = a + 1 
	a = a + 2 

А можно писать  


	var a = 1; a = a + 1; a = a + 2; 

То есть команды разделяются или переводом строки, или точкой с запятой. 


Чаще всего используются оба метода одновременно: 


	var a = 1; 
	a = a + 1; 
	a = a + 2; 

Остальные операции и некоторые дополнительные способы использования уже описанных инструкций я буду пояснять в следующих главах, по мере применения (тем более что самые пытливые читатели уже посмотрели в справочнике), а сейчас можно отвлечься от теории и заняться практическим применением всего того, о чем вы все это время читали (и отдохнуть от слова «инструкция»). 


Вы ездите в трамваях? А в троллейбусах? Даже если нет, вы все равно знаете, что такое счастливые билетики. Это те билеты, у которых сумма первых трех цифр в номере равна сумме последних трех. 


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


Это можно проверить при помощи небольшой программы на JavaScript, и именно тут вам пригодятся все те сведения, которые вы уже усвоили.


Итак, ставим цель: Проверить все числа от 000000 до 999999 на «счастливость», то есть — чтобы сумма первых трех цифр совпадала с суммой последних трех. 


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


	var ticketsCount = 0; 
	for (var d1 = 0; d1 < 10; d1++) { 
		for (var d2 = 0; d2 < 10; d2++) {
			for (var d3 = 0; d3 < 10; d3++) {
				for (var d4 = 0; d4 < 10; d4++) {
					for (var d5 = 0; d5 < 10; d5++) {
						for (var d6 = 0; d6 < 10; d6++) {
							if ( (d1+d2+d3) == (d4+d5+d6)) {
								ticketsCount++;
							}
						}
					}
				}
			}
		}
	} 
	alert (ticketsCount); 

Сразу предупреждаю — этот скрипт будет работать долго (браузер даже может предупредить об этом и предложить завершить работу скрипта — не соглашайтесь, а то так и не узнаете, сколько же счастливых билетов существует). 


Увидели? 


А теперь, ситуация: вы взяли билетик, а на нем сумма первых трех цифр отличается от суммы последних трех всего на единицу... Не расстраивайтесь — это к деньгам. 


Итак, вот вам задачи, которые нужно сделать самостоятельно (чур, аналитически не считать!): 


  1. Посчитайте, сколько всего бывает «денежных» билетиков в одной партии 


  2. Кроме счастливых, есть еще «самые счастливые» билетики — у которых равна не сумма цифр, а сами цифры. Сколько таких билетиков?  


  3. Посчитайте число билетов, счастливых «по-московски» (а москвичи пусть считают билеты, счастливые «по-питерски») — то есть такие, у которых сумма цифр, стоящих на четных местах, равна сумме цифр, стоящих на нечетных. Скажите «Я так и думал». 




В начало страницы



В начало страницы