RUЭВМ
Вы хотите отреагировать на этот пост ? Создайте аккаунт всего в несколько кликов или войдите на форум.
Апрель 2024
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
2930     

Календарь Календарь

Последние темы
» Вити больше нет!
автор bug19 Пн Фев 20 2023, 19:54

» Собираем оригинальный Орион 128
автор bug19 Пн Фев 20 2023, 19:47

» Проблема плющеного экрана ОРИОНА
автор kanzler Пн Ноя 28 2022, 12:05

» Орион 128 и его клоны возрождение 2019-2022 год
автор kanzler Пн Ноя 28 2022, 12:03

» Электроника КР-04. Информация, документы, фото.
автор kanzler Пн Ноя 28 2022, 12:02

» Новости форума
автор kanzler Пн Ноя 28 2022, 11:52

» Орион-128 НГМД запуск 2021 года
автор matrixplus Сб Сен 10 2022, 17:36

» ПЗУ F800 для РК86
автор ведущий_специалист Сб Сен 10 2022, 10:37

» Микропроцессорная лаборатория "Микролаб К580ИК80", УМК-80, УМПК-80 и др.
автор Электротехник Вт Июл 26 2022, 19:33

» Орион-128 SD карта в Орионе
автор matrixplus Чт Июн 02 2022, 09:00

» 7 Мая. День Радио!
автор Viktor2312 Чт Май 12 2022, 10:58

» Серия: Массовая радио библиотека. МРБ
автор Viktor2312 Ср Май 11 2022, 12:17

» Полезные книги
автор Viktor2312 Пн Май 09 2022, 15:07

» Орион 128 Стандарты портов и системной шины Х2
автор matrixplus Вс Май 08 2022, 23:08

» Орион-128 и Орион ПРО еще раз про блоки питания
автор matrixplus Вс Май 08 2022, 19:09

» Орион-128 Программаторы
автор matrixplus Вс Май 08 2022, 19:02

» Орион ПРО история сборки 2021 до 2022
автор matrixplus Вс Май 08 2022, 18:47

» Анонсы монет (New coin).
автор Viktor2312 Сб Май 07 2022, 23:11

» Хочу свой усилок для квартиры собрать не спеша
автор Viktor2312 Сб Май 07 2022, 19:33

» Амфитон 25у-002С
автор Viktor2312 Сб Май 07 2022, 09:38

» Майнер: T-Rex
автор Viktor2312 Вс Май 01 2022, 09:12

» GoWin. Изучение документации. SUG100-2.6E_Gowin Software User Guide. Среда разработки EDA.
автор Viktor2312 Пн Апр 25 2022, 01:01

» GoWin. Изучение документации. UG286-1.9.1E Gowin Clock User Guide.
автор Viktor2312 Сб Апр 23 2022, 18:22

» GoWin. Documentation Database. Device. GW2A.
автор Viktor2312 Ср Апр 20 2022, 14:08

» GOWIN AEC IP
автор Viktor2312 Ср Апр 20 2022, 12:08

Самые активные пользователи за месяц
Нет пользователей

Поиск
 
 

Результаты :
 


Rechercher Расширенный поиск


Пустая тема. Тема буфер.

Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Чт Дек 03 2020, 02:41

1
Операторы.

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


Арифметические операторы.

Таблица: Арифметические операторы
Пустая тема. Тема буфер. 9ed_0063

Таблица перечисляет допустимые арифметические операторы С. Операторы +, —, * и / работают в С точно так же, как и в большинстве других языков. Их можно применять практически ко всем встроенным типам данных. Когда применяется / к целому числу или символу, остаток обрубается, например: 10/3 равно 3.

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

int х, у;
х = 10;
у = 3;
printf("%d", x/y); /* выводит 3 */
printf ("%d", х%у); /* выводит 1 - остаток целочисленного деления */

x = 1;
y = 2;
printf("%d %d", х/у, х%у)/ /* выводит 0 1*/

Причина того, что последняя строка печатает 0 и 1, заключается в том, что в результате целочисленного деления 1/2 получается 0 с остатком 1. 1 % 2 выдаёт остаток 1.

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


Увеличение и уменьшение.

С предоставляет два полезных оператора, обычно отсутствующих в других языках. Это операторы уменьшения и увеличения, -- и ++. Оператор ++ добавляет 1 к операнду, а -- вычитает 1. Поэтому следующие операторы эквивалентны:

х = х + 1;

это то же самое, что и

++ х;

Аналогично

х = х - 1;

это то же самое, что и

--х;

Как оператор увеличения, так и оператор уменьшения могут стоять перед операндом (префиксный) или после операнда (постфиксный). Например:

х = х + 1;

может быть записано как

++ х;

или

х ++;

Тем не менее, существует разница использования префиксного и постфиксного операторов в выражениях. Когда оператор увеличения или уменьшения стоит перед операндом, С производит увеличение или уменьшение до получения значения операнда. Если оператор следует за операндом, С получает значение операнда перед его увеличением или уменьшением. Рассмотрим следующий пример:

х = 10;
у = ++x;

В этом случае у устанавливается в значение 11. А если записать это как

х = 10;
у = x++;

то y будет иметь значение 10. В обоих случаях х устанавливается в 11. Бывает необходимо контролировать последовательность операций увеличения или уменьшения.

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

