Язык c — Помогите с языком С.


Содержание

Записная книжка программиста-новичка, C#, SQL, PHP и все-все-все

Я ведь это уже делал, но хрен теперь найдешь тот кусок кода, гуглим снова… Где бы найти простое и понятное руководство для начинающего, а не тонкости для мега-гуру?

Рубрики

Свежие записи

Свежие комментарии

  • Calator prin Romania к записи Как переименовать проект/каталог проекта в Visual Studio?
  • iukovl к записи Как изменить максимальный размер загружаемого файла в php
  • sdfdsgeg к записи Работа с файлом конфигурации (configuration) в C# — читаем и сохраняем
  • iukovl к записи Как изменить максимальный размер загружаемого файла в php
  • Надежда к записи Ошибка в коде привела к убыткам в 476 миллионов долларов и банкротству компании

Архивы

Самоучитель по C# для начинающих. 01. Основы языка, переменные, логика, циклы.

1.1 Начальные понятия

Данный самоучитель рассчитан на людей, совершенно не знакомых с программированием, но способных скачать, установить и запустить программу — в данном случае Visual Studio 2010 (2008,2012). В первой части я кратко расскажу о основах языка C#. Формат самоучителя подразумевает краткое и упрощенное изложение — за подробностями касательно отдельных функций и классов обращайтесь в гугл и msdn, за продвинутыми методиками программирования в продвинутые книги. В принципе почти всю информацию можно найти в интернете, надо лишь знать что искать, так что в отличие от классических книг на несколько сотен страниц я буду давать ту основу, зная которую вы уже сможете сформулировать поисковый запрос — ни в одном разделе я сознательно не даю полной и исчерпывающей информации, ее место в документации. Крайне желательно знать английский язык хотя бы на уровне чтения со словарем — в англоязычном интернете информации на порядок больше, невероятно полезные сайты вроде StackOverflow не имеют русских аналогов, а русскоязычные форумы и обсуждения чаще всего напоминают знаменитый анекдот (под американским форумом можно смело понимать англоязычный с немцами, индусами и бразильцами):

Чем отличаются русский, американский и еврейский форумы?
— на американском форуме вы задаете вопрос и вам дают ответ
— на еврейском форуме вы задаете вопрос и вам задают встречный вопрос
— на русском форуме вы задаете вопрос и вам долго объясняют почему вы такой мудак.

Современные языки программирования вообще и C# в частности скрывают многие низкоуровневые особенности работы компьютеров, так что детально разбираться в особенностях работы регистров процессора и тому подобной зауми новичку не надо (99% программистов тоже). Но некоторые вещи стоит держать в уме.

Что такое язык программирования? Это язык, который понимает компьютер. (ваш Капитан Очевидность) Но на самом деле компьютер понимает только нули и единицы. Так что любой современный язык программирования на самом деле промежуточен — после того как вы напишете программу, он переводится на настоящий язык компьютера — компилируется. Таким образом сначала мы пишем программу на языке программирования в обычном текстовом файле, потом компиллируем в двоичный язык компьютера.

С# в этом плане еще сложней — сначала ваша программа на C# переводится в специальный промежуточный язык — байт-код, после чего уже этот промежуточный язык переводится в двоичный код. Промежуточный язык рассчитан на специальный набор промежуточных программ, которые надо установить на компьютер перед запуском программы на C# — .Net Framework.

Схема работы .Net и C#

Таким образом мы:

1. Пишем код на языке C# в обычный текстовый файл

2. Компилируем программу в байт-код с помощью компилятора C# (1 и 2 можно делать без Visual Studio, например набрать исходный текст в Блокноте и скомпилировать через командную строку)

3. Запускаем полученную программу на компьютере, где уже установлен .Net Framework соответствующей версии), который переводит программу в двоичный код и собственно запускает, давая доступ к компьютеру. (соответственно на компьютере без Net Framework программа не запустится вообще).

1.2 Привет мир

Перейдем к практике, для создания самой простой программы мы запустим Visual Studio и выполним следующее:

1. Пойдем в меню File-New Project (Файл — Новый проект) или сразу кликнем на Create New Project

2. Выберем шаблон Console Application (Консольное приложение)

3. Выберем каталог на диске, где будет расположен наш проект

4. Добавим две строчки в текст программы, чтобы он выглядел вот так

4. Нажмем F5 (можно выбрать в меню Debug — Start Debugging ) и увидим черное окошко с нашим Привет мир, которое закроется после нажатия Enter.

Что это и зачем оно надо? В теории это программа без кнопок и меню, которой можно управлять через командную строку. В наше время такие программы используются редко, в основном очень продвинутыми сисадминами или в мире Linux (что в принципе одно и то же), но знать об их существовании полезно — программисту может довестись с такой работать или даже писать. Нам она нужна по одной-единственной причине — такая программа меньше всего будет отвлекать от изучения универсальных особенностей языка C#.

В самом простом случае (это про нас) компьютер последовательно выполняет команды программиста — одну за другой:

System.Console.WriteLine(«Привет мир!»); — выводит в консоль (то самое черное окно) строку «Привет мир»»

System.Console.ReadLine(); — читает строку, которую мы вводим (ввод завершается нажатием Enter) и переходит к следующей команде.

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

1.3 Простые переменные

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

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

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

— int, целое число от -2,147,483,648 до 2,147,483,647
— string, строка
— double, число с дробной частью и переменным количеством знаков после запятой, например 1.38 принимает значения от -1,79769313486232 в 308 степени до 1,79769313486232 в 308 степени. Проще говоря очень большие.
— decimal, число с дробной частью и повышенной точностью рассчетов, специально для финансовых операций — в миллионных и более мелких долях float могут накапливаться мелкие ошибки, банки это не любят
— bool — специальный тип для передачи данных об истинности или ложности, принимает только два значения — true или false. В старых языках вместо него использовали int с значениями 1 и 0, но это было менее наглядно и приводило к ошибкам.

Как уже говорилось выше очень часто программы обрабатывают данные о людях. Попробуем это сделать и мы.

Не забудьте запустить по F5 и посмотреть результаты.

Здесь мы объявляем две переменные-строки, оставляем их пока пустыми, объявляем набор переменных с данными о людях, склеиваем из них одну большую строку и заносим в первую переменную-строку, заносим в тот же самый набор переменных другие данные, склеиваем все вместе и заносим в другую строку и только после этого выводим две финальные строки на экран.

Стоит обратить внимание на склеивание нескольких строк в одну с помощью +. Больше информации можно найти здесь, подробное описание всевозможных издевательств над строками — здесь.

1.4 Арифметические операции

Компьютеры почти всегда что-то считают. Собственно само слово computer означает вычислитель. В этой области даже самый слабенький процессор намного превосходит человеческий мозг.

Почему произошло столь странное недоразумение с дробным числом во второй раз? Все дело в том, что внутри одной строки мы выполнили сразу несколько операций. А в каком порядке они выполняются? В порядке приоритета. И у оператора присваивания =, который записывает данные в переменную, этот приоритет один из самых низких

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

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

1.5 Управление и логика

На данный момент наша программа не отличается умом — Скайнет из нее не получится, уничтожение человечеству не грозит. Мы просто выполняем команды по очереди, одну за другой, а хотелось бы принимать решения в зависимости от внешних условий — например «если есть возможность, уничтожить всех людей, иначе работать над созданием такой возможности». Делается это с с помощью специальной конструкции если-иначе, или, на родном для C# английском if-else и специальных операторов сравнения:

  • — величина слева больше
  • = — меньше либо равно и больше либо равно
  • == — просто равно, обратите внимание, что равенство очень похоже на оператор присваивания, который записывает значение в переменную = — не путайте их, равенство — это двойное «равно»
  • != — не равно
  • и другие

Компьютерная логика проста — высказывание или результат сравнения может быть либо истиной либо ложью, либо true либо flase, либо уничтожать человечество либо нет. Третьего компьютеру не дано. Для хранения таких данных существует специальный тип данных — логический — bool — который может принимать только два значения (догадываетесь какие?). Если вы хотите чего-то посложней и похардкорней — то все вместе это булева алгебра, изучайте и просвещайтесь.

Нам важно понять, что любая операция сравнения, на пример 2

Язык c — Помогите с языком С.

Язык Си, созданный Денисом Ритчи в начале 70-х годов в Bell Laboratory американской корпорации AT&T, является одним из универсальных языков программирования. Язык Си считается языком системного программирования, хотя он удобен и для написания прикладных программ. Среди преимуществ языка Си следует отметить переносимость программ на компьютеры различной архитектуры и из одной операционной системы в другую, лаконичность записи алгоритмов, логическую стройность программ, а также возможность получить программный код, сравнимый по скорости выполнения с программами, написанными на языке ассемблера. Последнее связано с тем, что хотя Си является языком высокого уровня, имеющим полный набор конструкций структурного программирования, он также обладает набором низкоуровневых средств, обеспечивающих доступ к аппаратным средствам компьютера. С 1989 года язык Си регламентируется стандартом Американского института национальных стандартов ANSI С. В настоящее время, кроме стандарта ANSI C разработан международный стандарт ISO C (International Standard Organization C).

В пособии в разделах 1-6 рассматриваются основные конструкции языка Си (общие для Си и Си++). Примеры программ приведены в разделе 7.

РАЗДЕЛ 1. ОСНОВНЫЕ ПОНЯТИЯ И ДАННЫЕ

Основные понятия языка

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

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

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

Различают видимые и управляющие символы. Первые могут быть отображены на экране дисплея либо отпечатаны на принтере. Вторые вызывают определенные действия в машине, например: звуковой сигнал — код 710, возврат курсора на один шаг — код 810, горизонтальная табуляция — код 910, перевод курсора на новую строку — код 1010, перемещение курсора в начало строки — код 1310 и т.д. Такие управляющие символы имеют десятичные номера 0 — 31, 127.

Для представления каждого символа в персональном компьютере используется один байт, поэтому общее число символов равно 2 8 = 256. Кодовая таблица, которая устанавливает соответствие между символом и его кодом, имеет 256 строк вида:

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

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

  1. Они должны начинаться с буквы латинского алфавита (а. z, А. Z) или с символа подчеркивания (_).
  2. В них могут использоваться буквы латинского алфавита, символ подчеркивания и цифры (0. 9). Использование других символов в идентификаторах запрещено.
  3. В языке Си буквы нижнего регистра (а. z), применяемые в идентификаторах, отличаются от букв верхнего регистра (А. Z). Это означает, что следующие идентификаторы считаются разными: name, NaMe, NAME и т.д.
  4. Идентификаторы могут иметь любую длину, но воспринимается и используется для различения объектов (функций, переменных, констант и т.д.) только часть символов. Их число меняется для разных систем программирования, но в соответствии со стандартом ANSI C не превышает 32 (в Си++ это ограничение снято). Если длина идентификатора установлена равной 5, то имена count и counter будут идентичны, поскольку у них совпадают первые пять символов.
  5. Идентификаторы для новых объектов не должны совпадать с ключевыми словами языка и именами стандартных функций из библиотеки.

В программах на языке Си важная роль отводится комментариям. Они повышают наглядность и удобство чтения программ. Комментарии обрамляются символами /* и */. Их можно записывать в любом месте программы.

В языке Си++ введена еще одна форма записи комментариев. Все, что находится после знака // до конца текущей строки, будет также рассматриваться как комментарий. Отметим, что компилятор языка Си, встроенный в систему программирования Borland C++, позволяет использовать данный комментарий и в программах на Си.

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

Типы данных

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

В языке различают понятия «тип данных» и «модификатор типа». Тип данных — это, например, целый, а модификатор — со знаком или без знака. Целое со знаком будет иметь как положительные, так и отрицательные значения, а целое без знака — только положительные значения. В языке Си можно выделить пять базовых типов, которые задаются следующими ключевыми словами:

  • char — символьный;
  • int — целый;
  • float — вещественный;
  • double — вещественный двойной точности;
  • void — не имеющий значения.

Дадим им краткую характеристику:

  1. Переменная типа char имеет размер 1 байт, ее значениями являются различные символы из кодовой таблицы, например: ‘ф’, ‘:’, ‘j’ (при записи в программе они заключаются в одинарные кавычки).
  2. Размер переменной типа int в стандарте языка Си не определен. В большинстве систем программирования размер переменной типа int соответствует размеру целого машинного слова. Например, в компиляторах для 16-разрядных процессоров переменная типа int имеет размер 2 байта. В этом случае знаковые значения этой переменной могут лежать в диапазоне от -32768 до 32767.
  3. Ключевое слово float позволяет определить переменные вещественного типа. Их значения имеют дробную часть, отделяемую точкой, например: -5.6, 31.28 и т.п. Вещественные числа могут быть записаны также в форме с плавающей точкой, например: -1.09e+4. Число перед символом «е» называется мантиссой, а после «е» — порядком. Переменная типа float занимает в памяти 32 бита. Она может принимать значения в диапазоне от 3.4е-38 до 3.4e+38.
  4. Ключевое слово double позволяет определить вещественную переменную двойной точности. Она занимает в памяти в два раза больше места, чем переменная типа float (т.е. ее размер 64 бита). Переменная типа double может принимать значения в диапазоне от 1.7e-308 до 1.7e+308.
  5. Ключевое слово vo >Объект некоторого базового типа может быть модифицирован. С этой целью используются специальные ключевые слова, называемые модификаторами. В стандарте ANSI языка Си имеются следующие модификаторы типа:

Модификаторы записываются перед спецификаторами типа, например: unsigned char. Если после модификатора опущен спецификатор, то компилятор предполагает, что этим спецификатором является int. Таким образом, следующие строки:

являются идентичными и определяют объект а как длинный целый. Табл. 1 иллюстрирует возможные сочетания модификаторов (unsigned, signed, short, long) со спецификаторами (char, int, float и double), а также показывает размер и диапазон значений объекта (для 16-разрядных компиляторов).

Тип Размер в байтах (битах) Интервал изменения
char 1 (8) от -128 до 127
unsigned char 1 (8) от 0 до 255
signed char 1 (8) от -128 до 127
int 2 (16) от -32768 до 32767
unsigned int 2 (16) от 0 до 65535
signed int 2 (16) от -32768 до 32767
short int 2 (16) от -32768 до 32767
unsigned short int 2 (16) от 0 до 65535
signed short int 2 (16) от -32768 до 32767
long int 4 (32) от -2147483648 до 2147483647
unsigned long int 4 (32) от 0 до 4294967295
signed long int 4 (32) от -2147483648 до 2147483647
float 4 (32) от 3.4Е-38 до 3.4Е+38
double 8 (64) от 1.7Е-308 до 1.7Е+308
long double 10 (80) от 3.4Е-4932 до 3.4Е+4932

Переменные и константы

Все переменные до их использования должны быть определены (объявлены). При этом задается тип, а затем идет список из одной или более переменных этого типа, разделенных запятыми. Например:

В языке различают понятия объявления переменной и ее определения. Объявление устанавливает свойства объекта: его тип (например, целый), размер (например, 4 байта) и т.д. Определение наряду с этим вызывает выделение памяти (в приведенном примере дано определение переменных).

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

Переменные в языке Си могут быть инициализированы при их определении:

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

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

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

Наряду с переменными в языке существуют следующие виды констант:

  • вещественные, например 123.456, 5.61е-4. Они могут снабжаться суффиксом F (или f), например 123.456F, 5.61e-4f;
  • целые, например 125;
  • короткие целые, в конце записи которых добавляется буква (суффикс) H (или h), например 275h, 344H;
  • длинные целые, в конце записи которых добавляется буква (суффикс) L (или l), например 361327L;
  • беззнаковые, в конце записи которых добавляется буква U (или u), например 62125U;
  • восьмеричные, в которых перед первой значащей цифрой записывается нуль (0), например 071;
  • шестнадцатеричные, в которых перед первой значащей цифрой записывается пара символов нуль-икс (0x), например 0x5F;
  • символьные — единственный символ, заключенный в одинарные кавычки, например ‘О’, ‘2’, ‘.’ и т.п. Символы, не имеющие графического представления, можно записывать, используя специальные комбинации, например \n (код 10), \0 (код 0). Эти комбинации выглядят как два символа, хотя фактически это один символ. Так же можно представить любой двоичный образ одного байта: ‘\NNN’, где NNN — от одной до трех восьмеричных цифр. Допускается и шестнадцатеричное задание кодов символов, которое представляется в виде: ‘\х2В’, ‘\хЗ6’ и т.п.;
  • строковые — последовательность из нуля символов и более, заключенная в двойные кавычки, например: «Это строковая константа». Кавычки не входят в строку, а лишь ограничивают ее. Строка представляет собой массив из перечисленных элементов, в конце которого помещается байт с символом ‘\0’. Таким образом, число байтов, необходимых для хранения строки, на единицу превышает число символов между двойными кавычками;
  • константное выражение, состоящее из одних констант, которое вычисляется во время трансляции (например: а=60+301);
  • типа long double, в конце записи которых добавляется буква L (или l), например: 1234567.89L.

Как вводить и выводить информацию

Операции ввода/вывода в языке Си организованы посредством библиотечных функций (причем их довольно много).

Самый простой механизм ввода — чтение по одному символу из стандартного входного потока (с клавиатуры) с помощью функции getchar( ). Она имеет следующий прототип (т.е. описание заголовка):

Здесь определен тип единственного аргумента (vo >Оператор вида:

присваивает переменной х очередной вводимый символ. Переменная х должна иметь символьный или целый тип.

Другая функция — putchar(х) выдает значение переменной x в стандартный выходной поток (на экран дисплея). Функция putchar( ) имеет прототип:

Объявления getchar( ) и putchar( ) сделаны в заголовочном файле stdio.h, содержащем описания заголовков библиотечных функций стандартного ввода/вывода. Чтобы библиотечные функции стали доступны программе, к ней необходимо подключить данный файл. Подключение осуществляется с помощью директивы препроцессора

помещаемой в начало программы (подробнее см. в разделе 5).

Заметим, что для функции getchar( ) после выбора символа необходимо нажать клавишу . Иногда это создает определенные неудобства. Функции getch( ) и getche( ) устраняют их. Они имеют следующие прототипы:

Обе эти функции вводят символ сразу же после нажатия соответствующей клавиши (здесь не надо дополнительно нажимать клавишу ). Отличие между ними заключается в том, что getche( ) отображает вводимый символ на экране дисплея, а getch( ) — нет. Прототипы этих функций содержатся в файле conio.h (консольный ввод/вывод). Для их использования файл conio.h также следует подключить к программе с помощью директивы #include .

Форматированный вывод данных

Функция printf( ) (прототип содержится в файле stdio.h) обеспечивает форматированный вывод. Ее можно записать в следующем формальном виде:

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

Каждая спецификация преобразования начинается со знака % и заканчивается некоторым символом, задающим преобразование. Между знаком % и символом преобразования могут встречаться другие знаки в соответствии со следующим форматом:

Все параметры в квадратных скобках не являются обязательными.

На месте параметра c_n (символ преобразования) могут быть записаны:

    с — значением аргумента является символ;
    d или i — значением аргумента является десятичное целое число;
    е — значением аргумента является вещественное десятичное число в экспоненциальной форме вида 1.23e+2;
    Е — значением аргумента является вещественное десятичное число в экспоненциальной форме вида 1.23E+2;
    f — значением аргумента является вещественное десятичное число с плавающей точкой;
    g (или G) — используется, как е или f, и исключает вывод незначащих нулей;
    о — значением аргумента является восьмеричное целое число;
    s — значением аргумента является строка символов (символы строки выводятся до тех пор, пока не встретится символ конца строки или же не будет, выведено число символов, заданное точностью);
    u — значением аргумента является беззнаковое целое число;
    х — значением аргумента является шестнадцатеричное целое число с цифрами 0. 9, а, b, с, d, е, f;
    X — значением аргумента является шестнадцатеричное целое число с цифрами 0. 9, А, В, С, О, Е, F;
    р — значением аргумента является указатель;
    n — применяется в операциях форматирования. Аргумент, соответствующий этому символу спецификации, должен быть указателем на целое. В него возвращается номер позиции строки (отображаемой на экране), в которой записана спецификация %n.

Необязательные параметры в спецификации преобразования:

  • признак минус (-) указывает, что преобразованный параметр должен быть выровнен влево в своем поле;
  • признак плюс (+) требует вывода результата со знаком;
  • строка цифр, задающая минимальный размер поля (ширина поля). Здесь может так же использоваться символ *, который тоже позволяет задать минимальную ширину поля и точность представления выводимого числа;
  • точка (.), отделяющая размер поля от последующей строки цифр;
  • строка цифр, задающая максимальное число выводимых символов, или же количество цифр, выводимых справа от десятичной точки в значениях типов float или double (точность);
  • символ F, определяющий указатель типа far;
  • символ N, определяющий указатель типа near;
  • символ h, определяющий аргумент типа short int (используется вместе с символами преобразования d, i, о, u, х, Х);
  • символ l, указывающий, что соответствующий аргумент имеет тип long (в случае символов преобразования d, i, о, u, х, X) или double (в случае символов преобразования е, Е, f, g, G);
  • символ L, указывающий, что соответствующий аргумент имеет тип long double (используется вместе с символами преобразований е, Е, f, g, G);
  • символ #, который может встречаться перед символами преобразования g, f, е и перед символом х. В первом случае всегда будет выводиться десятичная точка, а во втором — префикс 0x перед соответствующим шестнадцатеричным числом.

Если после знака % записан не символ преобразования, то он выводится на экран. Таким образом, строка %% приводит к выводу на экран знака %.

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

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

Среди управляющих символьных констант наиболее часто используются следующие:

    \а — для кратковременной подачи звукового сигнала;
    \b — для перевода курсора влево на одну позицию;
    \f — для подачи формата;
    \n — для перехода на новую строку;
    \r — для возврата каретки;
    \t — горизонтальная табуляция;
    \v — вертикальная табуляция;
    \\ — вывод символа \;
    \’ — вывод символа ‘ ;
    \» — вывод символа «;
    \? — вывод символа ?.

Например, в результате вызова функции:

сначала выполняется горизонтальная табуляция (\t), т.е. курсор сместится от края экрана, затем на экран будет выведено слово Computer, после этого курсор переместится в начало следующей строки (\n), затем будет выведено целое число i по формату %d (десятичное целое), и, окончательно, курсор перейдет в начало новой строки (\n).

Напечатать строку символов можно и так:

Форматированный ввод данных

Функция scanf( ) (прототип содержится в файле stdio.h) обеспечивает форматированный ввод. Ее можно записать в следующем формальном виде:

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

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

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

Рассмотрим символы преобразования функции scanf( ) (указываются после символа %):

    с — на входе ожидается появление одиночного символа;
    d или i — на входе ожидается десятичное целое число и аргумент является указателем на переменную типа int;
    D или l — на входе ожидается десятичное целое число и аргумент является указателем на переменную типа long;
    е или Е — на входе ожидается вещественное число с плавающей точкой;
    f — на входе ожидается вещественное число с плавающей точкой;
    g или G — на входе ожидается вещественное число с плавающей точкой;
    о — на входе ожидается восьмеричное целое число и аргумент является указателем на переменную типа int;
    О — на входе ожидается восьмеричное целое число и аргумент является указателем на переменную типа long;
    s — на входе ожидается появление строки символов;
    х — на входе ожидается шестнадцатеричное целое число и аргумент является указателем на переменную типа int;
    Х — на входе ожидается шестнадцатеричное целое число и аргумент является указателем на переменную типа long;
    р — на входе ожидается появление указателя в виде шестнадцатеричного числа;
    n — применяется в операциях форматирования. Аргумент, соответствующий этому символу спецификации, должен быть указателем на целое. В него возвращается номер позиции (после ввода), в которой записана спецификация %n;
    u — на входе ожидается беззнаковое целое число и аргумент является указателем на переменную типа unsigned int;
    U — на входе ожидается беззнаковое целое число и аргумент является указателем на переменную типа unsigned long;
    [ ] — сканирует входную строку для получения символов.

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

    F — изменяет указатель, заданный по умолчанию, на указатель типа far;
    N — изменяет указатель, заданный по умолчанию, на указатель типа near;
    h — преобразует аргумент к типу short int (может записываться перед символами d, i, о, u, х);
    l — преобразует аргумент к типу long int (может записываться перед символами d, i, o, u, x);
    L — преобразует аргумент к типу long double (может записываться перед символами е, f, g).

Ввести целое число (int a;), символ (char b;) и вещественное число (float t;) можно так:

РАЗДЕЛ 2. ОПЕРАЦИИ И ОПЕРАТОРЫ

Операции языка Си

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

Операции выполняются в строгой последовательности. Величина, определяющая преимущественное право на выполнение той или иной операции, называется приоритетом. В табл. 2 перечислены различные операции языка Си. Их приоритеты для каждой группы одинаковы (группы выделены цветом). Чем большим преимуществом пользуется соответствующая группа операций, тем выше она расположена в таблице. Порядок выполнения операций может регулироваться с помощью круглых скобок.

Знак операции Назначение операции
( ) Вызов функции
[ ] Выделение элемента массива
. Выделение элемента записи
-> Выделение элемента записи
! Логическое отрицание
Поразрядное отрицание
Изменение знака
++ Увеличение на единицу
Уменьшение на единицу
& Взятие адреса
* Обращение по адресу
(тип) Преобразование типа (т.е. (float) a)
sizeof( ) Определение размера в байтах
* Умножение
/ Деление
% Определение остатка от деления
+ Сложение
Вычитание
Сдвиг влево
>> Сдвиг вправо
Меньше, чем
Меньше или равно
> Больше, чем
>= Больше или равно
= = Равно
!= Не равно
& Поразрядное логическое «И»
^ Поразрядное исключающее «ИЛИ»
| Поразрядное логическое «ИЛИ»
&& Логическое «И»
|| Логическое «ИЛИ»
?: Условная (тернарная) операция
= Присваивание
+=, — =, *=, /=, %=, >=, &=, |=, ^= Составные операции присваивания (например, а *= b
(т.е. a = a * b) и т.д.)
, Операция запятая

Для исключения путаницы в понятиях «операция» и «оператор», отметим, что оператор — это наименьшая исполняемая единица программы. Различают операторы выражения, действие которых состоит в вычислении заданных выражений (например: a = sin(b)+c; j++;), операторы объявления, составные операторы, пустые операторы, операторы метки, цикла и т.д. Для обозначения конца оператора в языке Си используется точка с запятой. Что касается составного оператора (или блока), представляющего собой набор логически связанных операторов, помещенных между открывающей (<) и закрывающей (>) фигурными скобками («операторными скобками»), то за ним точка с запятой не ставится. Отметим, что блок отличается от составного оператора наличием определений в теле блока.

Охарактеризуем основные операции языка Си. Сначала рассмотрим одну из них — операцию присваивания (=). Выражение вида

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

Различают унарные и бинарные операции. У первых из них один операнд, а у вторых — два. Начнем их рассмотрение с операций, отнесенных к первой из следующих традиционных групп:

  1. Арифметические операции.
  2. Логические операции и операции отношения.
  3. Операции с битами.

Арифметические операции задаются следующими символами (табл. 2): +, -, *, /, %. Последнюю из них нельзя применять к переменным вещественного типа. Например:

Логические операции отношения задаются следующими символами (см. табл. 2): && («И»), || («ИЛИ»), ! («НЕ»), >, >=,

x y x&&y x||y !x
1
1 1 1
1 1
1 1 1 1

Битовые операции можно применять к переменным, имеющим типы int, char, а также их вариантам (например, long int). Их нельзя применять к переменным типов float, double, void (или более сложных типов). Эти операции задаются следующими символами:

(поразрядное отрицание), > (сдвиг вправо), & (поразрядное «И»), ^ (поразрядное исключающее «ИЛИ»), | (поразрядное «ИЛИ»).

Примеры: если a = 0000 1111 и b = 1000 1000, то

В языке предусмотрены две нетрадиционные операции инкремента (++) и декремента (—). Они предназначены для увеличения и уменьшения на единицу значения операнда. Операции ++ и — можно записывать как перед операндом, так и после него. В первом случае (++n или —n) значение операнда (n) изменяется перед его использованием в соответствующем выражении, а во втором (n++ или n—) — после его использования. Рассмотрим две следующие строки программы:

Предположим, что b = b1 = 2, c = c1 = 4. Тогда после выполнения операций: a = 6, b = 2, c = 5, a1 = 7, b1 = 2, c1 = 5.

Широкое распространение находят также выражения с еще одной нетрадиционной тернарной или условной операцией . В формуле

y = a, если x не равно нулю (т.е. истинно), и y = b, если х равно нулю (ложно). Следующее выражение

позволяет присвоить переменной у значение большей переменной (а или b), т.е. y = max(a, b).

Еще одним отличием языка является то, что выражение вида а = а + 5; можно записать в другой форме: a += 5;. Вместо знака + можно использовать и символы других бинарных операций (см. табл. 2).

Другие операции из табл. 2 будут описаны в последующих параграфах.

Преобразование типов

Если в выражении появляются операнды различных типов, то они преобразуются к некоторому общему типу, при этом к каждому арифметическому операнду применяется такая последовательность правил:

  1. Если один из операндов в выражении имеет тип long double, то остальные тоже преобразуются к типу long double.
  2. В противном случае, если один из операндов в выражении имеет тип double, то остальные тоже преобразуются к типу double.
  3. В противном случае, если один из операндов в выражении имеет тип float, то остальные тоже преобразуются к типу float.
  4. В противном случае, если один из операндов в выражении имеет тип unsigned long, то остальные тоже преобразуются к типу unsigned long.
  5. В противном случае, если один из операндов в выражении имеет тип long, то остальные тоже преобразуются к типу long.
  6. В противном случае, если один из операндов в выражении имеет тип unsigned, то остальные тоже преобразуются. к типу unsigned.
  7. В противном случае все операнды преобразуются к типу int. При этом тип char преобразуется в int со знаком; тип unsigned char в int, у которого старший байт всегда нулевой; тип signed char в int, у которого в знаковый разряд передается знак из сhar; тип short в int (знаковый или беззнаковый).

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

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

(здесь можно указать любой допустимый в языке Си тип).

(переменная a целого типа явно преобразована к типу float; если этого не сделать, то результат будет потерян, т.к. a * 12 > 32767).

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

Указатели и операции с ними

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

Унарная операция & дает адрес объекта, поэтому оператор

присваивает адрес переменной х переменной у. Операцию & нельзя применять к константам и выражениям; конструкции вида &(х+7) или &28 недопустимы.

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

присваивает z значение переменной, записанной по адресу у. Если

Объекты, состоящие из знака * и адреса (например, *а), необходимо определить. Делается это, например, так:

Определение вида char *d говорит о том, что значение, записанное по адресу d, имеет тип char.

Указатели могут встречаться и в выражениях. Если у — указатель на целое, т.е. имело место объявление int *у, то *у может появиться там же, где и любая другая переменная, не являющаяся указателем. Таким образом, следующие выражения вполне допустимы:

Первое из них заносит число 7 в ячейку памяти по адресу у, второе увеличивает значение по адресу х в пять раз, третье добавляет единицу к содержимому ячейки памяти с адресом z. В последнем случае круглые скобки необходимы, так как операции с одинаковым приоритетом выполняются справа налево. В результате если, например, *z = 5, то (*z)++ приведет к тому, что *z = 6, а *z++ всего лишь изменит сам адрес z (операция ++ выполняется над адресом z, а не над значением *z по этому адресу).

Указатели можно использовать как операнды в арифметических операциях. Если у — указатель, то унарная операция y++ увеличивает его значение; теперь оно является адресом следующего элемента. Указатели и целые числа можно складывать. Конструкция у + n (у — указатель, n — целое число) задает адрес n-гo объекта, на который указывает у. Это справедливо для любых объектов (int, char, float и др.); транслятор будет масштабировать приращение адреса в соответствии с типом, указанным в определении объекта.

Любой адрес можно проверить на равенство (==) или неравенство (!=) со специальным значением NULL, которое позволяет определить ничего не адресующий указатель.

Операторы цикла

Циклы организуются, чтобы выполнить некоторый оператор или группу операторов определенное число раз. В языке Си три оператора цикла: for, while и do — while. Первый из них формально записывается, в следующем виде:

Тело цикла составляет либо один оператор, либо несколько операторов, заключенных в фигурные скобки < . >(после блока точка с запятой не ставится). В выражениях 1, 2, 3 фигурирует специальная переменная, называемая управляющей. По ее значению устанавливается необходимость повторения цикла или выхода из него.

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

Любое из трех выражений в цикле for может отсутствовать, однако точка с запятой должна оставаться. Таким образом, for ( ; ; ) <. >— это бесконечный цикл, из которого можно выйти лишь другими способами.

В языке Си принято следующее правило. Любое выражение с операцией присваивания, заключенное в круглые скобки, имеет значение, равное присваиваемому. Например, выражение (а=7+2) имеет значение 9. После этого можно записать другое выражение, например: ((а=7+2)

позволяет вводить значение переменной сh и давать истинный результат только тогда, когда введенным значением является буква ‘i’. В скобках можно записывать и несколько формул, составляющих сложное выражение. Для этих целей используется операция запятая. Формулы будут вычисляться слева направо, и все выражение примет значение последней вычисленной формулы. Например, если имеются две переменные типа char, то выражение

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

Допускаются вложенные конструкции, т.е. в теле некоторого цикла могут встречаться другие операторы for.

Оператор while формально записывается в таком виде:

Выражение в скобках может принимать ненулевое (истинное) или нулевое (ложное) значение. Если оно истинно, то выполняется тело цикла и выражение вычисляется снова. Если выражение ложно, то цикл while заканчивается.

Оператор do-while формально записывается следующим образом:

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

Допускается вложенность одних циклов в другие, т.е. в теле любого цикла могут появляться операторы for, while и do — while.

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

Операторы условных и безусловных переходов

Для организации условных и безусловных переходов в программе на языке Си используются операторы: if — else, switch и goto. Первый из них записывается следующим образом:

Если условие в скобках принимает истинное значение, выполняется оператор_1, если ложное — оператор_2. Если вместо одного необходимо выполнить несколько операторов, то они заключаются в фигурные скобки. В операторе if слово else может отсутствовать.

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

Оператор switch позволяет выбрать одну из нескольких альтернатив. Он записывается в следующем формальном виде:

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

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

Допускаются вложенные конструкции switch.

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

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

РАЗДЕЛ 3. СТРУКТУРИРОВАННЫЕ ТИПЫ ДАННЫХ

Массивы

Массив состоит из элементов одного и того же типа. Ко всему массиву целиком можно обращаться по имени. Кроме того, можно выбирать любой элемент массива. Для этого необходимо задать индекс, который указывает на его относительную позицию. Число элементов массива назначается при его определении и в дальнейшем не изменяется. Если массив объявлен, то к любому его элементу можно обратиться следующим образом: указать имя массива и индекс элемента в квадратных скобках. Массивы определяются так же, как и переменные:

В первой строке объявлен массив а из 100 элементов целого типа: а[0], а[1], . а[99] (индексация всегда начинается с нуля). Во второй строке элементы массива b имеют тип char, а в третьей — float.

Двумерный массив представляется как одномерный, элементами которого так же являются массивы. Например, определение char а[10][20]; задает такой массив. По аналогии можно установить и большее число измерений. Элементы двумерного массива хранятся по строкам, т.е. если проходить по ним в порядке их расположения в памяти, то быстрее всего изменяется самый правый индекс. Например, обращение к девятому элементу пятой строки запишется так: а[5][9].

Пусть задан массив:

Тогда элементы массива а будут размещаться в памяти следующим образом: a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2].

Имя массива — это константа, которая содержит адрес его первого элемента (в данном примере а содержит адрес элемента а[0][0]). Предположим, что a = 1000. Тогда адрес элемента а[0][1] будет равен 1002 (элемент типа int занимает в памяти 2 байта), адрес следующего элемента а[0][2] — 1004 и т.д. Что же произойдет, если выбрать элемент, для которого не выделена память? К сожалению, компилятор не отслеживает данной ситуации. В результате возникнет ошибка и программа будет работать неправильно.

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

задает массив из пяти элементов а[0], a[1], a[2], a[3], a[4]. Если объект *у определен как

то оператор у = &a[0]; присваивает переменной у адрес элемента а[0]. Если переменная у указывает на очередной элемент массива а, то y+1 указывает на следующий элемент, причем здесь выполняется соответствующее масштабирование для приращения адреса с учетом длины объекта (для типа int — 2 байта, long — 4 байта, double — 8 байт и т.д.).

Так как само имя массива есть адрес его нулевого элемента, то оператор у = &a[0]; можно записать и в другом виде: у = а. Тогда элемент а[1] можно представить как *(а+1). С другой стороны, если у — указатель на массив a, то следующие две записи: a[i] и *(у+i) — эквивалентны.

Между именем массива и соответствующим указателем есть одно важное различие. Указатель — это переменная и у = а; или y++; — допустимые операции. Имя же массива — константа, поэтому конструкции вида a = y; a++; использовать нельзя, так как значение константы постоянно и не может быть изменено.

Переменные с адресами могут образовывать некоторую иерархическую структуру (могут быть многоуровневыми) типа указатель на указатель (т.е. значение указателя является адресом другого указателя), указатель на указатель на указатель и т.д. Если указатели адресуют элементы одного массива, то их можно сравнивать (отношения вида , = =, != и другие работают правильно). В то же время нельзя сравнивать ли6о использовать в арифметических операциях указатели на разные массивы (соответствующие выражения не приводят к ошибкам при компиляции, но в большинстве случаев не имеют смысла). Любой адрес можно проверить на равенство или неравенство с константой NULL. Указатели на элементы одного массива можно также вычитать. Тогда результатом будет число элементов массива, расположенных между уменьшаемым и вычитаемым объектами.

Язык Си позволяет инициализировать массив при его определении. Для этого используется следующая форма:

В последнем случае: b[0][0] = 1, b[0][1] = 2, b[0][2] = 3, b[1][0] = 4, b[1][1] = 5, b[1][2] = 6.

В языке допускаются массивы указателей, которые определяются, например, следующим образом: char *m[5];. Здесь m[5] — массив, содержащий адреса элементов типа char.

Строки символов

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

Определение char а[10]; указывает компилятору на необходимость резервирования места для максимум 10 символов. Константа а содержит адрес ячейки памяти, в которой помещено значение первого из десяти объектов типа char. Процедуры, связанные с занесением конкретной строки в массив а, копируют ее по одному символу в область памяти, на которую указывает константа а, до тех пор, пока не будет скопирован нулевой символ, оканчивающий строку. Когда выполняется функция типа printf(«%s», а), ей передается значение а, т.е. адрес первого символа, на который указывает а. Если первый символ — нулевой, то работа функции printf() заканчивается, а если нет, то она выводит его на экран, прибавляет к адресу единицу и снова начинает проверку на нулевой символ. Такая обработка позволяет снять ограничения на длину строки (конечно, в пределах объявленной размерности): строка может иметь любую длину, но в пределах доступной памяти.

Инициализировать строку при таком способе определения можно следующим образом: (при определении массива с одновременной инициализацией пределы изменения индекса можно не указывать).

Второй способ определения строки — это использование указателя на символ. Определение char *b; задает переменную b, которая может содержать адрес некоторого объекта. Однако в данном случае компилятор не резервирует место для хранения символов и не инициализирует переменную b конкретным значением. Когда компилятор встречает оператор вида b =»IBM PC»;, он производит следующие действия. Во-первых, как и в предыдущем случае, он создает в каком-либо месте объектного модуля строку «IBM PC», за которой следует нулевой символ (‘\0’). Во-вторых, он присваивает значение начального адреса этой строки (адрес символа ‘I’) переменной b. Функция printf(«%s», b) работает так же, как и в предыдущем случае, осуществляя вывод символов до тех пор, пока не встретится заключительный нуль.

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

Для ввода и вывода строк символов помимо scanf( ) и printf() могут использоваться функции gets( ) и puts( ) (их прототипы находятся в файле stdio.h).

Если string — массив символов, то ввести строку с клавиатуры можно так:

(ввод оканчивается нажатием клавиши ). Вывести строку на экран можно следующим образом:

Отметим также, что для работы со строками существует специальная библиотека функций, прототипы которых находятся в файле string.h.

Наиболее часто используются функции strcpy( ), strcat( ), strlen( ) и strcmp( ).

Если string1 и string2 — массивы символов, то вызов функции strcpy( ) имеет вид:

Эта функция служит для копирования содержимого строки string2 в строку string1. Массив string1 должен быть достаточно большим, чтобы в него поместилась строка string2. Так как компилятор не отслеживает этой ситуации, то недостаток места приведет к потере данных.

Вызов функции strcat( ) имеет вид:

Эта функция присоединяет строку string2 к строке string1 и помещает ее в массив, где находилась строка string1, при этом строка string2 не изменяется. Нулевой байт, который завершал первую строку, заменяется первым байтом второй строки.

Функция strlen( ) возвращает длину строки, при этом завершающий нулевой байт не учитывается. Если a — целое, то вызов функции имеет вид:

Функция strcmp( ) сравнивает две строки и возвращает 0, если они равны.

Структуры

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

Объявление структуры осуществляется с помощью ключевого слова struct, за которым идет ее тип и далее список элементов, заключенных в фигурные скобки:

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

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

(при этом выделяется соответствующая память). Описание без последующего списка не выделяет никакой памяти; оно просто задает форму структуры. Введенное имя типа позже можно использовать для объявления структуры, например:

Теперь переменная days имеет тип date.

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

Разрешается вкладывать структуры друг в друга, например:

Определенный выше тип data включает три элемента: day, month, year, содержащий целые значения (int). Структура man включает элементы name, fam, bd и voz. Первые два — name[20] и fam[20] — это символьные массивы из 20 элементов каждый. Переменная bd представлена составным элементом (вложенной структурой) типа data. Элемент age содержит значения целого типа int). Теперь можно определить переменные, значения которых принадлежат введенному типу:

Здесь определен массив man_, состоящий из 100 структур типа man.

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

При работе со структурами необходимо помнить, что тип элемента определяется соответствующей строкой описания в фигурных скобках. Например, массив man_ имеет тип man, year является целым числом и т.п. Поскольку каждый элемент структуры относится к определенному типу, его имя может появиться везде, где разрешено использование значений этого типа. Допускаются конструкции вида man_[i]=man_[j]; где man_[i] и man_[j] — объекты, соответствующие единому описанию структуры. Другими словами, разрешается присваивать одну структуру другой по их именам.

Унарная операция & позволяет взять адрес структуры. Предположим, что определена переменная day:

Здесь day — это структура типа date, включающая три элемента: d, m, у. Другое определение

устанавливает тот факт, что db — это указатель на структуру типа date.

В этом случае для выбора элементов d, m, у структуры необходимо использовать конструкции:

Действительно, db — это адрес структуры, *db — сама структура. Круглые скобки здесь необходимы, так как точка имеет более высокий, чем звездочка, приоритет. Для аналогичных целей в языке Си предусмотрена специальная операция ->. Эта операция выбирает элемент структуры и позволяет представить рассмотренные выше конструкции в более простом виде:

Оператор typedef

Рассмотрим описание структуры:

Здесь фактически вводится новый тип данных — data. Теперь его можно использовать для объявления конкретных экземпляров структуры, например:

В язык Си введено специальное средство, позволяющее назначать имена типам данных (переименовывать). Таким средством является оператор typedef. Он записывается в следующем виде:

Здесь «тип» — любой разрешенный тип данных и «имя» — любой разрешенный идентификатор.

После этого можно сделать объявление:

Оно будет выполнять то же самое, что и привычное объявление int a,b;. Другими словами, INTEGER можно использовать как синоним ключевого слова int.

Битовые поля

Особую разновидность структур представляют собой битовые поля. Битовое поле — это последовательность соседних битов внутри одного, целого значения. Оно может иметь тип signed int или unsigned int и занимать от 1 до 16 битов. Поля размещаются в машинном слове в направлении от младших к старшим разрядам. Например, структура:

обеспечивает размещение данных в двух байтах (в одном слове). Если бы последнее поле было задано так: unsigned d:6, то оно размещалось бы не в первом слове, а в разрядах 0 — 5 второго слова.

В полях типа signed крайний левый бит является знаковым.

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

Объединение (union)

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

Пусть задано определение:

Здесь ir имеет размер 2 байта, fr — 4 байта, cr — 1 байт. Размер переменной z будет равен размеру самого большого из трех приведенных типов (т.е. 4 байтам). В один и тот же момент времени z может иметь значение только одной из переменных ir, fr или cr.

Перечислимый тип данных

Перечислимый тип данных предназначен для описания объектов из некоторого заданного множества. Он задается ключевым словом enum. Рассморим пример:

Здесь введен новый тип данных seasons. Теперь можно определить переменные этого типа:

Каждая из них (а, b, c) может принимать одно из четырех значений: spring, summer, autumn и winter. Эти переменные можно было определить сразу при описании типа:

Рассмотрим еще один пример:

Имена, занесенные в days (также как и в seasons в предыдущем примере), представляют собой константы целого типа. Первая из них (mon) автоматически устанавливается в нуль, и каждая следующая имеет значение на единицу больше, чем предыдущая (tues=1, wed=2 и т.д.).

Можно присвоить константам определенные значения целого типа (именам, не имеющим их, будут, как и раньше, назначены значения предыдущих констант, увеличенные на единицу). Например:

После этого mon=5, tues=8,wed=10, thur=11, fri=12, sat=13, sun=14.

Тип enum можно использовать для задания констант true=1 и false=0, например:

РАЗДЕЛ 4. ФУНКЦИИ

Общие сведения

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

В общем случае функции в языке Си необходимо объявлять. Объявление функции (т.е. описание заголовка) должно предшествовать ее использованию, а определение функции (т.е. полное описание) может быть помещено как после тела программы (т.е. функции main( )), так и до него. Если функция определена до тела программы, а также до ее вызовов из определений других функций, то объявление может отсутствовать. Как уже отмечалось, описание заголовка функции обычно называют прототипом функции.

Функция объявляется следующим образом:

Тип функции определяет тип значения, которое возвращает функция. Если тип не указан, то предполагается, что функция возвращает целое значение (int).

При объявлении функции для каждого ее параметра можно указать только его тип (например: тип функция (int, float, . ), а можно дать и его имя (например: тип функция (int а, float b, . ) ).

В языке Си разрешается создавать функции с переменным числом параметров. Тогда при задании прототипа вместо последнего из них указывается многоточие.

Определение функции имеет следующий вид:

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

Таких операторов в подпрограмме может быть несколько, и тогда они фиксируют соответствующие точки выхода. Например:

Вызвать эту функцию можно следующим образом:

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

В языке Си аргументы функции передаются по значению, т.е. вызванная функция получает свою временную копию каждого аргумента, а не его адрес. Это означает, что вызванная функция не может изменить значение переменной вызвавшей ее программы. Однако это легко сделать, если передавать в функцию не переменные, а их адреса. Например:

Вызов swap(&b, &c) (здесь подпрограмме передаются адреса переменных b и с) приведет к тому, что значения переменных b и c поменяются местами.

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

Рассмотрим, как функции можно передать массив в виде параметра. Здесь возможны три варианта:

  1. Параметр задается как массив (например: int m[100];).
  2. Параметр задается как массив без указания его размерности (например: int m[];).
  3. Параметр задается как указатель (например: int *m;). Этот вариант используется наиболее часто.

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

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

Классы памяти

В языке Си различают четыре основных класса памяти: внешнюю (глобальную), автоматическую (локальную), статическую и регистровую память.

Внешние (глобальные) переменные определены вне функций и, следовательно, доступны для любой из них. Они могут быть определены только один раз. Выше уже говорилось, что сами функции всегда глобальные. Язык не позволяет определять одни функции внутри других. Область действия внешней переменной простирается от точки во входном файле, где она объявлена, до конца файла. Если на внешнюю переменную нужно ссылаться до ее определения или она определена в другом входном файле, то в подпрограмме или файле она должна быть объявлена как extern.

Автоматические переменные по отношению к функциям являются внутренними или локальными. Они начинают существовать при входе в функцию и уничтожаются при выходе из нее (для них можно использовать ключевое слово auto). Однако оно практически не используется, так как при отсутствии ключевого слова переменные по умолчанию принадлежат к классу auto.

Статические переменные объявляются с помощью ключевого слова static. Они могут быть внутренними (локальными) или внешними (глобальными). Внутренние статические переменные, как и автоматические, локальны по отношению к отдельной функции. Однако они продолжают существовать, а не возникают и не уничтожаются при каждом ее вызове. Другими словами, они являются собственной постоянной памятью для функции. Внешние статические переменные доступны внутри оставшейся части файла после того, как они в нем объявлены, однако в других файлах они неизвестны. Это, в частности, позволяет скрыть данные одного файла от другого файла.

Регистровые переменные относятся к последнему классу. Ключевое слово register говорит о том, что переменная, о которой идет речь, будет интенсивно использоваться. Если возможно, значения таких переменных помещаются во внутренние регистры микропроцессора, что может привести к более быстрой и короткой программе (разработчики компиляторов фирмы Borland утверждают, что оптимизация компиляторов данной фирмы по использованию регистровых переменных сделана так хорошо, что указание использовать переменную как регистровую может только снизить эффективность создаваемого машинного кода). Для регистровых переменных нельзя взять адрес; они могут быть только автоматическими с допустимыми типами int или char.

Таким образом, можно выделить четыре модификатора класса памяти: extern, auto, static, register. Они используются в следующей общей форме:

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

Указатели на функции

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

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

Через указатель можно войти в функцию, т.е. запустить ее на выполнение. Объявление вида:

говорит о том, что f — это указатель на функцию, возвращающую целое значение. Первая пара скобок необходима, без них int *f( ); означало бы, что f — функция, возвращающая указатель на целое значение. После объявления указателя на функцию в программе можно использовать объекты: *f — сама функция; f — указатель на функцию. Для любой функции ее имя (без скобок и аргументов) является указателем на эту функцию.

Аргументы функции main( )

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

Любая такая строка представляется в виде:

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

Назовем аргументы функции main( ) соответственно: argc, argv и env (возможны и любые другие имена). Тогда допустимы следующие описания:

Предположим, что на диске A: есть некоторая программа prog.exe. Обратимся к ней следующим образом:

Тогда argv[0] — это указатель на строку A:\prog.exe, argv[1] — на строку file1 и т.д. На первый фактический аргумент указывает argv[1], а на последний — argv[3]. Если argc=1, то после имени программы в командной строке параметров нет. В нашем примере argc=4.

Рекурсия

Рекурсией называется такой способ вызова, при котором функция обращается к самой себе.

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

Библиотечные функции

В системах программирования подпрограммы для решения часто встречающихся задач объединяются в библиотеки. К числу таких задач относятся: вычисление математических функций, ввод/вывод данных, обработка строк, взаимодействие со средствами операционной системы и др. Использование библиотечных подпрограмм избавляет пользователя от необходимости разработки соответствующих средств и предоставляет ему дополнительный сервис. Включенные в библиотеки функции поставляются вместе с системой программирования. Их объявления даны в файлах *.h (это так называемые включаемые или заголовочные файлы). Поэтому, как уже упоминалось выше, в начале программы с библиотечными функциями должны быть строки вида:

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

РАЗДЕЛ 5. ФАЙЛЫ

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

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

В Си существует два типа потоков: текстовые (text) и двоичные (binary).

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

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

Прежде чем читать или записывать информацию в файл, он должен быть открыт и тем самым связан с потоком. Это можно сделать с помощью библиотечной функции fopen( ). Она берет внешнее представление файла (например, c:\my_prog.txt) и связывает его с внутренним логическим именем, которое используется далее в программе. Логическое имя — это указатель на требуемый файл. Его необходимо определить; делается это, например, так:

Здесь FILE — имя типа, описанное в стандартном заголовочном файле stdio.h, fp — указатель на файл. Обращение к функции fopen( ) в программе осуществляется выражением:

Спецификация файла (т.е. имя файла и путь к нему) может, например, иметь вид: «c:\\my_prog.txt» — для файла my_prog.txt на диске с:.

Способ использования файла задается следующими символами:

    r — открыть существующий файл для чтения;
    w — создать новый файл для записи (если файл с указанным именем существует, то он будет переписан);
    а — дополнить файл (открыть существующий файл для записи информации, начиная с конца файла, или создать файл, если он не существует);

r+ — открыть существующий файл для чтения и записи;
w+ — создать новый файл для чтения и записи;
a+ — дополнить или создать файл с возможностью чтения и записи;

rb — открыть двоичный файл для чтения;
wb — создать двоичный файл для записи;
аb — дополнить двоичный файл;

r+b — открыть двоичный файл для чтения и записи;
w+b — создать двоичный файл для чтения и записи;
а+b — дополнить двоичный файл с предоставлением возможности чтения и записи;

rt — открыть текстовой файл для чтения;
wt — создать текстовый файл для записи;
at — дополнить текстовый файл;

r+t — открыть текстовой файл для чтения и записи;
w+t — создать текстовый файл для чтения и записи;
a+t — дополнить текстовый файл с предоставлением возможности записи и чтения.

Если режим t или b не задан (например, r, w или а), то он определяется значением глобальной переменной _fmode. Если fmode=0_BINARY, то файлы открываются в двоичном режиме, а если _fmode=0_TEXT — в текстовом режиме. Константы 0_BINARY и 0_ТЕXТ определены в файле fcntl.h.

Строки вида r+b можно записывать и в другой форме: rb+.

Если в результате обращения к функции fopen( ) возникает ошибка, то она возвращает константу NULL.

Рекомендуется использовать следующий способ открытия файла:

После окончания работы с файлом он должен быть закрыт. Это делается с помощью библиотечной функции fclose( ). Она имеет следующий прототип:

При успешном завершении операции функция fclose( ) возвращает значение нуль. Любое другое значение свидетельствует об ошибке.

Рассмотрим другие библиотечные функции, используемые для работы с файлами (все они описаны в файле stdio.h):

1. Функция putc( ) записывает символ в файл и имеет следующий прототип:

Здесь fp — указатель на файл, возвращенный функцией fopen( ), с — символ для записи (переменная с имеет тип int, но используется только младший байт). При успешном завершении putc( ) возвращает записанный символ, в противном случае возвращается константа EOF. Она определена в файле stdio.h и имеет значение -1.

2. Функция getc( ) читает символ из файла и имеет следующий прототип:

Здесь fp — указатель на файл, возвращенный функцией fopen( ). Эта функция возвращает прочитанный символ. Соответствующее значение имеет тип int, но старший байт равен нулю. Если достигнут конец файла, то getc( ) возвращает значение ЕОF.

3. Функция feof( ) определяет конец файла при чтении двоичных данных и имеет следующий прототип:

Здесь fp — указатель на файл, возвращенный функцией fopen( ). При достижении конца файла возвращается ненулевое значение, в противном случае возвращается 0.

4. Функция fputs( ) записывает строку символов в файл. Она отличается от функции puts( ) только тем, что в качестве второго параметра должен быть записан указатель на переменную файлового типа.

При возникновении ошибки возвращается значение EOF.

5. Функция fgets( ) читает строку символов из файла. Она отличается от функции gets( ) тем, что в качестве второго параметра должно быть указано максимальное число вводимых символов плюс единица, а в качестве третьего — указатель на переменную файлового типа. Строка считывается целиком, если ее длина не превышает указанного числа символов, в противном случае функция возвращает только заданное число символов.

Функция возвращает указатель на строку string при успешном завершении и константу NULL в случае ошибки либо достижения конца файла.

6. Функция fprintf( ) выполняет те же действия, что и функция printf( ), но работает с файлом. Ее отличием является то, что в качестве первого параметра задается указатель на переменную файлового типа.

7. Функция fscanf( ) выполняет те же действия, что и функция scanf(), но работает с файлом. Ее отличием является то, что в качестве первого параметра задается указатель на переменную файлового типа.

При достижении конца файла возвращается значение EOF.

8. Функция fseek( ) позволяет выполнять чтение и запись с произвольным доступом и имеет следующий прототип:

Здесь fp — указатель на файл, возвращенный функцией fopen( ), count — номер байта относительно заданной начальной позиции, начиная с которого будет выполняться операция, access — способ задания начальной позиции.

Переменная access может принимать следующие значения:

    0 — начальная позиция задана в начале файла;
    1 — начальная позиция считается текущей;
    2 — начальная позиция задана в конце файла.

При успешном завершении возвращается нуль, при ошибке — ненулевое значение.

9. Функция ferror( ) позволяет проверить правильность выполнения последней операции при работе с файлами. Имеет следующий прототип:

В случае ошибки возвращается ненулевое значение, в противном случае возвращается нуль.

10. Функция remove( ) удаляет файл и имеет следующий прототип:

Здесь file_name — указатель на строку со спецификацией файла. При успешном завершении возвращается нуль, в противном случае возвращается ненулевое значение.

11. Функция rewind( ) устанавливает указатель текущей позиции в начало файла и имеет следующий прототип:

12. Функция fread( ) предназначена для чтения блоков данных из потока. Имеет прототип:

Она читает n элементов данных, длиной size байт каждый, из заданного входного потока fp в блок, на который указывает указатель ptr. Общее число прочитанных байтов равно произведению n*size. При успешном завершении функция fread( ) возвращает число прочитанных элементов данных, при ошибке — 0.

13. Функция fwrite( ) предназначена для записи в файл блоков данных. Имеет прототип:

Она добавляет n элементов данных, длиной size байт каждый, в заданный выходной файл fp. Данные записываются с позиции, на которую указывает указатель ptr. При успешном завершении операции функция fwrite( ) возвращает число записанных элементов данных, при ошибке — неверное число элементов данных.

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

    stdin — для ввода данных из стандартного входного потока (по умолчанию — c клавиатуры);
    stdout — для вывода данных в стандартный выходной поток (по умолчанию — на экран дисплея);
    stderr — файл для вывода сообщений об ошибках (всегда связан с экраном дисплея);
    stdprn — для вывода данных на принтер;
    stdaus — для ввода и вывода данных в коммуникационный канал.

В языке Си имеется также система низкоуровневого ввода/вывода (без буферизации и форматирования данных), соответствующая стандарту системы UNIX. Прототипы составляющих ее функций находятся в файле io.h. К этим функциям относятся:

    open( ) — открыть файл;
    close( ) — закрыть файл;
    read( ) — читать данные;
    write( ) — записать данные;
    lseek( ) — поиск определенного байта в файле;
    unlink( ) — уничтожить файл.

РАЗДЕЛ 6. ДРУГИЕ ВОЗМОЖНОСТИ

Динамическое распределение памяти. Функции malloc( ) и free( )

В языке Си принято следующее распределение памяти:

СТЕК Верхние адреса
СВОБОДНАЯ ПАМЯТЬ
РАЗДЕЛ ГЛОБАЛЬНЫХ
ПЕРЕМЕННЫХ И КОНСТАНТ
КОД ПРОГРАММЫ Нижние адреса

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

Функции malloc( ) и free( ) используются для динамического распределения свободной памяти. Функция malloc( ) выделяет память, функция free( ) освобождает ее. Прототипы этих функций хранятся в заголовочном файле stdlib.h и имеют вид:

Функция malloc( ) возвращает указатель типа void; для правильного использования значение функции надо преобразовать к указателю на соответствующий тип. При успешном выполнении функция возвращает указатель на первый байт свободной памяти размера size. Если достаточного количества памяти нет, возвращается значение 0. Чтобы определить количество байтов, необходимых для переменной, используют операцию sizeof( ).

Пример использования этих функций:

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

Препроцессор

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

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

Первая строка вызывает замену в программе идентификатора MAX на константу 25. Вторая позволяет использовать в тексте вместо открывающей фигурной скобки ( < ) слово BEGIN.

Отметим, что поскольку препроцессор не проверяет совместимость между символическими именами макроопределений и контекстом, в котором они используются, то рекомендуется такого рода идентификаторы определять не директивой #define, а с помощью ключевого слова const с явным указанием типа (это в большей степени относится к Си++):

(тип int можно не указывать, так как он устанавливается по умолчанию).

Если директива #define имеет вид:

причем между первым идентификатором и открывающей круглой скобкой нет пробела, то это определение макроподстановки с аргументами. Например, после появления строки вида:

оператор READ(y); воспринимается так же, как scanf(«%d»,&y);. Здесь val — аргумент и выполнена макроподстановка с аргументом.

При наличии длинных определений в подстановке, продолжающихся в следующей строке, в конце очередной строки с продолжением ставится символ \.

В макроопределение можно помещать объекты, разделенные знаками ##, например:

После этого PR(а, 3) вызовет подстановку а3. Или, например, макроопределение приведет к замене z(sin, x, +, y) на sin(x+y).

Символ #, помещаемый перед макроаргументом, указывает на преобразование его в строку. Например, после директивы

следующий фрагмент текста программы

Опишем другие директивы препроцессора. Директива #include уже встречалась ранее. Ее можно использовать в двух формах:

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

Следующая группа директив позволяет избирательно компилировать части программы. Этот процесс называется условной компиляцией. В эту группу входят директивы #if, #else, #elif, #endif, #ifdef, #ifndef. Основная форма записи директивы #if имеет вид:

Здесь проверяется значение константного выражения. Если оно истинно, то выполняется заданная последовательность операторов, а если ложно, то эта последовательность операторов пропускается.

Действие директивы #else подобно действию команды else в языке Си, например:

Здесь если константное выражение истинно, то выполняется последовательность_операторов_1, а если ложно — последовательность_операторов_2.

Директива #elif означает действие типа «else if». Основная форма ее использования имеет вид:

Эта форма подобна конструкции языка Си вида: if. else if. else if.

устанавливает определен ли в данный момент указанный идентификатор, т.е. входил ли он в директивы вида #define. Строка вида

проверяет является ли неопределенным в данный момент указанный идентификатор. За любой из этих директив может следовать произвольное число строк текста, возможно, содержащих инструкцию #else (#elif использовать нельзя) и заканчивающихся строкой #endif. Если проверяемое условие истинно, то игнорируются все строки между #else и #endif, а если ложно, то строки между проверкой и #else (если слова #else нет, то #endif). Директивы #if и #ifndef могут «вкладываться» одна в другую.

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

Рассмотрим примеры. Три следующие директивы:

проверяют определен ли идентификатор WRITE (т.е. была ли команда вида #define WRITE. ), и если это так, то имя WRITE начинает считаться неопределенным, т.е. не подлежащим замене.

проверяют является ли идентификатор WRITE неопределенным, и если это так, то определятся идентификатор WRITE вместо имени fprintf.

Директива #error записывается в следующей форме:

Если она встречается в тексте программы, то компиляция прекращается и на экран дисплея выводится сообщение об ошибке. Эта команда в основном применяется на этапе отладки. Заметим, что сообщение об ошибке не надо заключать в двойные кавычки.

Директива #line предназначена для изменения значений переменных _LINE_ и _FILE_, определенных в системе программирования Си. Переменная _LINE_ содержит номер строки программы, выполняемой в текущий момент времени. Идентификатор _FILE_ является указателем на строку с именем компилируемой программы. Директива #line записывается следующим образом:

Здесь номер — это любое положительное целое число, которое будет назначено переменной _LINE_, имя_файла — это необязательный параметр, который переопределяет значение _FILE_.

Директива #pragma позволяет передать компилятору некоторые указания. Например, строка

говорит о том, что в программе на языке Си имеются строки на языке ассемблера. Например: и т.д.

Рассмотрим некоторые глобальные идентификаторы или макроимена (имена макроопределений). Определены пять таких имен: _LINE_, _FILE_, _DATE_, _TIME_, _STDC_. Два из них (_LINE_ и _FILE_) уже описывались выше. Идентификатор _DATE_ определяет строку, в которой сохраняется дата трансляции исходного файла в объектный код. Идентификатор _TIME_ задает строку, сохраняющую время трансляции исходного файла в объектный код. Макрос _STDC_ имеет значение 1, если используются стандартно — определенные макроимена. В противном случае эта переменная не будет определена.

Использование программно-доступных регистров микропроцессора Intel 8086

В языке Си для IBM-совместимых персональных компьютеров обращение к регистрам микропроцессора Intel 8086 осуществляется с помощью специальных объектов, называемых псевдопеременными. Полный список псевдопеременных включает 21 элемент: _АХ, _ВХ, _СХ, _DX, _CS, _DS, _SS, _ES, _SP, _ВР, _DI, _SI, _AL, _AH, _BL, _ВH, _CL, _СН, _DL, _DH, _FLAGS. Их имена образуются из имен регистров с префиксом _ (например, переменная _AX связана с регистром AX). Первые двенадцать псевдопеременных и последняя имеют тип unsigned int, а оставшиеся восемь — unsigned char. Присвоение значения какой-либо переменной, например _АХ, вызывает занесение этого значения в регистр АХ. Получение значения переменной, например _ВХ, эквивалентно получению значения из регистра ВХ.

РАЗДЕЛ 7. ПРИМЕРЫ

Рассмотрим примеры программ, в которых используются различные конструкции языка Си. Первый из них демонстрирует использование управляющих символов n в функциях printf( ) и scanf( ).

Результаты работы этой программы имеют вид:

Значение n1 определяет число введенных цифр, а n2 — число выведенных символов в строке x = 234 (с пробелами).

Следующий пример показывает использование спецификаций %[], а также символов * и #.

Результаты работы программы имеют следующий вид:

Здесь пользователем введена строка Comp-1-2-3-4-5. Из нее только четыре символа (Comp) совпадают с первыми символами, заданными в квадратных скобках рассматриваемой спецификации [Computer]. Поэтому только эти четыре символа попадут в первую строку, а оставшиеся символы (1-2-3-4-5) попадут во вторую строку. Число n1 определяет минимальную ширину поля для вывода, а число n2 = 3 — количество цифр после запятой. В результате число 12.345678 будет смещено относительно левой границы, и после запятой будут выведены три цифры. Шестнадцатеричное число 0х100 выведено функцией printf( ) с префиксом 0x, без префикса 0x и в десятичной форме.

Третья программа демонстрирует использование условного оператора if. else и оператора for для организации цикла.

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

Новая библиотечная функция clrscr( ) имеет следующий прототип:

Она выполняет очистку экрана и объявлена в заголовочном файле conio.h.

Четвертая программа демонстрирует использование рекурсивной функции для вычисления факториала. (Отметим, что определение функции factorial( ) может находиться и после функции main( ), но в этом случае функция factorial( ) должна быть объявлена перед функцией main( ), т.е. до main( ) необходимо поместить строку: long factorial(int);.)

Результаты работы этой программы:

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

Результаты работы этой программы:

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

  • занесение фамилии абонента и номера телефона в справочник;
  • поиск в справочнике номера телефона по фамилии абонента;
  • удаление из справочника фамилии абонента и номера его телефона.

Ниже приведен текст головной программы main.c:

С помощью директив #include в головную программу включаются файлы: my.h, findt.c, choicet.c, addt.c и subt.c. Считается, что все они находятся в корневом каталоге диска A:. Если это не так, то необходимо изменить соответствующие директивы #include. В файле my.h определены глобальные переменные и некоторые символьные значения.

Файл my.h, в частности, определяет, что телефонный справочник будет организован в каталоге tel диска A:. Поэтому необходимо перед запуском программы main.exe создать этот подкаталог либо использовать другой подкаталог. В последнем случае необходимо изменить строку:

которая задает имя файла с телефонным справочником (tel_num.txt).

Модуль findt.c, текст которого приведен ниже, содержит функцию Find( ) для поиска строки str в файле tel_num.txt.

Модуль choicet.c содержит функцию Choice( ), позволяющую проверить есть ли заданная строка в файле tel_num.txt.

Модуль addt.c содержит функцию Add( ), которая добавляет заданную строку в файл tel_num.txt.

Модуль subt.c содержит функцию Sub( ), которая удаляет заданную строку из файла tel_num.txt.

Ниже приводится возможный сценарий работы с программой main.

Последняя программа showt.c позволяет вывести на экран содержимое телефонного справочника.

Си в качестве «первого» языка

Начинай сразу с objective-C, с реального приложения. Нет ничего хуже, чем отсутствие заинтересованности, даже если сейчас чешется, удержать это ощущение на долго не получится, а живой проект будет отличным мотиватором.
Язык — это лишь способ реализации определенных задач, если цель твоя iOS — просто глупо начинать с C. Я лично не вижу ни одного «за». А глубокие материи ты и на С все равно так вот сразу не познаешь, все прийдет с опытом.

Из литературы посоветую — Фаулер «Рефакторинг. Улучшение существующего кода.» — поможет сразу писать код более правильно и ускорить процесс «вникания в высшие матери»

. Другое дело, что очень часто (пример – курсы Стэнфорда CS193P) в учебных пособиях по Obj-C подразумевается знание C.

Это так же подразумевает наличия опыта (вернувшись к аналогии с вождением — это как пересесть с легковой на грузовик скажем).

Просто начни и все. Язык не важен, важна платформа и прадигма. Си — это процедурный язык, obj-c — объектно-ориентированный. И это один из главных доводов против выбора Си, как первого. Второй — платформа. Практикуя сразу под iOS — ты постепенно ознакомишься с API девайсов и не будешь изучать не нужные тебе программные интерфейсы десктопов.
Литература не важна — подойдет любоая описывающая в подходящей тебе манере API и основы языка. Остальное легко найти в сети.

Мой совет начинать в таком порядке, свою карьеру программером:

1) Плаксин.М «Тестирование_и_отладка_программ». Начните ковыряться с существующими программами, за основу можно взять calc.exe или еще что-либо. Умение тестировать дает возможность беспощадной работы со своим собственным кодом за который вы будете в ответе перед своими коллегами. Это очень полезный навык, пусть даже в минимальном объеме но программер должен уметь тестировать!

2) Язык С среди компьютерных языков сейчас занимает туже роль что и Английский среди человеческих. Зная С вам легче будет понять другие!

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

4) Алгоритмы, без них никуда! Чем больше вы их знаете и умете применять на практике и давать оценку по сложности, тем лучше!

5) Паттерны, это имеет смысл когда у вас хоть какой-то опыт программирования. Хотя бы 20 программ напишите, потом поймете сразу что на практике вам встречалось, а что нет. Будете отчетливо понимать чем конкретно тот или иной паттерн может вам помочь.

6) Будьте прагматичны! Любое действие должно Вас приводить к какой-либо ранее поставленной Вами цели.

7) Почитайте «Мифический человеко-месяц» Брукса. То что изложено в книге нужно понимать для того чтобы знать какие конкретно задачи следует выполнять, а какие нет! Умение поправить руководителя правильно и корректно, причем аргументировано дает Вам возможность принести больше в программный проект и следовательно даст Вам преимущество перед коллегами.

Преимущества и недостатки C# — Учим Шарп #1

Опубликовано shwan в 06.11.2020

Я хочу обсудить с тобой один очень важный вопрос, который достаточно часто упускают из внимания: действительно ли тебе нужно учить язык C#?

Что бы тебе ни рассказывали на всевозможных онлайн курсах, книгах, тренингах и конференциях, о том, как можно стать программистом за 21 день – все это ложь, п*дежь и провокация.

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

Поэтому, я предлагаю тебе предварительно рассмотреть основные преимущества и недостатки языка C#, перспективы развития, сферы применения и уровни зарплатных ожиданий. Это может помочь тебе понять действительно ли ты правильно инвестируешь свое время. А время – это самый ценный ресурс, запомни это.

История языка C#

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

Данный язык создан всеми так горячо любимой корпорацией Зла Microsoft в 2000 году. Он очень многое унаследовал от своих родителей (С++ и Java), но и привнес нового.

Возможной версией использования символа хештега принято считать наследование плюсиков от предков, примерно следующим образом: C → C++ → C++++(C#), потому что символ «#» при хорошем воображении можно получить путем объединения 4-х знаков «+».

Язык активно развивается. Регулярно выходят новые версии C#, которые добавляют новые синтаксические конструкции в язык, а также увеличивают его быстродействие и надежность.

Преимущества C#

Данный язык использует объектно-ориентированный подход к программированию во всем. Это означает, что тебе нужно будет описывать абстрактные конструкции на основе предметной области, а потом реализовывать между ними взаимодействие. Данный подход пользуется большой популярностью, потому что позволяет не держать в голове всю информацию, а работать по принципу черного ящика: подал входные данные -> МАГИЯ -> PROFIT.

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

Еще стоит упомянуть, что все это работает на базе платформы .NET Framework. Что это означает? Для многих непосвященных, это просто какая-то приблуда, которую нужно установить на комп, чтобы программа запустилась, но дело обстоит значительно глубже. Написанный тобой код на языке C# транслируется в промежуточный язык (IL), который в свою очередь уже преобразуется в машинный код на твоем компьютере прямо во время выполнения приложения (JIT). Спрашивается, зачем это все? А суть в том, что ты можешь пилить со своим другом Васей на разных языках один и тот же проект и ни одному из вас не придется переучиваться. Но я никогда не видел, чтобы это реально использовали на практике. Но это еще не все. Так как окончательная компиляция из промежуточного кода выполняется в живую на твоей конкретной машине, то возможно увеличение производительности за счет использования специфических команд именно твоего процессора.

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

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

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

Но IDE действительно хороша, к тому же имеется ее полнофункциональная бесплатная версия Community.

Еще к плюсам можно отнести строгую типизацию, которая позволяет защититься от дурака, и не так давно появившаяся кросспратформенность в .NET Core (да-да, мелкомягкие потихоньку захватывают линукс).

Недостатки C#

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

C# очень легко дизассемблируется. Это означает, что с большой долей вероятности твой код будет получен и изучен конкурентами. Конечно же, есть специальные инструменты, которые могут усложнить этот процесс, но на 100% защититься от этого практически невозможно.

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

C# не является повсеместно распространенным языком. Большинство программистов сосредоточены в коммерческой Enterprise сфере, что накладывает весьма серьезные ограничения на поиск работы в небольших городах, где кроме Delphi или PHP ничего жизни не видели. К тому же, как бы то ни было, C# в первую очередь ассоциируется с Windows. Вряд ли в обозримом будущем что-то изменится и Винда все также будет продолжать доминировать на рынке, но все же небольшой риск остается, особенно учитывая недавние фейлы с обновлениями в Windows 10.

Перспективы развития C#

C# входит в первую пятерку самых популярных языков программирования на 2020 год. Он используется во многих крупных компаниях, а также и в небольших стартапах. Сейчас компания Microsoft делает большой упор на развитие универсальности и кросспалтформенности для этого языка. Уже сейчас с его помощью можно разрабатывать практически любой тип приложений.

Компания Microsoft остается одной из крупнейших IT компаний мира, а C# ее флагманский язык программирования, который постоянно развивается и впитывает в себя все новые возможности. Поэтому в обозримом будущем проблем у данного языка возникнуть не должно.

Сферы применения языка C#

В этой области C#, наверное, впереди планеты всей. Хочешь разрабатывать обычные приложения для компьютера – пожалуйста, стандартные WinForms Application и консоль тебе в помощь. Хочешь такие же, но покрасивее? – используй WPF. И специальные приложения для магазина в Windows Store тоже. Веб-приложения? – Легко ASP.NET всегда придет на помощь. На Linux? – тоже не вопрос, .NET Core уже здесь. Мобильное приложение? – Xamarin сделает сразу под все платформы. Хочешь написать игру? – движок Unity показывает себя очень даже неплохо, и при этом также адаптирует игру под различные платформы. Хочешь приблизить апокалипсис с восстанием машин и создаешь искусственный интеллект? – есть целая платформа с кучей инструментов для этого Microsoft AI Platform. Также и для компьютерного зрения и ботов. Я вообще с трудом могу придумать пример того, что невозможно реализовать на C#. Я где-то встречал даже операционную систему написанную на шарпе. Поэтому в этой области все хорошо.

Зарплаты разработчиков C#

Здесь все в целом неплохо. По данным на 2020 год, C# явно не является самым высокооплачиваемым языком, но и не самый низкооплачиваемый тоже. Среднее значение зарплаты для данного языка в России около 90к рублей. Это весьма неплохой результат, но бесспорно есть и более дорогие языки. В целом, уровень заработной платы намного больше зависит от прямоты рук и уровня знаний, поэтому не так важно на каком языке писать, главное делать это хорошо. Но данная цифра задает примерный уровень для Middle разработчика в среднем по России. От этого уже можно отталкиваться.

Итоги

C# это объектно-ориентированный язык с большим количеством синтаксического сахара, что позволяет экономить время и силы. Он используется во многих крупны организациях, стартапах, а также начинающими. Имеется удобная и бесплатная среда разработки. Достаточно прост в освоении на базовом уровне, но содержит вагон и маленькую тележку скрытых особенностей, чтобы разобраться в которых потребуется много времени. Позволяет разрабатывать универсальные мобильные приложения и игры, но используется для этого достаточно редко.

В целом это перспективный язык, достаточно простой для освоения начинающим. Но следует помнить, что существует множество альтернатив, которые лучше подходят под некоторые задачи. Например, могу порекомендовать языки C++, Java, Python.

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

Основная идея C# — это универсальность. Ты можешь реализовать все на одном языке и для любой платформы, но с большой долей вероятности это будет работать медленнее, чем разработанное специально под конкретную платформу.

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

На этом мы заканчиваем наш первый урок. Подписывайтесь на мои социальные сети: Вконтакте, Телеграм, YouTube и Дзен. Ну а еще есть специальный закрытый чат, для изучающих C# по моему курсу. С вами был Вадим. Пока!

elizarov

Блог Романа Елизарова

Я писал о том, что программист должен знать несколько языков программирования. Теперь я конкретизирую какие именно языки должны быть известному каждому программисту. Начну с языка программирования Си. Согласно индексу TIOBE, язык Си является самым популярным языком программирования уже очень продолжительное время. Он иногда уступает первую позицию, но в общем стабильно держится первым.

Язык Си в целом стандартизован и компиляторы для него существуют практически под любую платформу. Большая часть системного программного обеспечение пишется на языке Си. Ядро операционной системы Linux, да и многих других, полностью написано на языке Си. Разработчики системного ПО стараются сводить к минимуму платформенно-зависимые вставки на ассемблере, что позволяет повторно использовать большую часть кода.

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

Зачем же нужно знание языка Си программисту, который пишет прикладное программное обеспечение на других языках? Во первых, все первые пять наиболее популярных сейчас языков программирования так или иначе основаны на языке Си. В дополнение к самому Си на первом месте, C++ и Objective-C являются его расширениями в том или ином виде, а Java и C# используют синтаксис основанный на языке Си.

Во вторых, если программист пишет на каком-нибудь узкоспециализированном или универсальном динамическом языке (PHP, JavaScript, Python, Perl и т.п.), то его среда исполнения, интерпретатор, и основные библиотеки в большинстве случаев написаны на Си (ну или иногда на C++, что не отменяет необходимость знать Си). А значит для того, чтобы понять что же именно происходит в том или ином куске кода, почему та или иная операция занимает какое-то определенное время или потребляет какие-то ресурсы нужно иметь представление о языке Си. Любая нестандартная ситуация или неожиданное поведение — и вот уже приходится изучать исходные тексты библиотеки на Си. Любой выход за рамки задач, которые были предусмотрены разработчиками языка — и вот уже приходится самому писать расширение на языке Си. Собственно, все универсальные языки программирования поддерживают тот или иной способ взаимодействия с кодом написанным на Си, что подчеркивает особый статус языка Си в современном мире.

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

Язык Си это лингва франка современного программистского мира. Хотите, чтобы ваши идеи были понятны наибольшему число программистов? Изложите их на языке Си или, на крайний случай, на одном из Си-подобных языков. Хотите понимать максимальный круг литературы, написанной для программистов про алгоритмы, дизайн и т.п.? Учите язык Си.

Я самостоятельно выучила 4 языка и поделюсь секретами, которые помогли мне в этом

Ребята, мы вкладываем душу в AdMe.ru. Cпасибо за то,
что открываете эту красоту. Спасибо за вдохновение и мурашки.
Присоединяйтесь к нам в Facebook и ВКонтакте

Всем привет! Меня зовут Кристина, и я самостоятельно выучила 4 языка: белорусский, польский, английский и немецкий. Я веду свой блог kryscina.com о работе и жизни за границей. Благодаря знанию иностранных языков после 8 лет работы в журналистике я самостоятельно освоила профессию бизнес-аналитика. Без знакомств, после 20 собеседований нашла работу в Варшаве. После 8 месяцев изучения немецкого нашла работу в Мюнхене за 17 дней. Сейчас я живу в Регенсбурге (Германия) и воспитываю сына.

Специально для AdMe.ru я расскажу о секретах и лайфхаках, которые неизменно помогают мне при изучении нового языка. Приготовьтесь: это непросто, но результат стоит потраченных усилий.

С чего начать

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

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

И еще один важный момент: при изучении языка у вас не будет выходных. Необходимо полностью окунуться в языковую среду и составить такой график, найти такие упражнения и занятия, чтобы процесс не превратился в скучную и изнуряющую работу. А значит, то, о чем вы читаете / слушаете / смотрите, должно быть вам по-настоящему интересно.

Для себя я выделила 6 основных форм изучения языка. Вот несколько советов и полезных ссылок о том, как наиболее эффективно использовать каждую из них.

1. Смотрите

Здесь вам на помощь придут множество сервисов: YouTube, онлайн-телевидение и онлайн-медиатеки. Рекомендую смотреть как каналы для изучения языка (например, для изучения английского хороши English with Lucy, engVid, ETJ English, EnglishLessons4U), так и включать ролики блогеров, которые будут рассказывать вам о каких-то простых и повседневных вещах, например как они наводят уборку в своем доме или о том, что они готовят на неделю. В таком случае усвоение будет происходить «фоном» и вы начнете привыкать к языку.

Методика изучения языка при помощи фильмов и сериалов у меня примерно такая: сначала смотрю простые сериалы с субтитрами и с Google Translate под рукой, потом — без субтитров, еще позже — сериалы посложнее. У многих стриминговых сервисов встроены субтитры, это удобно. На начальном этапе можно выбирать сериалы, которые вы уже смотрели и, возможно, не один раз, например «Друзья». И важный момент: обязательно отключайте субтитры, когда достигнете определенного уровня понимания! И конечно, нет никакого смысла включать русские субтитры.

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

2. Читайте

Мой фаворит — чтение с помощью читалки Kindle. Если вы учите английский, на Kindle можно скачать англо-русский словарь и тут же подсматривать перевод. Для продвинутых пользователей я рекомендую англо-английский: достаточно нажать на непонятное слово — и появится подсказка с описанием слова из словаря или статья из «Википедии». Для любителей бумажных изданий советую простые журналы вроде кулинарных, комиксы или художественные книги для подростков.

Мое недавнее открытие — сервис Blinkist, который объединяет в себе «читать» и «слушать». Здесь собраны нон-фикшен-книги в сокращенном формате на английском, которые можно также слушать в аудиоформате, параллельно подсматривая в текст. Некоторые книги хочется купить сразу после прослушивания, а на некоторые больше не хочется тратить и минуты — получаются этакие «трейлеры» интересующих книг с пользой для словарного запаса.

3. Слушайте

Необязательно слушать скучные образовательные упражнения. Кому понравятся бесконечные повторения одних и тех же фраз? Найдите для себя радиостанцию по душе или выберите подкаст на интересующую тему. Важно, чтобы тема вам действительно нравилась. Вас интересует мода? А может быть, психология? Найдите об этом подкаст, например через библиотеку iTunes, Spotify или Apple Music. Подкасты удобны тем, что их можно слушать, не напрягаясь, где угодно и когда угодно: во время пробежки, в метро или даже за приготовлением обеда.

И музыка! Конечно же, музыка. Слушайте одну и ту же песню по 20 раз, пока не выучите слова. Напевайте их в машине по дороге на работу. Я использую Spotify на телефоне + Musixmatch с синхронным текстом проигрываемых песен. За компьютером удобнее установить расширение Google Translate в браузере: открываем текст песни, кликаем дважды на каждое непонятное слово — профит. Новые слова можно выписывать — получится комбо для расширения словарного запаса.

4. Играйте

Если вам важна игровая составляющая, вам на помощь придут множество полезных мобильных приложений. Нельзя не упомянуть Lingualeo — с удовольствием использую этот сервис, там можно и читать тексты, и учить новые слова. Мне нравятся и всем известные Duolingo и Busuu. Приложений масса, но самое главное — это регулярность.

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

5. Пишите

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

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

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

6. Говорите, говорите и еще раз говорите

Мои лучшие учителя — дети друзей из Германии: Марлина и Люка с их подружкой Юли.

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

Здорово, если у вас появляется возможность общаться с местными жителями во время путешествий. Лучший для этого способ, конечно, снять жилье через Couchsurfing и Airbnb.

Когда я переехала в Германию, в изучении немецкого мне очень помогли дети. Они чудесные учителя! Дело в том, что их словарный запас примерно равен вашему уровню, они всегда с удовольствием покажут, что имеют в виду, — для них это привычная форма общения лет эдак до 7. Поэтому самые лучшие помощники и мотиваторы для изучения нового языка — маленькие дети, говорящие на нем.

И немного из личного опыта: я решила ввести английский язык для своего ребенка в качестве родного, об этом я подробнее пишу в своем блоге. Мы живем в Германии, муж говорит с малышом по-немецки, а я — по-английски. Мы выбрали такой путь, имея на это собственные причины, и, конечно, я не хочу советовать такой метод всем. Но каждый день я замечаю, что ребенок — лучшая мотивация сделать свою собственную речь идеальной и дотянуть свои знания до native speaker. Дети гораздо быстрее запоминают новую информацию, и, быть может, когда вы достигнете определенных успехов в изучении языка, вам будет интересно обучать ему своих малышей и всегда узнавать что-то новое.

А что вам помогает в изучении иностранных языков?

Помогите с языком C++

Вопрос собственно вот в чем :
(возможно он глуп и прост, но все же)

1. #include
2. #include
3. #include
4.
5. using namespace std;
6.
7. int main()<
8.
9. cout > c;
15.
16.
17. if (c == ‘F’ || c == ‘f’)
18. cout > c;
25. if (c == ‘R’ || c == ‘r’)
26. <
27. cout Лучший ответ

using namespace std;

void main()
<
setlocale(LC_ALL, «rus»);
system(«color 0A»);

int num = 10, dum = 10, tum = 10;
for (;;)
<
char c;
cout Похожие вопросы

Язык программирования Си сложен в изучении?

Тошнит от pascal, около 2-ух месяцев изучаю на нем азы программирования. Хочу начать программировать на языке уровнем пониже. Из известных мне понравился си, но вот спросил у знакомого, а он сказал что си очень сложен. Особенно укаатели, говорил лучше изучать его 3-им или 4-ым по счету. Конечно я понимаю, что с моим багажом знаний я буду быдлокодить по крупному, но программирование мне нравится. Блин так ли он сложен как его знакомый малюет?

Проще только ассемблер.

Тебя скорее от программирования тошнит. Язык C здесь ничем не поможет.

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

На каких языках ты еще программировал?

Что конкретно не нравится?

Что там сложного может быть — его 40 лет назад создали. Сам подумай.

Причина субъективна он приелся. Хочется чего-то нового!

Си и Паскаль практически идентичные языки, разница крайне незначительная.

Чистый C прост в изучении. Чуть-чуть проще, нежели Pascal.

В чем причина неприязни к паскалю? Он у вас до сих пор под DOS?

Переходи на lisp же. Там бездна нового.

как-то так, если правильно помню (давно забросил оба):

Синтаксис, конечно же, зависит от реализации языка.

Нет ну точно под DOS не сижу))) Просто надоел!

Без указателей ты и в Паскале не сможешь создать динамический массив или связанный список.

BTW Есть люди которые понимают этальные когомологии, осилили как-то.

Си очень простой язык. А вот программы писать на нём довольно сложно. Особенно работающие с какими-нибудь структурами данных отличных от массива. Впрочем от паскаля он отличается исключительно синтаксисом и более слабой типизацией и я сомневаюсь что тебя не будет тошнить от C.

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

Процедурщина не может быть сложной.

Я за бан, ибо линакс непричем.

Правильно, паскаль — какашка, он никогда не был предназначен для того, чтобы на нём реально программировали что-то серьёзное. Учи ц.

Если что указатели есть и в Паскале, да. Так что твой знакомый чего-то не знает, походу

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

Гораздо труднее усвоить все нюансы применения. Но это приходит с опытом.

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

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

С — это просто засохший кал, порножурналы с небритыми тетками и пара незарегистрированных стволов наших Отцов. Изучай современные языки типа сишарпа, эфшарпа или кложуры.

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

Те, кто пугает сложностью нормальных языков и отсылает ко всяким Васикам, почему-то вбили себе в голову, будто ступенчатое возрастание сложности — вершина всего. Видимо, неверно обобщили свой школьный опыт. Арифметика идет впереди алгебры только потому, что арифметика — основа алгебры. А Basic — не основа Java, Java — не основа C++. Врачей-студентов не отправляют на первом курсе на мясокомбинат практиковаться в разделке туши. Изучающим русский не скармливают сначала болгарский.

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

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

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

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

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

Язык программирования Си сложен в изучении?

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

Тошнит от pascal, около 2-ух месяцев изучаю на нем азы программирования.

Не может тошнить от Pascal за 2(два!) месяца изучения программирования на нём. Не может. Тебя тошнит либо от программирования вообще, либо от осознания собственного нубства. Pascal тут не при чём, как и C, впрочем, тоже. И если от сверстников ты, первое время, сможешь замаскировать языком C свои неудачи, то позже ты завязнешь в том самом менеджменте памяти и указателях (о которых тебя предупреждал друг) и потеряешь время, необходимое на изучение алгоритмов и прочей дискретной математики. Ты можешь научиться бороться с неудобствами языка программирования C, но так и не научиться программировать. Прикинь, бывает и так.

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

Хочу начать программировать на языке уровнем пониже.

Хватит врать, пиши правду: «нуб, изучаю программирование на Pascal, хочу стать крутым и уважаемым!»

Так, вот, чтоб стать крутым и уважаемым (или богатым) нужно знать алгоритмы и уметь программировать. Ни Pascal, ни C тут не показатель. Кстати, если внимательно посмотришь на историю программирования, то можешь заметить, что многие «крутые» программы (или, даже, хорошо продаваемые операционные системы) были вначале написаны на Pascal (и лишь значительно позже были переписаны на другие ЯП).

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

Короче, учи алгоритмы, <построение, анализ и доказательство алгоритмов>и программирование, а не «крутые» языки программирования, потому, что до ассемблера ты всё-равно не доберёшся (а остальные языки программирования — абстрактное рафинированное фуфло, с той или иной степенью абстракции).

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

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

А вообще пора то ли тему прикрепить по поводу выбора ЯП, то ли отдельный форум сделать.

Правильно, паскаль — какашка, он никогда не был предназначен для того, чтобы на нём реально программировали что-то серьёзное. Учи ц.

Мальчик, ты — категоричный и необразованный дебил. По статистике, Паскаль — самый успешный язык программирования стартапов. Одна MS Windows чего только стоит.

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

А теперь давай представим, как тебя тошнило бы от так горячо любимого и уважаемого тобой ассемблера? Ты же программист по сути — смоделируй ситуацию: ты в школе начинаешь изучать программирование с универсального ассемблера. Не тошнит?

(ты же не собираешься сейчас спорить об универсальности ассемблера?)

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

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

А вообще пора то ли тему прикрепить по поводу выбора ЯП, то ли отдельный форум сделать.

Нефиг отделяться. Пусть профи, типо тебя, помнят откуда они родом! :D

А теперь давай представим, как тебя тошнило бы от так горячо любимого и уважаемого тобой ассемблера?

Ты меня с кем то перепутал, в жизни ни строки не написал на асме.

(ты же не собираешься сейчас спорить об универсальности ассемблера?)

Что есть универсальность?;-)

ты ему сразу выбор под нос суёшь

Да! Добро пожаловать в большой мир;-)

Пусть профи, типо тебя, помнят откуда они родом! :D

Я вообще c программируемого калькулятора начинал;-)

Дай догадаюсь, в паскале тебе не нравятся begin и end?

Хочу начать программировать на языке уровнем пониже.

У тебя наверное какое-то своё определение слова «уровень».

Ты меня с кем то перепутал, в жизни ни строки не написал на асме.

Т.е. ты не связан с числодробилками и никогда не советовал смотреть gcc -S в случае чего?

Началось. Вот этого я и боялся.

Странный у тебя мир — подстава на подставе. А если бы ему LISP больше подошёл, а ты ему C разрекламировал и впарил?

Я вообще c программируемого калькулятора начинал;-)

Т.е. ты не связан с числодробилками и никогда не советовал смотреть gcc -S в случае чего?

Связан, советовал, но асма не знаю. Выхлоп там и так понятен.

А если бы ему LISP больше подошёл, а ты ему C разрекламировал и впарил?

Си лишпу не помеха! Все равно лишперы фрагменты С-шного кода регулярно юзают.

БЗ-32. Когда отец принес на ночь MK-64 я смог сделать 2D посадку на луну;-)

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

А ещё есть диалекты типа SmallC, TinyC, но они вообще на любителя, типа меня.

Блин, напомни, что это? В голове вертится, вспомнить не могу, противно.

Си лишпу не помеха! Все равно лишперы фрагменты С-шного кода регулярно юзают.

А всё потому, что в мире Unix/Linux язык программирования C — практически, как ассемблер. И, например, возня с низкоуровневым менеджментом памяти способна убить всё удовольствие от изучения более-менее сложных алгоритмов и программирования вообще.

БЗ-32. Когда отец принес на ночь MK-64 я смог сделать 2D посадку на луну;-)

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

Когда отец принес на ночь MK-64 я смог сделать 2D посадку на луну;-)

Русский язык в консоли C++

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

К примеру, если мы напишем такой код на С++

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

Если же мы будем использовать функцию setlocale() внутри функции main()

То получим вместо иероглифов нормальный русский шрифт, вуаля:

Также, можно опустить последний аргумент функции — setlocale(LC_ALL, «Russian»); можно заменить на setlocale(0, «»); — работоспособность программы от этого не изменится.

Обучение программированию с нуля: с чего начать изучение в домашних условиях

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

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

Что нужно знать «чайнику»

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

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

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

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

Особенности обучения программированию на постсоветском пространстве

После развала СССР все отечественные ВУЗы долгое время даже и не пытались перекроить свою систему обучения под потребности современного рынка. Не являлись исключением из этого правила и технические ВУЗы.

Программирования как отдельной отрасли и специализации не существовало как таковой. Его основы преподавались лишь как привязка к другим инженерным дисциплинам. И даже те крохи знаний, которые давались студентам в этой области, не соответствовали современным стандартам и утратили свою актуальность еще 20-30 лет назад.

Ситуация кардинально не изменилась и через 10 лет. Лишь некоторые учебные заведения, учуяв веяния нового времени, в начале двухтысячных года начали перекраивать свое обучение под мировые стандарты. И только с этого момента программирование стало восприниматься как отдельная профессия и специализация обучения:

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

А это в профессии программиста является наиболее важным аспектом. Поэтому большинство из сегодняшних гуру российской IT-индустрии начинали свое обучение программированию с нуля самостоятельно.

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

С какого языка начать изучать программирование

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

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

Чаще всего выбор падает на язык программирования C ( си) . Именно с него большинство новичков во всем мире начинают свое обучение. На основе C было создана основная часть программных языков, и во многом они наследуют его структуру и синтаксис.

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

  • Простая для понимания основа – часть встроенных возможностей языка для простоты вынесена в отдельно подключаемые библиотеки. К таким элементам относится большая часть математических функций и методов для работы с файловой системой;
  • Оптимально подогнанная система типов – благодаря простому набору типов данных и строгой типизации уменьшается риск допущения ошибок в процессе написания программного кода;
  • Направленность C на процедурный тип программирования, при котором соблюдается четкая иерархия всех элементов кода;
  • Доступ к памяти машины с помощью указателей;
  • Минимальное количество поддерживаемых ключевых слов;
  • Поддержка области действия имен;
  • Поддержка пользовательских типов данных ( объединения и структуры ).

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

Программы (компиляторы) для программирования

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

Вот несколько специализированных компиляторов с поддержкой языка C:

  • Microsoft Visual Studio – профессиональный инструмент, поддерживающий множество языков, в том числе и несколько серверных. Подойдет для новичков, если брать его «на вырост»:
  • Borland C++ — бесплатный компилятор, идеально подходящий для начинающего обучение. В отличие от предыдущего инструмента, отличается ясным и понятным интерфейсом. Поэтому его освоение не вызовет особых трудностей даже при самостоятельном освоении азов программирования:
  • Code::Blocks – бесплатная среда разработки, поддерживающая написание кода на нескольких языках. Средний по сложности освоения вариант:

Что касается специализированной литературы, то советовать книги определенных авторов мы не будем. Тут, как говорится, выбирайте, что душе угодно. Потому что в большинстве случаев подбор самоучителя по программированию – это индивидуальный процесс. Используйте тот источник, который больше подходит именно для вас.

Да и в интернете можно найти очень много информации. Например, на нашем сайте специализированной литературе по IT тематике посвящен целый раздел.

Тенденции на рынке программирования

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

  • Веб-программирование – здесь понадобятся знания PHP , CSS и HTML ;
  • Разработка приложений под мобильную операционную систему Andro >Java . Поэтому потребуется знание основ этого языка;
  • C# (си sharp) – дальний потомок C . На основе C# построена веб-технология ASP.net от Microsoft .

И последний совет всем начинающим. Перед тем, как приступить к обучению программированию с нуля, следует запастить терпением. А также: таблетками от головной боли, кофе, чаем и побрить череп наголо. Потому что во время постижения программных наук, обучающиеся часто вырывают волосы со своей головы вместе с корнем. Удачного старта!

Цукерберг рекомендует:  Профессия - Как заинтересовать подростка изучать программированиеIT
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих