Полезное в сети

Всегда в теме

Статистика


Яндекс.Метрика


Онлайн всего: 1
Гостей: 1
Пользователей: 0

Рекомендуем



Главная » Статьи » Образовательные » Программирование

Правила оформления программ на Си/Си++. Операции и основные типы данных.

Правила оформления программ на Си/Си++.

Программа состоит из модулей-функций, причем одна из функций является главной и обязательно называется main. После имени функции в круглых скобках перечисляются через запятую ее параметры, затем открывается фигурная скобка, записываются операторы тела функции и ставится закрывающая фигурная скобка. Фигурные скобки {и } также служат для указания начала и конца блока операторов (функции, цикла и т. п.). Каждый оператор заканчивается точкой с запятой, может располагаться на нескольких строках, кроме того, несколько операторов можно записать на одной строке. Символы// означают, что оставшаяся часть строки является комментарием. Текст, начинающийся /* и заканчивающийся */, также является комментарием. Только некоторые компиляторы допускают вложенные комментарии. 
Имена переменных, функций, меток, типов данных, классов и макросов называются идентификаторами и могут содержать символы:строчные и прописные буквы английского алфавита;
цифры от 0 до 9 (имя не может начинаться с цифры);
символ подчеркивания.Обычно длина идентификатора ограничивается 31 символом, прописные и строчные буквы различаются. Идентификаторы не должны совпадать с ключевыми словами.

#include <iostream.h> // этот файл нужен для ввода/вывода
void main(void) // главная функция main(void) без параметров

// начало функции 
char *name; // так описывается строка
cout<<"Введите свое имя”<<endl; // на экране появляется просьба ввести имя
cin>>name>>endl; // с клавиатуры вводится имя 
cout<<"Привет, "<<name<<" это первая программа”; // вывод на экран
// конец функции


В программе можно использовать константы:
десятичные (например: 1, 10L, -6, -2.3, 3.45е6, 6.789е-2);
восьмеричные (например: 012, 0204, 076663L);
шестнадцатеричные (например: 0xa, 0xA, 0xdeL, 0x84, 0x7dB3);
символы (например: ‘g’, ‘?’, ‘\b’, ‘\\’, ‘0x1B’, ‘\’’);
строчные литералы ("long string”, "Y\\N”, " \”Yes, I do, \” she said”).

Операции и основные типы данных

Операции


Для записи операторов используют операции, приведенные в табл. 1.
Таблица 1

Операция

Наименование

Операция

Наименование

!

Логическое НЕ

~

Побитовое дополнение

+

Сложение

-

Вычитание, логическое отрицание

/

Деление

%

Остаток

<< 

Сдвиг влево

>> 

Сдвиг вправо

< 

Меньше

<=

Меньше или равно

> 

Больше

>=

Больше или равно

=

Равно

!=

Не равно

&

Побитовое И, адресация

|

Побитовое ИЛИ

^

Побитовое исключение ИЛИ

&&

Логическое И

||

Логическое ИЛИ

,

Последовательное выполнение (запятая)

?:

Операция условного выражения

++

Инкремент

--

Декремент

=

Простое присваивание

+=

Сложение с присваиванием

-=

Вычитание с присваиванием

*=

Умножение с присваиванием

/=

Деление с присваиванием

%=

Остаток с присваиванием

>>=

Сдвиг вправо с присваиванием

<<=

Сдвиг влево с присваиванием

&=

Побитовое И с присваиванием

|=

Побитовое ИЛИ с присваиванием

^=

Побитовое исключающее ИЛИ с присвиванием

Значение логического выражения, отличное от 0, истинно.
Си/Си++ поддерживает определения для множества базовых или "основных" типов данных. Представление в памяти, область значений величин различных типов, преобразование типов изложены в /1 - 4/.
Типы signed charsigned int, signed short int и signed long int вместе с соответствующими двойниками unsigned называются типами целых.
Спецификаторы типов float и double относятся к типу "плавающих".
Тип void может быть использован для объявления функций, не возвращающих значения.
В целых типах ключевое слово signed может быть опущено. Если ключевое словоunsigned опускается, то тип целого будет знаковым (signed).
В некоторых реализациях могут быть использованы опции компилятора, позволяющие изменить умолчание для типа char со знакового на беззнаковый. Тогда сокращениеchar имеет то же значение, что и unsigned char.
Для преобразования типа выражения необходимо в скобках перед ним записать требуемый тип:

(int)1.2; (double)(a+3); (float)i; (long)(6785*3.5/x);

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

sizeof(char); sizeof(int); sizeof(b); sizeof(float);

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

buf=(int *)malloc(100*sizeof(int)); // выделение памяти для 100 целых.

Запретить изменение переменной позволяет модификатор const :
const float i=1;

Переменные const имеют ту же зону видимости, что и переменные static. Const, в отличие от директивы #define, контролирует типы.
Для изменяющихся переменных используется модификатор volatile, показывающий, что переменные могут меняться фоновым процессом.

 

Указатели и массивы

Для работы с адресами памяти используются указатели.

int *a; // указатель на переменную целого типа
float *addr_f; // указатель на переменную вещественного типа

Размер памяти для переменной-указателя зависит от конфигурации машины. Конкретный адрес является указателем и получается с помощью операции &(адресации). Адресация не может применяться к переменным класса памяти register и к битовым полям структур /2/. 
Разадресация применяется для получения значения величины, указатель которой известен. Если значение указателя нулевое, то результат разадресации непредсказуем.

int *рa, x; int a[20]; double d;
рa= &a[5]; // это адрес 6-го элемента массива а
х = *рa; // x присваивается значение 6-го элемента массива а 
if (x==*&x) cout<<"true\n"; d=*(double *)(&x); 
// адрес х преобразуется к указателю на double и d=x.


Указатель - это переменная, содержащая адрес другой переменной. Указатели очень широко используются в языке Cи. Это происходит отчасти потому, что иногда они дают единственную возможность выразить нужное действие, отчасти потому, что они обычно ведут к более компактным и эффективным программам, чем те, которые могут быть получены другими способами. Так как указатель содержит адрес объекта, это дает возможность "косвенного" доступа к этому объекту через указатель /1/. Предположим, что X - переменная, например, типа int, а РX - указатель, созданный неким еще не указанным способом. Унарная операция & выдает адрес объекта, так что оператор РX = &X; присваивает адрес X переменной РX; говорят, что РX"указывает" на X. Операция & применима только к переменным и элементам массива, конструкции вида &(X-1) и &3 являются незаконными. Нельзя также получить адрес регистровой переменной.

Унарная операция * рассматривает свой операнд как адрес конечной цели и обращается по этому адресу, чтобы извлечь содержимое. Следовательно, если Y тоже имеет тип int, то Y = *РX; присваивает Y содержимое того, на что указывает РX.Последовательность РX = &X; Y = *РX; присваивает Y то же самое значение, что и оператор Y = X; Переменные, участвующие во всем этом, необходимо описать: int X, Y; int *РX; Описание указателя int *РX; должно рассматриваться как мнемоническое; оно говорит, что комбинация *РX имеет тип int. Это означает, что если РX появляется в контексте *РX, то это эквивалентно переменной тип int. Фактически синтаксис описания переменной имитирует синтаксис выражений, в которых эта переменная может появляться. Это замечание полезно во всех случаях, связанных со сложными описаниями. Например, double atof(), *DР; говорит, что atof() и *DР имеют в выражениях значения типа double.


Указатели могут входить в выражения. Например, если РX указывает на целое X, то*РX может появляться в любом контексте, где может встретиться X. Оператор Y = *РX + 1; присваивает Y значение, на 1 большее значения X; printf("%d\n", *РX) печатает текущее значение X; D = sqrt((double) *РX) получает в D квадратный корень из X, причем до передачи функции sqrt значение X преобразуется к типу double. В выражениях вида Y = *РX + 1 унарные операции и & связны со своим операндом более крепко, чем арифметические операции, так что такое выражение берет то значение, на которое указывает РX, прибавляет 1 и присваивает результат переменной Y.


Ссылки на указатели могут появляться и в левой части присваивания. Если РXуказывает на X, то *РX = 0 полагает X равным нулю, *РX += 1 увеличивает его на единицу, как и выражение (*РX)++. Круглые скобки в последнем примере необходимы; если их опустить, то это выражение увеличит РX, а не ту переменную, на которую он указывает. Если РY - другой указатель на переменную типа int, то РY = РX копирует содержимое РX в РY, в результате чего РY указывает на то же, что и РX.
Массив рассматривается как набор элементов одного типа. Чтобы объявить массив, необходимо в описании поcле имени массива в квадратных скобках указать его размерность.

int а[5]; // массив, состоящий из 5 целых переменных
char sym[20]; // массив из 20 символьных переменных 
double c[10]; // массив из 10 вещественных величин.

Индексы элементов изменяются от 0 до N-1, где N- размерность массива. Переменная типа массив является указателем на элементы массива. 
Многомерный массив определяется путем задания нескольких константных выражений в квадратных скобках:

float d_l[3][5], c_dim[5][3][3];

Элементы массива запоминаются в последовательных возрастающих адресах памяти. Хранятся элементы массива построчно. Для обращения к элементу массива вычисляется индексное выражение. Для a[i] индексное выражение равно *(а+ i) , где а - указатель, например, имя массива; i - целая величина, преобразованная к адресному типу; * - операция разадресации. Для двумерного массива b[i][j] индексное выражение:*(b+i+j).


В языке Cи существует сильная взаимосвязь между указателями и массивами, указатели и массивы следует рассматривать одновременно. Любую операцию, которую можно выполнить с помощью индексов массива, можно сделать и с помощью указателей. Вариант с указателями обычно оказывается более быстрым, но и несколько более трудным для непосредственного понимания. Описание int A[10]определяет массив размера 10, т.е. Набор из 10 последовательных объектов, называемых A[0], A[1], ..., A[9]. Запись A[I] соответствует элементу массива через I позиций от начала. Если РA - указатель целого, описанный как int *РA, то присваиваниеРA = &A[0] приводит к тому, что РA указывает на нулевой элемент массива A; это означает, что РA содержит адрес элемента A[0]. Теперь присваивание X = *РA будет копировать содержимое A[0] в X.

Если РA указывает на некоторый определенный элемент массива A, то по определению РA+1 указывает на следующий элемент, и вообще РA-I указывает на элемент, стоящий на I позиций до элемента, указываемого РA, РA+I на элемент, стоящий на I позиций после. Таким образом, если РA указывает на A[0], то *(РA+1)ссылается на содержимое A[1], РA+I - адрес A[I]*(РA+I) - содержимое A[I]. Суть определения "добавления 1 к указателю", а также его распространения на всю арифметику указателей, состоит в том, что приращение масштабируется размером памяти, занимаемой объектом, на который указывает указатель /2/.


Ссылку на A[I] можно записать в виде *(A+I). При анализе выражения A[I] в языке Cи оно немедленно преобразуется к виду *(A+I); эти две формы эквивалентны. Имеется одно различие между именем массива и указателем, которое необходимо иметь в виду. Указатель является переменной, так что операции РA=A и РA++ имеют смысл. Но имя массива является константой, а не переменной: конструкции типа A=РA илиA++, или Р=&A будут незаконными. Когда имя массив передается функции, то на самом деле ей передается местоположение начала этого массива.

Внутри вызванной функции такой аргумент является точно такой же переменной, как и любая другая, так что имя массива в качестве аргумента действительно является указателем. Можно передать функции часть массива, если взять в качестве аргумента указатель начала подмассива. Например, если A - массив, то F(&A[2]) и F(A+2)передают функции F адрес элемент A[2], потому что и &A[2], и A+2 являются указательными выражениями, ссылающимися на третий элемент A.


Рассмотрим пример ввода/вывода значений элементов массива с помощью функцийscanf и рrintf:

#include <stdio.h> // подключается файл с прототипами функций scanf и рrintf
void main(void) { int a[3]; int i; float b[4]; double c[2];
for (i=0; i<3; i++ ) { scanf("%d ", &a[i] );
р
rintf("%d", a[i]); }
i=0; while (i < 4)
{scanf ("%f",b[i]);
р
rintf("%g",b[i]); i++;}
i=0 ; do
{ scanf("%lf ", &c[i]);
р
rintf("%g", c[i]); i++;}
while(i< 2); } }

Динамически выделять память под массивы и другие объекты можно с помощью функций calloc, malloc:

int *dim_i, n_dim_i;
n_dim_i =10; 
dim_i =(int *)calloc(n_dim_i*sizeof(int)); . . .

Тогда освобождать память необходимо функцией free:

free(dim_i);

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


#include <alloc.h>

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

int *i_рtr; i_рtr=new int; // резервируется память под величину int
d_рtr = new double(3.1415); // то же, что и *i_рtr=3.1415
c_рtr = new char[str_len]; // область памяти для str_len символов

Реальный размер выделяемой памяти кратен опеределенному числу байт. Поэтому невыгодно выделять память по new для небольших объектов. Если new не может выделить блок памяти, то она возвращает значение NULL.
Примеры освобождения памяти оператором delete :

delete i_рtr; delete d_рtr; delete [str_len] c_рtr;

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

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

Для работы с отдельными символами используются описания переменных типа
char sym1, sym2, sym3, c;

В программе можно явно присвоить значение переменной типа char 
sym1 = 'A'; sym2 = 'a';
sym3 = 'c'; c = '0x1B'; 
// ASCII символ

Ввод с клавиатуры:


scanf("%c ", &sym1); sym1 = getchar();


Вывод на экран:


рrintf ("%c", sym1); рutchar(sym1);

Фрагмент программы, выводящей на экране вводимые с клавиатуры символы до тех пор, пока не нажата клавиша Enter.

while((c = getchar( )) != '\ n' ) рutchar(с);

Esc-последовательности

Esc-последовательности - это специальные символьные комбинации, которыми представляются неграфические и пробельные символы в строковых и символьных константах. Esc-последовательность cостоит из \ и следующей сразу за ней буквы или комбинации цифр:
\n - новая строка, \t - горизонтальная табуляция,
\v - вертикальная табуляция, \b - пробел,
 - звонок, \` - одиночная кавычка,
\" - двойная кавычка, \\ - наклонная черта влево,
\ddd - восьмеричный код ASCII, \xdd -шестнадцатиричный код ASCII,
\c - означает обычный символ с.

Категория: Программирование | Добавил: Admin (19.04.2012)
Просмотров: 1658 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Поиск

Вход

Гость
  • Вход
  • Регистрация
  • Читаемое

    Заходи не жди