высший + (унарный плюс) - (унарный минус) ++ -- * / %
низший + - (бинарные операторы)

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


Операторы отношения и логические операторы.

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

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

Таблица: Операторы отношения и логические операторы
Пустая тема. Тема буфер. 9ed_0064

Таблица показывает операторы отношения и логические операторы. Таблица истинности для логических операторов образована с использованием на входах 1 и 0:
Пустая тема. Тема буфер. 9ed_0065

Как операторы отношения, так и логические операторы имеют более низкий приоритет по сравнению с арифметическими операторами. Это означает, что выражение типа 10 > 1+12 вычисляется как 10 > (1 + 12). Результатом, естественно, будет ложь.

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

10 > 5 && 1(10 < 9) || 3 <= 4

в результате чего получаем истину.

Ниже показаны приоритеты выполнения операторов отношения и логических операторов:

высший ! > >= < <=  &&
низший ||

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

! 1 && 0

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

! (1 && 0)

то получится истина.

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


int x;
x = 100;
printf("%d", x > 1);


Битовые операторы.

В противоположность большинству языков, С поддерживает все существующие битовые операторы. Поскольку С создавался, чтобы заменить ассемблер, то была необходимость поддержки всех (или по крайней мере большинства) операций, которые может выполнить ассемблер. Битовые операции — это тестирование, установка или сдвиг битов в байте или слове, которые соответствуют стандартным типам языка С char и int. Битовые операторы не могут использоваться с float, double, long double, void и другими сложными типами. Таблица содержит имеющиеся операторы.

Таблица. Битовые операторы:
Пустая тема. Тема буфер. 9ed_0066

Битовые операторы И, ИЛИ, НЕ используют ту же таблицу истинности, что и их логические эквиваленты, за тем исключением, что они работают по-битно. Исключающее ИЛИ имеет следующую таблицу истинности:

Пустая тема. Тема буфер. 9ed_0067

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

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

Битовое И чаще всего используется для выключения битов То есть любой бит, установленный в 0, вызывает установку соответствующего бита в Другом операнде также в 0. Например, следующая функция читает символы из порта модема, используя функцию read_modem(), и сбрасывает бит четности в 0.

char get_char_from_modem(void)
{
char ch;
ch = read_modem (); /* получение символа из порта модема * /
return (ch & 127);
}

Чётность отображается восьмым битом, который устанавливается в 0 с помощью битового И, поскольку биты с номерами от 1 до 7 установлены в 1, а бит с номером 8 — в 0. Выражение ch & 127 означает, что выполняется битовая операция И между битами переменной ch и битами числа 127. В результате получим ch со сброшенным старшим битом. В следующем примере предполагается, что ch имеет символ 'А' и имеет бит чётности:

Пустая тема. Тема буфер. 9ed_0068

Битовое ИЛИ может использоваться для установки битов. Любой бит, установленный в любом операнде, вызывает установку соответствующего бита в другом операнде. Например, в результате операции 128 | 3 получаем:

Пустая тема. Тема буфер. 9ed_0069

Исключающее ИЛИ или как его ещё называют, XOR, устанавливает бит, если соответствующие биты в операндах отличаются. Например, в результате операции 127 ^ 120 получаем:

Пустая тема. Тема буфер. 9ed_0070

В общем, битовые И, ИЛИ и исключающее ИЛИ операции применяются к каждому биту переменной. Поэтому битовые операторы обычно не используются в условных операторах, которыми являются операторы отношения и логические операторы. Например: если х содержит 7, то х && 8 выдаст 1, в то время как х & 8 выдаст 0.

ПАМЯТКА: Операторы отношений и логические операторы всегда в качестве результата выдают 0 или 1, в то время как аналогичные им битовые операторы могут создать любое число в соответствии с их работой, другими словами, битовые операторы могут создать значения, отличные от 0 или 1, тогда как логические операторы всегда выдают 0 или 1.

Операторы сдвига >> и << сдвигают биты в переменной вправо и влево на указанное число. Общий вид оператора сдвига вправо:

переменная >> число сдвигов

а общий вид оператора сдвига влево:

переменная << число сдвигов

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

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

Пустая тема. Тема буфер. 9ed_0071

Оператор дополнение, ~, инвертирует состояние каждого бита указанной переменной, то есть 1 устанавливается в 0, а 0 — в 1.

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

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

Можно использовать показанную ниже функцию encode() для кодирования символа:

/* Простейшая шифрующая функция */

char encode(code ch)
{
return(~ch); /* дополнение */
}

***


.

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Пт Дек 04 2020, 01:58

2
Оператор ?

С имеет очень мощный оператор, который можно использовать вместо структуры if-then-else. Оператор ? имеет следующий вид:

выражение1 ? выражение2 : выражение3;

где выражение1, выражение2 и выражениеЗ - это выражения.

Оператор ? работает следующим образом: вычисляется выражение1; если оно истинно, то вычисляется выражение2 и всё выражение получает это значение; а если оно ложно, то вычисляется выражение3 и всё выражение получает это значение. Например:

х = 10;
у = х > 9 ? 100 : 200;

В данном примере у получает значение 100. Если бы х было меньше, чем 9, то у получило бы значение 200. Ниже приведен фрагмент программы, выполняющий такие же действия, но с использованием операторов if/else:

х = 10;
if (х > 9) у = 100;
else у = 200;

Для того, чтобы закрепить это на практике, и заодно проверить работоспособность, и потренироваться, вспомнить работу %d, работу printf и т. д. Напишем коротенькую программку, откомпилируем её и посмотрим результат:

Код программы:

#include <stdio.h>

int per_1;
int per_2;

int main(void){
per_1 = 10;
per_2 = per_1 > 9 ? 100 : 200;
printf ("\n");
printf ("%d\n", per_2);

per_1 = 3;
per_2 = per_1 >9 ? 100 : 23 + 7;
printf ("\n");
printf ("%d\n", per_2);
printf ("\n");

return (0);
}

В начале программа должна перевести каретку, после чего напечатать число 100, так как per_1 у нас равен 10, а оно больше 9. Потом снова перевести каретку и во втором случае так как per_1 не больше 9 и результат будет "лож" то есть 0, то должно вычислиться 23 + 7 и результат присвоиться переменной per_2 и напечататься 30, после чего опять произойдёт перевод каретки и программа закончится.

Результат работы:

Пустая тема. Тема буфер. 9ed_0072


Операторы указания & и *.

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

  1. Предоставляют быстрое обращение к элементам массива.

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

  3. Поддерживают динамические структуры данных, например списки.

Оператор &. Это унарный оператор, возвращающий адрес операнда в памяти. (Унарному оператору требуется только один операнд.) Например:

m = &count;

помещает в m адрес переменной count. Это адрес внутреннего местоположения переменной в компьютере. С самим значением переменной ничего не делается. Оператор & можно запомнить как «взятие адреса». Поэтому вышеупомянутый оператор присваивания можно прочитать как «m получает адрес count».

Для лучшего понимания данного присваивания предположим, что переменная count находится по адресу 2000. Также предположим, что count имеет значение 100. После данного присваивания m будет содержать 2000.

Оператор *, дополняющий &. Это унарный оператор, возвращающий значение переменной по указанному адресу. Например: если m содержит адрес переменной count, то

q = *m;

помещает значение count в q. Следуя вышеприведённому примеру, q получит значение 100, поскольку 100 хранилось по адресу 2000 - адресу, находящемуся в переменной m. Операция * может быть запомнена как «по адресу». В данном случае оператор можно прочитать как «q получает значение по адресу m».

К несчастью, значки для умножения и для взятия «по адресу» - одинаковы, впрочем как и значки битового И и «взятие адреса». Эти операторы не имеют связи друг с другом. Как & так и * имеют более высокий приоритет по сравнению с остальными арифметическими операциями, за исключением унарного минуса, имеющего такой же приоритет.

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

char *ch;

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

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

int х, *у, count;

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

Ниже операторы * и & используются для занесения числа 10 в переменную target:

#include <stdio.h>

/* присвоение с помощью * и & */

int main(void)

{
int target, source;
int *m;

source = 10;
m = &source;
target = *m;

printf("%d", target);

return 0;
}

Добавив в код нашего примера выше и этот код:

Пустая тема. Тема буфер. 9ed_0073

Получим результат, старые наши 100, 30 и дополнительно 10.

Пустая тема. Тема буфер. 9ed_0074

***


.

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Вт Дек 08 2020, 21:42

3
Оператор sizeof

sizeof - это унарный оператор, возвращающий длину в байтах переменной или типа, помещенных в скобки. Например:

float f;
printf("%f ", sizeof f);
printf("%d", sizeof(int));

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

Использование sizeof помогает создавать переносимый код для тех случаев, когда код зависит от размера стандартных типов данных С. Например, представим, что программе, работающей с базой данных, необходимо сохранять 6 целочисленных значений в записи. Для того, чтобы сделать эту программу переносимой, не следует предполагать, что размер целочисленного типа - 2 или 4 байта, следует самостоятельно определить настоящую длину, используя sizeof.

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


#include <stdio.h>

int main(void){
printf ("char                   - "); printf ("%d", sizeof(char)); printf (" Byte\n\n");
   printf ("unsigned char          - "); printf ("%d", sizeof(unsigned char)); printf (" Byte\n\n");
   printf ("signed char            - "); printf ("%d", sizeof(signed char)); printf (" Byte\n\n");
   printf ("int                    - "); printf ("%d", sizeof(int)); printf (" Byte\n\n");
   printf ("unsigned int           - "); printf ("%d", sizeof(unsigned int)); printf (" Byte\n\n");
   printf ("signed int             - "); printf ("%d", sizeof(signed int)); printf (" Byte\n\n");
   printf ("short int              - "); printf ("%d", sizeof(short int)); printf (" Byte\n\n");
   printf ("unsigned short int     - "); printf ("%d", sizeof(unsigned short int)); printf (" Byte\n\n");
   printf ("signed short int       - "); printf ("%d", sizeof(signed short int)); printf (" Byte\n\n");
   printf ("long int               - "); printf ("%d", sizeof(long int)); printf (" Byte\n\n");
   printf ("unsigned long int      - "); printf ("%d", sizeof(unsigned long int)); printf (" Byte\n\n");
   printf ("signed long int        - "); printf ("%d", sizeof(signed long int)); printf (" Byte\n\n");
   printf ("float                  - "); printf ("%d", sizeof(float)); printf (" Byte\n\n");
   printf ("double                 - "); printf ("%d", sizeof(double)); printf (" Byte\n\n");
   printf ("long double            - "); printf ("%d", sizeof(long double)); printf (" Byte\n\n");
   printf ("\n\n\n\n\n\n");

return (0);
}

Как она выглядит в редакторе компилятора:

Пустая тема. Тема буфер. 9ed_0114

И результат её работы:

Пустая тема. Тема буфер. 9ed_0115


Оператор «запятая».

Оператор «запятая» используется для связки нескольких выражений. Левая сторона оператора «запятая» всегда вычисляется как void (то есть не выдающее значения). Это означает, что значение выражения, находящегося с правой стороны, станет значением разделённого запятыми выражения. Например:

х = (у = 3, у + 1);

Сначала присваивается 3 переменной у, а затем 4 переменной х. Скобки необходимы, поскольку оператор «запятая» имеет более низкий приоритет по сравнению с оператором присваивания.

Оператор «запятая» вызывает выполнение последовательности действий. Когда он используется с правой стороны оператора присваивания, то присваиваться будет значение последнего выражения, стоящего в разделенном запятыми списке. Ниже приведён еще один пример:

у = 10;

х = (у = у - 5, 25 / у);

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

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


Операторы [ ] u ()

В С круглые скобки предназначены для изменения приоритета выполнения операторов.

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

#include <stdio.h>

char t[80];

int main(void)
{
t[3] = 'X';
printf("%c", t[3]);
return 0;
}

сначала присваивается значение 'X' четвёртому элементу (надо помнить, что индексация массивов в С начинается с 0) массива t, а затем печатается этот элемент.


Приоритеты в С.

Таблица. Приоритеты операторов:
Пустая тема. Тема буфер. 9ed_0116

Таблица содержит приоритеты всех операторов в С. Следует обратить внимание, что все операторы, кроме унарных операторов и оператора ?, вычисляются слева направо. Унарные операторы (*, &, -) и оператор ? вычисляются справа налево.

***

...

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Ср Дек 09 2020, 10:28

4
Выражения.

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


Преобразование типов в выражениях.

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

  1. Все переменные типа char и short int преобразуются к типу int. Все переменные типа float преобразуются к типу double.

  2. Если один из пары операндов имеет тип long double, другой операнд также преобразуется к long double.
    Иначе если один из операндов имеет тип double, другой операнд также преобразуется к double.
    Иначе если один из операндов имеет тип long, другой операнд также преобразуется к long.
    Иначе если один из операндов имеет тип unsigned, другой операнд также преобразуется к unsigned.

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

Пустая тема. Тема буфер. 9ed_0117

Сначала символ ch преобразуется к целому, а вещественная переменная с одинарной точностью f преобразуется к double. Затем ch / i преобразуется к double, поскольку f * d имеет тип double. Конечный результат имеет тип double, поскольку оба операнда типа double.


Принудительные преобразования.

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

(тип) выражение

где тип - это один из стандартных типов данных С или определяемый пользователем тип. Например, если необходимо, чтобы выражение х / 2 имело тип float (остаток сохранится), следует написать:

(float) х / 2

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

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

#include <stdio.h>

/* выводит i и i/2 с дробной частью */

int main (void)
{
int i;
for(i=1; i<=50; ++i )
printf ("%d / 2 is: %f\n", i, (float) i/2);
return 0;
}

Пустая тема. Тема буфер. 9ed_0118

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

Пустая тема. Тема буфер. 9ed_0119

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


Пробелы и круглые скобки.

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

х=10/у~(127/х);

х = 10 / у ~ (127 / х) ;

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

х=у/3-34*temp&127;

или

х = (у / 3) - ((34 * temp) & 127);


Сокращённые операторы в С.

С имеет несколько специальных сокращённых операторов, кодирующих некоторые операторы присваивания. Например:

х = х + 10;

может быть кратко записано как

х += 10;

Оператор += сообщает компилятору, что необходимо присвоить переменной х старое значение x плюс 10.

Это сокращение работает для всех бинарных операторов в С (где требуется два операнда). Стандартная форма сокращений следующая:

переменная = переменная оператор выражение;

то же самое, что и

переменная оператор = выражение;

В другом примере

х = х - 100;

записывается как

х -= 100;

Сокращённая нотация широко используется при профессиональном написании программ, и следует хорошо с ней разобраться.

***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Чт Дек 10 2020, 00:57

5
Операторы управления программой.

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

  1. Итерационные операторы - это while, for и do/while. Они чаще всего называются циклами.

  2. Операторы выбора или условные операторы - это if и switch.

  3. Операторы перехода - это break, continue и goto. (Оператор return, в принципе, также является оператором перехода, поскольку он воздействует на программу.)

Функция exit()  она также влияет на выполнение программы.


Истина и ложь в С.

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


Операторы выбора.

С поддерживает два типа оператора выбора: if и switch. Кроме этого, оператор ? является альтернативой оператору if.


IF

Стандартная форма оператора if следующая:

if (выражение) оператор;
else оператор;

где оператор может быть или простым, или составным. (Надо помнить, что в С составной оператор -это группа операторов, заключенных в фигурные скобки.) Оператор else не обязателен. Стандартная форма оператора if с составными операторами следующая:

if (выражение) {
последовательность операторов
}

else {
последовательность операторов
}

Если выражение истинно (любое значение, кроме 0), выполняется блок операторов, следующий за if; иначе выполняется блок операторов, следующих за else. Всегда выполняется код ассоциированный или с if или с else, но никогда не выполняются оба кода одновременно.

Рассмотрим следующую программу, являющуюся простейшим вариантом игры «угадай число». Она печатает сообщение «**Rignt**», когда игрок угадывает число.

#include <stdio.h>

/* программа "угадай число" */

int main(void){
int magic = 123; /* искомое число */
int guess;
printf ("Enter your guess: ");
scanf ("%d", &guess);
if (guess == magic) printf("\n\n** Right **\n\n");
return 0;
}

Пустая тема. Тема буфер. 9ed_0120

Отображение работы программы:

Пустая тема. Тема буфер. 9ed_0121

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

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

#include <stdio.h>

/* программа "угадай число" */

int main(void){
int magic = 123; /* искомое число */
int guess;
printf ("Enter your guess: ");
scanf ("%d", &guess);
if (guess == magic) printf("\n\n** Right **\n\n");
else printf("\n\n.. Wrong ..\n\n");

return 0;
}

Пустая тема. Тема буфер. 9ed_0122

И результат её работы, при неправильном числе:

Пустая тема. Тема буфер. 9ed_0123


Вложенные if

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

if (x)

   if (у) printf("1");

  else printf("2");

Какому if соответствует какое else?

К счастью, С предоставляет очень простое правило для разрешения такого рода проблем. В С else соответствует ближайшему предшествующему if (на том же уровне видимости), еще не имеющему оператора else. В данном случае else связан с оператором if (у). Для того, чтобы связать else с оператором if (х), следует использовать фигурные скобки, как показано ниже:
f (x) {
   if (у) printf ("1");
}
else printf ("2");

Теперь else связано с if (x), поскольку он не принадлежит больше блоку if (у). Из-за правил видимости С else теперь не знает об операторе if (у), поскольку он находится на другом уровне.

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

#include <stdio.h>

/* программа "угадай число" */

int main(void){
int magic = 123; /* искомое число */
int guess;
printf ("Enter your guess: ");
scanf ("%d", &guess);
if (guess == magic){
   printf("\n\n** Right **\n\n");
   printf("%d is the magic number\n\n\n\n", magic);
}
else{
printf("\n\n.. Wrong ..\n\n");
   if(guess > magic) printf("Too high\n\n\n\n");
   else printf("Too low\n\n\n\n");
}

return 0;
}

Пустая тема. Тема буфер. 9ed_0124

Результат работы программы, при правильно введённом числе:

Пустая тема. Тема буфер. 9ed_0125

Результат работы программы, если введённое число больше правильного:

Пустая тема. Тема буфер. 9ed_0126

Результат работы программы, если введённое число меньше правильного:

Пустая тема. Тема буфер. 9ed_0127


Лесенка if-else-if

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

if (выражение)
оператор;
else if (выражение)
оператор;
else if (выражение)
оператор;

...

else
 оператор;

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

#include <stdio.h>

/* программа "угадай число 5" */

int main(void)
{
int magic = 5; /* искомое число */
int guess;

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

if (guess == magic){
   printf ("\n\n** Right **\n\n");
   printf ("%d is the magic number\n\n\n\n", magic);
}
else if(guess > magic)
printf ("\n\nWrong. Too high\n\n\n\n");
   else printf ("\n\nWrong. Too low\n\n\n\n");

return 0;
}

Пустая тема. Тема буфер. 9ed_0128

Результат работы программы, при правильно введённом числе:

Пустая тема. Тема буфер. 9ed_0129

Результат работы программы, если введённое число больше правильного:

Пустая тема. Тема буфер. 9ed_0130

Результат работы программы, если введённое число меньше правильного:

Пустая тема. Тема буфер. 9ed_0131


Оператор ? подробнее.

Оператор ? может использоваться для замены стандартной конструкции if/else:

if (условие) выражение;

else выражение;

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

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

выражение1 ? выражение2 : выражение3

где выражение1, выражение2 и выражение3 - это выражения.

Оператор ? работает следующим образом. Вычисляется выражение1. Если оно истинно, вычисляется выражение2 и вся конструкция получает вычисленное выражение. Если выражение1 ложно, вычисляется выражение3 и вся конструкция получает вычисленное выражение. Например:

х = 10;

у = х > 9 ? 100 : 200;

В данном примере у получает значение 100. Если бы х было меньше, чем 9, то у получило бы значение 200. Ниже приведен фрагмент программы, выполняющий такие же действия, но с использованием операторов if/else:

х = 10;

if (х > 9) у = 100;

else у = 200;

Используя оператор ?, возможно переписать нашу программу следующим образом:

#include <stdio.h>

/* программа "угадай число 5" */

int main(void)
{
int magic = 5; /* искомое число */
int guess;

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

if (guess == magic){
   printf ("\n\n** Right **\n\n");
   printf ("%d is the magic number\n\n\n\n", magic);
}
else
   guess > magic ? printf("\n\nHigh\n\n") : printf("\n\nLow\n\n") ;

return 0;
}

Здесь оператор ? приводит к выводу сообщения, основываясь на сравнении guess > magic.

***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Чт Дек 10 2020, 12:18

6
Оператор принятия решений switch

Хотя конструкция if-else-if может выполнять многочисленные проверки, она не очень элегантна. Код очень труден для восприятия и в нём может запутаться даже автор через некоторое время. С этой целью С имеет оператор принятия решений switch, выполняющий действия, основываясь на сравнении значения со списком констант символов или целых чисел. При обнаружении совпадения выполняется оператор или операторы, ассоциированные с данным значением. Оператор switch имеет следующий вид:

switch (выражение) {
case константа1:
последовательность операторов
break;
case константа2:
последовательность операторов
break;
case константа3:
последовательность операторов break;
...
default:
последовательность операторов
}

Оператор default выполняется, если не найдено соответствий, default необязателен и, если его нет, то в случае отсутствия совпадений ничего не происходит. Когда обнаруживается совпадение, операторы, ассоциированные с соответствующим case, выполняются до тех пор, пока не встретится оператор break. В случае default (или последнего case, если отсутствует default), оператор switch заканчивает работу при обнаружении конца.

Можно представить в более наглядной и понятной форме, например, так:

Пустая тема. Тема буфер. 9ed_0132

Следует знать о трех важных моментах оператора switch:

  1. switch отличается от if тем, что он может выполнять только операции проверки строгого равенства, в то время как if может вычислять логические выражения и отношения.

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

  3. Если в операторе switch используются символьные константы, они автоматически преобразуются к целочисленным значениям.


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

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

Так же можно иметь пустые условия. И выполнение переходит к следующему case, если отсутствует break.

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

/* неверно */

switch(с) {
case 1:
    int t;
...

Тем не менее переменная может быть добавлена:

/* верно */
switch(с) {
int t;
case 1:
...

Имеется возможность создания блока кода как одного из операторов в последовательности и объявление в нём переменной, как показано ниже:

/* Это также корректно */
switch (с) {
case 1:
{ /* create a block */
int t;
...
}


Вложенные операторы switch

Оператор switch может иметь среди последовательности операторов другой оператор switch. Даже если константы case внутреннего и внешнего операторов имеют одинаковые значения, не возникнет никакого конфликта. Следующий фрагмент кода совершенно корректен:

switch (х) {
case 1:
    switch(у) {
         case 0: printf("Divide by zero error.");
                      break;
          case 1: process(x,y);
      }
      break;
case 2:

...

***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Пт Дек 11 2020, 06:30

7
Циклы.


FOR

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

Стандартный вид цикла for следующий:

for (инициализация; условие; увеличение) оператор;

Оператор for имеет три главные части:

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

  2. Условие - это место, где находится выражение, определяющее условие работы цикла.

  3. Увеличение - это место, где определяется характер изменения переменной цикла на каждой итерации.

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

В нижеприведенном простом примере осуществляется вывод чисел от 1 до 25 включительно:

#include <stdio.h>

int main(void)
{
int x;
for(x=1; x<=25; x++) printf("%d ", x);
printf ("\n\n");

return 0;
}

Пустая тема. Тема буфер. 9ed_0137

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

Пустая тема. Тема буфер. 9ed_0138

В программе переменная x изначально установлена в 1. Поскольку х меньше 25, вызывается printf(), после чего х увеличивается на 1 и проверяется условие: по-прежнему ли х меньше либо равно 25. Данный процесс продолжается до тех пор, пока х не станет больше 25, и в этот момент цикл прервётся. В данном примере х является переменной цикла, которая изменяется и проверяется на каждой итерации цикла.

Ниже приведен пример цикла for, повторяющего несколько операторов:

#include <stdio.h>

int main(void){

int x;
float z;

for(x = 90; x != 45; x = x - 5){
z += 0.1;
printf ("The square root of %d, %f\n", x, z);
}
   printf ("\n\n");

return 0;
}

Пустая тема. Тема буфер. 9ed_0139

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

Пустая тема. Тема буфер. 9ed_0140

Как z += 0.1; так и printf(), вызываются и выполняются, пока х не равно 45. Обратим внимание, что в цикле переменная х уменьшается: сначала она получает значение 90 и на каждой итерации Цикла происходит уменьшение на 5.

Важно понять, что в цикле for проверка условия выполняется в самом начале. Это означает, что код в цикле может вообще не выполняться, если условие изначально ложно. Например:

x = 10;
for (у = 10; у != х; ++у) printf ("%d", у);

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


Вариации цикла for

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

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

for (х = 0, у = 0; х + у < 10; ++х)
{
scanf("%d", &у);

...

}

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

Ещё один интересный момент цикла for - это необязательность наличия какой-либо части. Практически можно опустить любую часть. Например, следующий цикл работает до тех пор, пока не будет введено 123:

for (х=0; х != 123; ) scanf ("%d", &х);

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


Бесконечный цикл.

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

for ( ; ; ) printf(" this loop will run forever. \n");

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

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

for ( ; ; )
{
ch = getchar(); /* ввод символа */
if (ch == 'A') break; /* выход из цикла */
}
printf("you typed an A");

Цикл будет работать до тех пор, пока на клавиатуре не будет набрана А.


Циклы for без тела.

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

Следующий пример показывает, как создать задержку с помощью for:

for (t = 0; t < SOME_VALUE; t++) ;

Как видно, в цикле отсутствует тело.

***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Сб Янв 02 2021, 13:46

8
Цикл: do while


Есть еще один тип циклов — do while. Этот цикл полезен, когда необходимо выполнить код по крайней мере — 1 раз. Рассмотрим его структуру:

Пустая тема. Тема буфер. 9ed_0149

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

Пустая тема. Тема буфер. 9ed_0150

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

***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Сб Янв 09 2021, 15:34

9
Оператор BREAK


Оператор break имеет два назначения. Первое - это окончание работы оператора switch. Второе - это принудительное окончание цикла, минуя стандартную проверку условия. Данное назначение здесь и рассматривается. Когда оператор break встречается в теле цикла, цикл немедленно заканчивается и выполнение программы переходит на строку, следующую за циклом. Например:

Пустая тема. Тема буфер. 9ed_0166

Данная программа выводит числа от 0 до 10 включительно и заканчивает работу, поскольку break вызывает немедленный выход из цикла, минуя условие t< 100.

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

Пустая тема. Тема буфер. 9ed_0167

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

break вызывает выход из самого внутреннего цикла. Например:

Пустая тема. Тема буфер. 9ed_0168

выводит числа от 0 до 9 включительно 2 раза. Каждый раз, когда встречается break, контроль передаётся внешнему циклу for.

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

Пустая тема. Тема буфер. 9ed_0169

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


***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Вс Янв 10 2021, 16:00

10
Функция exit()


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

void exit (int статус);

Она использует заголовочный файл stdlib.h. Значение статуса возвращается в операционную систему.

Для индикации корректности завершения работы exit() традиционно вызывается с аргументом 0.

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

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

Код:
#include <stdlib.h>
int main(void)
{
if (!special_adaptor()) exit(1);
play ();
return 0;
}

Пустая тема. Тема буфер. 9ed_0176

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

В другом примере exit() используется для выхода из программы и возврата в операционную систему:

Код:
void menu(void)
{
char ch;
printf ("1.    Check Spelling\n");
printf ("2.    Correct Spelling, Errors\n");
printf("3.    Display Spelling Errors\n");
printf("4.    Quit\n");
printf("    Enter your choice: ");
do {
ch = getchar(); /* чтение клавиатуры */
switch(ch)
{
case '1':
check_spelling();
break;
case '2':
correct_errors();
break;
case '3':
display_errors ();
break;
case '4':
exit(0); /* возврат в ОС*/
}
}
while(ch!='1' && ch!='2' && ch!='3');
}


***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Пн Янв 11 2021, 15:00

11
CONTINUE


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

Код:
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
 int x;
    do
 {
    scanf ("%d", &x);
    if (x < 0) continue;
    printf ("%d\n", x);
    }
 while(x < 100);

return 0;
}

Пустая тема. Тема буфер. 9ed_0181

В циклах while и do/while оператор continue вызывает переход к проверке условия и затем продолжает работу цикла. В случае for выполняется часть увеличения, затем проверяется условие и, наконец, выполняется само тело цикла.

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

Пустая тема. Тема буфер. 9ed_0182

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

Код:
for(t=0; t<100; ++t)
{
scanf ("%d", &x);
if (x<0) continue;
printf ("%d ", x);
}

В следующем примере оператор continue используется для ускорения выхода из цикла путём форсирования проверки, выполненной ранее:

Код:
void code(void)
{
char done, ch;
done = 0;
while (!done) {
ch = getchar();
if (ch == '.') {
done = 1; continue;
}
putchar(ch+1); /* сдвиг алфавита на одну позицию */
}
}

Можно использовать данную функцию для кодирования сообщений, сдвигая все символы на 1 вверх, то есть 'a' станет 'b'. Функция завершает работу при обнаружении точки, и вывода на экран символа, соответствующего точке, не происходит, поскольку благодаря continue выполнение, минуя оператор вывода, переходит к условию проверки, которое обнаруживает, что done истинно, и вызывает выход.


***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Пт Янв 15 2021, 12:55

12
Метки и GOTO.


Хотя goto уже давно не рекомендуют использовать, он по-прежнему используется в программах. Мы не будем рассматривать целесообразность его использования с точки зрения элегантности управления программой. Следует заметить, что не существует таких ситуаций, где он был бы единственным решением. Общепринято, что он может быть полезен в некоторых ситуациях, goto используется довольно редко. (В языках типа С, имеющих богатый набор структур управления и предоставляющих дополнительные элементы управления типа break и continue, в нём нет необходимости.) Большинство программистов знают, что goto может легко запутать программу и сделать её практически нечитабельной. Тем не менее, бывают моменты, когда goto не только не усложняет программу, но даже её упрощает.

goto требует наличия меток для работы. Метка - это корректный идентификатор С, завершаемый двоеточием. Метка должна находиться в той же функции, что и goto. Например, цикл от 1 до 100 может быть записан с использованием goto и меток следующим образом:

Пустая тема. Тема буфер. 9ed_0185

Одним из хороших способов использования goto является выход из нескольких уровней вложения. Например:

Пустая тема. Тема буфер. 9ed_0186

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

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

Пустая тема. Тема буфер. 9ed_0187

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

Пример использования goto

Код:
#include <stdio.h>

int main (void)
{
int х = 0;
loop1:
х++;
printf("Hello goto!\n");
if (х < 23) goto loop1;

return 0;
}

Пустая тема. Тема буфер. 9ed_0188

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

Пустая тема. Тема буфер. 9ed_0189


***

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty Re: Пустая тема. Тема буфер.

Сообщение  ведущий_специалист Сб Янв 16 2021, 11:48

13
А я бы уточнил, что использовать goto в С совсем не нужно. Как бы совсем.
ведущий_специалист
ведущий_специалист
Мастер+

Сообщения : 303
Дата регистрации : 2020-10-16
Откуда : Санкт Петербург

Вернуться к началу Перейти вниз

Пустая тема. Тема буфер. Empty .

Сообщение  Viktor2312 Вс Янв 17 2021, 01:42

14
Функции.


Функции - это базовые блоки С, в которых выполняются все операции. Стандартный вид функций следующий:

Пустая тема. Тема буфер. 9ed_0110

Спецификатор_типа определяет тип возвращаемого функцией значения с помощью оператора return. Это может быть любой допустимый тип. Если тип не указан, предполагается, что функция возвращает целочисленные значения. Список параметров - это разделённый запятыми список переменных, получающий значение аргументов при вызове функции. Функция может быть без параметров и в таком случае список параметров содержит ключевое слово void.


Оператор return

Оператор return имеет два назначения. Во-первых, немедленный выход из функции. То есть он осуществляет выход в вызывавший функцию код. Во-вторых, может использоваться для возврата значения.


Выход из функции.

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

Пустая тема. Тема буфер. 9ed_0111

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

Тем не менее, не многие функции используют данный метод окончания своего выполнения. Большинство функций используют оператор return для окончания выполнения с целью возврата значения или упрощения кода функции и увеличения его эффективности путем создания нескольких точек выхода. Важно запомнить, что функция может иметь несколько операторов return. Например, функция, показанная ниже, возвращает или индекс первого появления подстроки, указываемой в s1, в строке, указываемой в s2, или —1, если не обнаружено совпадений:

Пустая тема. Тема буфер. 9ed_0195

Надо обратить внимание, как два оператора return упрощают функцию.


Возвращаемые значения.

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

х = power(у);

if (max (х, у) > 100) printf ("greater");

for (ch=getchar(); isdigit(ch); ) ...;

Тем не менее функция не может стоять с левой стороны оператора присваивания. Оператор типа

swap (х, у) = 100; /* некорректный оператор */

неправилен. Компилятор выдаст ошибку.

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

int t;
t = f(); /* нет значения для присваивания t */
f() + f(); /* нет значений для сложения */

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

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

Последний тип функций не имеет определенного возвращаемого значения. Функция является обычной процедурой и не выдает значения. Примером служит srand(), используемая для инициализации генератора случайных чисел функции rand(). Иногда функции, не выдающие осмысленного результата, что-то все-таки выдают. Например, printf() возвращает число напечатанных символов. Очень трудно найти программу, которая проверяет это. Следовательно, хотя все функции, кроме функций, объявленных как void, возвращают значения, нет необходимости использовать все эти значения. Типичным вопросом по возвращаемым функциями значениям является: «Не должен ли я присвоить данное значение некоторой переменной, поскольку значение возвращается?» Ответ: «Нет». Если не указано, чему присваивается возвращаемое значение, то оно просто отбрасывается. Рассмотрим следующую программу, использующую mul():

Код:
#include <stdio.h>

int mul(int a, int b);

int main(void)
{
int x, y, z;
x = 10; y = 20;
z = mul(x, y); /* 1 */
printf ("%d\n\n", mul(x, y) ); /* 2 */
mul (x, y); /* 3 */
return 0;
}    

int mul (int a, int b)
{
return a*b;
}

Пустая тема. Тема буфер. 9ed_0112

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

Пустая тема. Тема буфер. 9ed_0113

Строка 1 (см. комментарии в программе) присваивает возвращаемое функцией mul() значение переменной z. В строке 2 возвращаемое значение напрямую не используется, но оно используется косвенно функцией printf(). Наконец, в строке 3 возвращаемое значение теряется, поскольку не происходит присваивание значения какой-либо переменной и также оно не используется ни в каком из выражений.


Значения, возвращаемые функцией main()

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

Если не определено возвращаемое значение, то в операционную систему будет передано неизвестное значение. Поэтому гораздо полезнее использовать оператор return.


Правила видимости для функций.

Правила видимости языка - это правила, управляющие тем, что «видит» часть программы.

Каждая функция в С - это дискретный блок кода. Код функции является собственностью функции, и к нему нельзя получить доступ с помощью какого-либо оператора или другой функции, помимо вызова данной функции. (Например, невозможно, используя goto, перейти на середину другой функции.) Код, образующий тело функции, спрятан от остальной части программы. Если код не использует глобальные переменные или данные, то он и другие части программы не могут влиять друг на друга. Другими словами, код и данные, определённые в одной функции, не могут действовать на код и данные, определённые в другой функции, поскольку данные функции имеют разные области видимости.

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

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


Аргументы функции.

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

Пустая тема. Тема буфер. 443_er13

Функция is_in() имеет два параметра: s и с. Функция возвращает 1, если символ с является частью строки s. В противном случае она возвращает ноль.

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


Передача по значению и передача по ссылке.

...

Viktor2312
RIP

Сообщения : 15492
Дата регистрации : 2012-08-10
Возраст : 45
Откуда : Пятигорск

Вернуться к началу Перейти вниз

Вернуться к началу

- Похожие темы

 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения