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

 

- a, c1, x12_45g но не 1а, 12-78

- “_”используется для образования для длинных имен

begin_of_1 но не _of_1

- в именах различаются маленькие и большие буквы (с большой буквы обычно пишут именованные константы, с малой – имена переменных);

- различают имена переменных;

- имена внутренних - до 31 знака;

- имена внешних - до 6 символов.

- ключевые слова языка Си зарезервированы (не могут быть использованы как имена !!!)

int, if, for, char…

Эти слова пишутся только маленькими буквами

 

Пример 6.3:

#include <stdio.h>

#define KOL 12

main()

{ int i, main[KOL], first_day_of_year;

}

Типы и размеры данных

 

 

6.4.2.1 Базовые типы Си

 

 

char единичный байт, содержащий одну литеру из допустимого набора (ASCII);

int целое, отображаемое на естественное представление целых4

float вещественное одинарной точности;

double вещественное удвоенной точности.

 

 

6.4.2.2 Квалификаторы

 

 

Различают два вида квалификаторов в языке Си:

1) длины (применимы к целым, int можно опускать)

- short

- long (можно применить к типу double)

2) знака (применимы к символьному и любому целому типу)

- signed

- unsigned

Примеры записи:

long int = long

short int = short

short<int<long

 

limits.h - в этом файле устанавливаются размеры типов

float.h - в этом файле устанавливаются константы с плавающей точкой

 

Реализация типов в языке Turbo C

ТИП Размер, бит Диапазон

Unsigned char 8 0..255

Char 8 -128..127

Unsigned short 16 0..65535

Short 16 -32768..32767

Unsigned int 16 0..65535

Int 16 -32768..32767

Unsigned long 32 0..4294967245

Long 32 -2147483648..2147483647

Float 32 3.4e-38..3.4e+38

Double 64 1.7e-308..1.7e+308

Long double 64 1.7e-308..1.7e+308

Отсутствует базовый тип логический, который моделируется целым типом:

– ложь = 0, истина = не 0.

Присутствует тип указатель.

Введен тип пустой (void) – отсутствие какого-либо значения.

 

 

Константы

 

 

6.4.3.1 Целочисленные константы

 

 

Типы int и long.

Системы исчисления

В 10 с/с цифры от 0 до 9 не начинающиеся с 0

В 8 с/с цифры от 0 до 7, обязательно начинаются с 0

В 16 с/с цифры от 0 до 9, буквы A..F (a..f) начинаются с 0х или 0Х

 

Пример 6.4:

170 /*десятичная*/

0252 /*восьмиричная*/

0хАА /*шестнадцатиричная*/

170L /*десятичная длинная*/

0252L /*восьмиричная длинная*/

0ХAАL /*шестнадцатиричная длинная*/

Во внутреннем представлении, если целая константа превысила 16 разрядов – автоматически представляется как 32 разряда (10 с/с). Если значение 8-ой или
16-ой константы превысило наибольшее целое без знака, то оно также будет представлено, как длинное беззнаковое.


6.4.3.2 С плавающей точкой

 

 

У констант с плавающей точкой float обязательно должны быть либо десятичная точка, либо е (экспоненциальная часть):

314.15 e-2 = 3.1415 = 314*10-2

 

6.4.3.3 Символьная

 

 

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

1) для представления “читаемых” (“печатных”) символов используются внутримашинные коды – ASCII, КОИ-8, ДКОИ.

2) Специальные символьные константы (ESС-последовательности):

- Апостроф \’

- Кавычки \”

- Пусто (нулевой символ) \0

- Новая строка \n

- Обратная косая \\

3) Последовательности трех восьмеричных символов: \ddd (код символа).

Пример 6.5:

‘M’ ‘m’ ‘П’ ‘п’

‘\n’ ‘\\’

‘\016’ = ‘f’

Символьная константа имеет тип int (т.к. есть расширенные коды в ASCII, размером в 2 байта).

6.4.3.4.Строковая константа

 

 

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

 

Пример 6.6:

“MM” “”ПМ” “Informatique” “m” “o”

Строковая константа представляет собой массив символов, в конце которого вставлен код признака конца строки - \0.

“ПМ”

П М \0

 

 

6.4.3.5 Константное выражение

 

 

Оперирует только с константами.

Кроме арифметических констант могут быть использованы именованные константы.

#define <имя> <текст>

<имя> - символьное имя

<текст> - последовательность литер

Семантика:

Далее по тексту программы производиться замена <имя> на <текст>, кроме как:

- внутри строковых констант;

- если цепочка, составляющая имя, является частью определения другого имени.

Особенности синтаксиса:

- имя может содержать только из заглавные буквы;

- не нужно писать декларации;

- ее нужна ; после #define.

 

Пример 6.7:

#define MAX 100

#define V_YEAR 1

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

Пример 6.8:

#define MAX 100

float a[MAX]…

Пример 6.9:

#define V_YEAR 1

int days_of_year [31+28+V_YEAR+31+30+31+30+31+31+30+31+30+31];


7 ДЕКЛАРАЦИИ В СИ

 

 

7.1 Декларации – назначение и синтаксис

 

 

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

 

Декларация:

1) специфицирует тип;

2) содержит список переменных этого типа;

3) возможна начальная инициализация;

4) возможен квалификатор константы (const).

 

Пример 7.1:

int up, down, step;

char c, str[101];

 

или

int up;

int down;

int step;

char c;

char str[101];

 

 

7.2 Инициализация

 

 

Инициализация (от англ. Initial – начальное) – это процесс придания переменным начальных значений при их объявлении. Записывается в Си в виде выражения после символа равно при декларации переменной:

char newline=’\n’;

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

Пример 7.2

int i =0;

int board=MAX+1;

float eps=1.0e-3;

char error[]=”Ошибка: ”;

 

О ш и б к а : \0

 

int kdm[12]={31,28,31,30,31,30,31,30,31,31,30,31,30,31};

 

 

7.3 Квалификатор константы const

 

 

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

Пример 7.3:

const float pi=3.1415;

const int kdm[12]={31,28,31,30,31,30,31,30,31,31,30,31,30,31};

……

pi=3.14; /*нельзя*/

kdm[i]=kdm[i]+1; /*нельзя*/


8 ОПЕРАТОРЫ В ЯЗЫКЕ СИ

 

 

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

 

 

В языке Си привычные знаки операций называют операторами, а конструкции языка (ветвления, циклы) называют инструкциями.

Свойства операторов:

- арность (количество операндов);

- позиция (место по отношению к операндам);

- приоритет (важность, старшинство);

- ассоциативность (порядок выполнения операторов с олинаковым приоритетом).

1.Операторы +, -, / , * , % бинарные.( % - остаток от деления)

 

Оператор Целые Вещественные
+ Сложение Сложение
- Вычитание Вычитание
* Умножение Умножение
/ Деление нацело Деление нацело
% Остаток от Деления --------------------  

Пример 8.1:

year%4

 

Приоритет:

prio(+) = prio(-)

prio(*) = prio (/) = prio(%)

prio(*, /, %) > prio(+, -)

Для унарных +, - :

prio(унарных)>prio(*, /, %)

 

Ассоциативность

Ассоциативность определяет порядок выполнения операторов с одинаковым приоритетом. Все арифметические операторы левоассоциативные.

Пример 8.2:

8/2/2 è 4/2=2

 

 

8.2 Операторы отношения и сравнения на равенство

 

 

Бинарные операторы:

1) отношения:>,>=,<,<= (одинаковый приоритет);

2) сравнения на равенство:

==(равно) !=(неравно)

Приоритет одинаковый внутри группы.

prio(отношения)>prio(сравнения на равенство)

prio(отношения)<prio(арифметических)

 

Пример 8.3:

K+1<l+2 (k+1)<(l+2)

Year%4==0 (Равен ли остаток от деления year на 4 0 ?)

Все операторы сравнения и отношения вырабатывают значение истина и ложь. В языке Си:

- ложь – 0

- истина - ≠ 0

- 8.3Логические операторы

 

 

8.3.1 Бинарные операторы:

&&- логическое ‘и’

|| - логическое ‘или’

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

Результат && есть “ложь”, как только первый попавшийся операнд есть “ложь”. Результат || есть “истина”, как только первый попавшийся операнд -“истина”.

Дальше вычисление не производится.

Свойства:

&& и || -левоассоциативные

prio(&&) = prio(||)

prio(&&) <prio (отношения, сравнения на равенство)

 

X&&Y

X Y И Л
И И Л
Л Л Л

 

X||Y

X Y И Л
И И И
Л И Л

 

Пример 8.4:

4 3 2 6 5 1 8 7 (приоритет)

Year%4==0&&year%100!=0||year%400==0

8.3.2 Унарный оператор

Логическое отрицание

не - !

 

 

0,если х ≠0

!х=

1,если х=0

prio(!)>prio(&&,||)

Пример 8.5:

Эквивалентны:

res==0 и !res

 

 

8.4 Побитовые операторы

 

 

Применяется к целочисленным операндам (char, short, int, long) знаковым и без знаковым.

 

 

8.4.1 Бинарные

 

 

8.4.1.1 Побитовое И

& : используют для обнуления разрядов или бита внутри байта

X&Y

X Y

Пример 8.6:

Значение выражения содержит 1 Maska1=017;

во всех разрядах, в которых ie1 и ie2 P=p&maska1;

содержит 1 и 0 во всех остальных разрядах

 

 

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

| : для установки разрядов в 1

X||Y

X Y

 

Пример 8.7:

Значение выражения содержит 1 Maska2=03;

во всех разрядах, в которых ie1 или ie2 m=m&maska2;

содержит 1 и 0 во всех остальных разрядах

 

Следует отличать логические и побитовые операторы !!!

 

Пример 8.8:

X=1; y=2;

x&&y /*=1*/

x&y /*=0*/

 

8.4.1.3 Побитовое исключающее ИЛИ

^ : 1- разные значения

0- остальные разряды


X ^ Y

X \ Y

 

Пример 8.9:

x=0177;

y=01;

x^y /*0176*/;

 

8.4.1.4 Сдвиг влево

<< - правый операнд должен быть >0

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

Пример 8.10

x=02; /*0102*/

y=x<<1; /*01002=4*/

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

 

8.4.1.5 Сдвиг вправо

>> - правый операнд должен быть >0

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

Пример 8.11

x=06; /*1102*/

y=x>>1; /*112=3*/

z=x>>2; /*12*/

Сдвиг вправо соответствует делению нацело на степень двойки.

 

 

8.4.2 Унарные

 

Унарный оператор побитового отрицания ~

x ~x

Пример 8.12

c=c&~03;

Значение выражения :

   

C_1 ……………………………………С_14 С_15 С_16

 

 

8.5 Операторы присваивания

 

 

Операторы присваивания имеют следующий вид

<e1><op>=<e2> - выражение

<op> - бинарный оператор

+ % << |

- >> ^

* &

/

Выполнение

<e1>=<e1><op><e2>

значки операторов присваивания

+= /= <<= &= ^=

-= %= >>= |=

Пример 8.14

x=15; x8=015;

y=8; y8=07;

z=5; z8=05;

x+=2; /*x=17*/

y-=7; /*y=1*/

z*=4; /*z=20*/

z/=2; /*z=10*/

z%=3; /*z=1*/

x8<<=2; /*x8=064*/

y8>>=1; /*y8=3*/

x8|=03; /*x8=067*/

x8^=07; /*x8=060*/

!!! Внимание !!!

x*=a+b ( x=x*(a+b)

( x=x*a+b;

Все операторы правоассоциативные.

 

 

8.6 Инкрементные и декрементные операторы

 

 

Унарные

инкрементный ++ : добавляет 1 к операнду;

декрементный -- : вычитает 1 из оператора

необычность

префиксный ++(--) увеличивает (уменьшает) операнд до его использования

постфиксный ++(--) увеличивает (уменьшает) операнд после его использования

Пример 8.15:

 

x=2;

y=x++; /*y=x; x+=1;

y=2; x=3*/

x=2;

z=++x; /*x+=1; z=x;

x=3; z=3*/

Эти операторы можно применять только к переменным, но не к выражениям.

 

 

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

 

 

Преобразование (приведение) типов: приведение операндов разных типов к некоторому общему.

Существуют правила, согласно которым операнды приводятся к общему типу.

1) Для бинарных операторов:

а) если 1 из операндов имеет тип long double, то операнды приводятся к типу long double;

б) если 1 из операндов имеет тип double, то общий тип – double;

в) если 1 из операндов имеет тип float, то общий тип - float;

г) если 1 из операндов имеет тип short или int, то общий тип – int; (для целочисленных операндов);

д) если 1 из операндов имеет тип long, то общий тип – long, то общий тип- long (для целочисленных операндов).

2) При присваивании:

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

а) char -> int (размножение знака)

б) int -> short

int -> char

long -> int

long -> char

(отбрасывание старших разрядов)

в) float -> int

int -> float

(преобразование типа с ПТ <-> целое)

г) double -> float (округление/отбрасывание)

3) При вызове функций (будет рассмотрено в соответствующей теме)

4) Явное задание приведения типов

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

- унарный;

- префиксный;

- правоассоциативный

Синтаксис:

(<имя_типа>) е,

где е – выражение

Семантика:

<е> приводится к заданному <типу>

 

Пример 8.19:

int x=16;

y=sqrt((double)x);

 


9 УПРАВЛЕНИЕ В СИ

 

Управление – определенный порядок выполнения вычислений в программе.

 

 

9.1 Инструкции и блоки

 

 

Если в конце выражения поставить ‘ ; ’, то выражение становится инструкцией.

<инструкция>::=<выражение>;

Пример 9.1:

x=0 j++ /* выражения */

x=0; j++; /* инструкции */

Составная инструкция ( блок ).

<блок>::={ [<декларация>]

<инструкция1>;

………………….

<инструкция n> ;

}

Внутри блока разрешены как операторы декларации так и исполнимые операторы.

 

 

9.2 Инструкция if – else

 

 

Синтаксис

if(<выражение>) либо if (<выражение>)

<инструкция1> <инструкция1>

else <инструкция2>

Семантика

Вычисляется значение выражения, если значение выражения истинно, то выполняется <инструкция1>, если ложно то <инструкция2>

Пример 9.2:

int a,b,c; /* исходные данные */

int x; /* результат */

……..

if(a>b) /* вариант 1 */

if(a>c) x=a;

else x=c;

else if(b>c) x=b;

else x=c;

/* вариант 2 */

………………………..

x=a;

if (b>x) x=b;

if(c>x) x=c;

9.3Переключатель switch

Используется для разветвления алгоритма более чем на 2 направления.

Синтаксис

Switch(<выражение>)

{ case <константное выражение1>:<инструкции 1>

case< константное выражение n>:< инструкции n>

default:<инструкции>

}

Семантика

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

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

Пример 9.3:

/* kd – количество дней месяца */

if (j==1|| j==3|| j==5|| j==7|| j==8|| j==10|| j==12) kd=31;

else if(j==2) kd=28;

else kd=30;

Пример 9.4:

………………………………..

switch (j)

{

case 1: kd=31; break;

case 2: kd=28;break;

case 3: kd=31;break;

…………………………….

case 12: kd=31;break;

default:printf(”Ошибка”);break;}

Пример 9.5:

switch (j)

{

case 1: case 3: case 5: case 7: case 8: case 10: case 12: kd=31; break;

case 4 :case 6: case 9: case 11: kd=30;break;

default: if (j==2) kd=28;

else printf(”Ошибка”);break; }

 

 

9.6 Цикл while

Синтаксис:

While (<выражение>)

<инструкция>

Аналог ”пока” языка алгоритмов. Это цикл с неизвестным количеством повторений, с предусловием.

Семантика:

Вычисляется выражение, если оно отлично от 0 (истинно),

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

Как только выражение станет равным 0 цикл while завершается. Если необходимо в теле цикла выполнить больше чем 1 инструкцию, то надо взять в { }

Пример 9.6:

/* е в степени х (с точностью eps ) */

float y,s,,eps,x;

int i,n;

………………………………………… /* Ввод х */

y=1; n=1; i=1; S=x;

while (s/n>eps)

{

y+=s/n;

i++;

n*=i;

s*=x;

}

9.7 Цикл for

Синтаксис

For (<выражение 1>;<выражение 2>;<выражение 3>)

<инструкция>

Это цикл с известным числом повторений.

Семантика

< выражение 1>

while(<выражение 2>)

{< инструкция >;

< выражение 3>;

}

<выражение 1> - инициализация

<выражение 2> - условие завершения цикла

<выражение 3> - изменение

Любое из этих 3 выражений может отсутствовать, но ‘;’ обязательно!!!

Пример 9.7:

/* бесконечный цикл */

for( ; ;)

{……...}

Если опущены <выражение1> и <выражение3> - они не используются.

<выражение1> берется до цикла.

<выражение3> изменяется внутри цикла

Пример 9.8-9.9

#define N 10

float X[N]

int i;

float s;

………………………………..

s=0;

for(i=0;i<N;i++)

s+=X[i];

Либо:

for(s=0,i=0;i<N;i++)

s+=X[i];

Особенности цикла for в языке С:

Переменная цикла и ее предельное значение могут изменятся внутри цикла. По завершению цикла переменная цикла определена. В выражениях 1, 2 и 3 может быть использовано более одного выражения, разделенных оператором ‘,’

‘,’- бинарный, инфиксный, левоассоциативный оператор.

Приммер 9.10 Реверсировать массив.

0 1 2 3 4

1  

 

#define N 10

…………….

float x[N];

int i, j;

float r;

…………….

For( i=0 , j=N-1; i<j ;i++ , j--)

{

r=x[i];

x[i]=x[j];

x[j]=r;

}

 

9.6 Цикл do while

 

Синтаксис: do <инструкция> while (<выражение>)

- цикл с неизвестным числом повторений.

Семантика: 1.выполняется <инструкция>

2.вычисляется значение <выражения>

3.если <выражение> истинно(не равно 0), то снова переходим на пункт 1. Если <выражение> равно 0 (ложно) – конец цикла.

 

9.7 Инструкция break и continue

 

Break используется в циклах while, for, do while и в конструкции zwitch. В циклах использование break приводит к немедленному их завершению (до достижения предельного значения переменной цикла for или до достижения условия завершения цикла в while или do while).

Пример 9.11 Определить, является ли матрица А положительно определенной (все элементы больше 0).

Aij>0 , i принадлежит [1,m], j принадлежит [1,n]

#define N 10

#define M 15

float a[M][N];

int i,j;

int pr=1;

for (i=0; i<=M-1;i++)

for(j=0; j<N; j++)

if (a[i][j]<=0 )

{ pr=0; break; }

if (pr) printf(“A - положительно определенная ”);

else printf(“A – не положительно определенная ”);

! Break завершает немедленно ближайший , охватывающий его цикл.

Continue вызывает переход к следующей итерации цикла : в for изменяет переменную цикла согласно закона , указанного в шапке цикла, в while , do while приводит к вычислению выражения , которое является условием продолжения цикла.

Пример 9.12 . Найти сумму S отрицательных элементов массива x[N]

#define N 5

float x[N] ;

int i;

float s=0;

for(i=0;i<=N-1;i++) или for(i=0;i<N;i++)

if (x[i]<0) s+=x[i]; {if (x[i]>=0 )continue;

s+=x[i];}

 

 


10 УКАЗАТЕЛИ И МАССИВЫ

 

10.1 Указатели

int x;

int *px; /* объявляется указатель на данное целого типа */

 

px=&x; /* указателю px присвоили адрес переменной x */

 

ПАМЯТЬ-массив последовательно проадресованных ячеек, с кото- рыми можно работать по одному и группами.

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

Оператор & (унарный) выдаёт адрес объекта.

Пример 10.1:

p=&c;(р ссылается на переменную с)

pi=&i; (pi ссылается на переменную i)

Применяется только к операндам которые находятся в памятии (переменные и элементы массива)

Не могут быть применины к константам и выражениям

 

Унарный оператор * -оператор раскрытия ссылки,

применяется только к указателям. Результат - объект, на который ссылается указатель

Пример 10.2:

int a=1,b=2,z[5];

int *ip; /* объявляем указатель на переменную целого

типа */

ip=&a; /* указатель ip ссылается на переменную a */

b=*ip; /* b=1 */

*ip=0; /* a=0 */

ip=&z[2] /* ip указывает на z[2] */

Указатель ссылается только на объекты заданного типа (кроме void)

При объявлении указателя можно написать указатель на тип void:

void *p;

но потом применять оператор разоименования (*) нельзя

Пусть

int a=1;

int *ip; => Используем *ip везде, где допустимо использовать a:

ip=&a;

- *ip=*ip+10; /* a+=10 */

- y=*ip+1; /* y=11+1 */

- *ip+=1; /* 11+1=12 */

 

- +*ip; /* 12+1=13 */

- (*ip)++; /* 13+1=14 */

- ! *ip++; /* изменяется сам указатель, а не то

значение на которое он ссылается */

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

заявлен в деклорации.

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

Пример10.3:

int a;

int *ip,*ir;

ir=&a;

ir=ip;

10.2 Связь между указателями и массивом

В языке C связь между указателями и массивом очень тесная, так как любая операция взятия элемента массива может быть выполнена с помощью оператора *(!!! более того * выполняется быстрее)

 

[ ] º *

int a[5];

i-й элемент:a[i]

С указателем:

int *pa

pa=&a[0];

x=*pa =>x=a[0];

Адресная арифметика:

Если указатель pa указывает на некоторый элемент массива, то выражение pa+1 указывает на следующий элемент массива, pa+i – на i-й после pa, pa-1 – на предыдущий (перед pa).

Если pa=&a[0], то *(pa+1)~a[1]

pa+i~ адрес a[i]

*(pa+i)~a[i]

Пример 10.4:

int *pa;

int a[5]= -1,-10,-100,-1000,-10000 ;

int a1,a2;

pa=&a[0];

a1=*(pa+1); /* a1=-10 */

a2=*(pa+2); /* a2=-100 */

 

Связь между адресной арифметикой и индексированием массива

 

Значение переменой или выражения типа массива есть адрес нулевого элемента этого массива.

ПРИМЕР 10-5

int a[5], *pa, *pm

pa=&a[0]:pm=a;

Эквивалентны

a[i] | *(a+1)

&a[i] | a+i

pa[i] *(pa+i)

Указатели группируються обычные элементы.Указатели также можно индексировать.Тогда *(pa+i) pa[i].Различия между именем.

I 10-4 Различия между именем масства и указателем(в роли имени массива)

Указатель=переменная

-допустимо

int*pa; int a[5]

pa=a;

pa++;

-недопустимо

int*pa;

int a[5];

a=pa;

a++;

 

Литерные указатели

Строковая константа, записаная в СИ в виде изображение есть массив литер или символов.

Количество байтов=количество литер+1 (для символа ’\ Ф ’)

ПРИМЕР 10-6

Char * pstr

Pstr=’ С указатели ’

Строка не копируется , а только указатели на массив .

ПРИМЕР 10-7

Char s _str[] =” как массив ”

Char *p_str=” с указателем”

s_str ---Элементы этого массива могут изменяться, но ссылается в оперативную память

p_str --- Это указатель инициализированный

В Си нет операторов для работы с массивом в целом ->недопустимо

 

10.5 Литерные указатели.

 

Строковая константа есть массив литер (символов). Количество байтов равно количеству литер +1 (для символа окончания строки \0).

 

Пример 10.6

char *pstr;

pstr=”с указателем”:

 

! Различие между декларациями строк как массива и с помощью указателя:

Пример 10.7

char s_str[]=”как массив”; /*11dyte*/

char p_str=”с указателем”; /*13byte*/

 

с   у к а з а т е л е м \0

p_str

 

к а к   м а с с и в \0

s_str

 

Замечание

s_str:

- элементы s_str могут изменяться.

- s_str всегда ссылается на одно и то же место в памяти.

 

p_str:

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

 

 

!!! В Си нет оператора для работы с массивом в целом (=> недопустимо s_str изменить).

 

10.6 Массивы указателей.

       
 
. . . рис.4     схема . . .
 
. . . схема     рис.4 . . .


 

 
 
 

 

 
 
 

схема
Рис.4

 

 

схема


Рис.4

 

 

Удобно в Си текст, представлять массивом указателей.

 

 

Пример 10.9

#define KL 100

int n1,n2;

char *v[KL];

char *temp;

int k;

temp=v[n1];

v[n1]=v[n2];

v[n2]=temp;

k=KL;

while (k-->0)

printf(“%s\n”,*v++);

10.7 Инициализация массива указателей

Пример 10.10:

Char*m_name[]= { ”ошибка”,”январь”,”февраль”,”март”,”апрель”,

”июнь”,”июль”,”август”,”сентябрь”,”октябрь”,”ноябрь”,”декабрь” } ;

/* обращаемся по номеру месяца */

(n<1 || n>12)? m_name[0]:m_name[n];

10.8 Многомерные массивы

Пример 10.11:

/* представляется как массив массивов */

int mpr[2][9]=

{

/* даты */ {1,7,8,1,2,9,24,7,8},

/* месяцы */ {1,1,3,5,5,5,8,11,11}

}

Это даты праздничных дней Украины не привязанных к Церковному

календарю.

Обращение к элементам двумерного массива.

……………………………………………………………………………

d_may1=mpr[0][3];

m_may1=mpr[1][3];

10.9 Указатели вместо многомерных массивов

Пример 10.12:

int a[3][4] /* массив массивов */

0 1 2 3

       
       
       

 

Int*b[3]

0)

1)

2)

 

Массив а занимает 24 байта (2 байта * количество элементов)

Массив b занимает первые 6 байт. У массива b не выделена пока память под собственно элементы. Это выделение может быть выполнено 2 способами:

1) при инициализации;

2) либо явно динамическим захватом памяти (см. 2 семестр);

Преимущество 2-го способа состоит в том , что строки в массиве b

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

Пример 10.13:

Берем из примера 10.10 первые 3 Элемента массива и выделяем под них память 2 способами.

1)

/* объявление массива строк как массива массивов char

 

m_name1[][10]={”ошибка”,”янв.”,”февр.”};

посчитает

компилятор обязательно задается

 

 

о ш и б к а \0     я н в . \0           ф е в . \0            

10 20 30

 

Количество не использованных байтов:12 (40%)

2)

char*m_name2[]={”ошибка”,”янв.”,”фев.”};

 

0) ошибка\0

 

1) янв.\0

 

2) фев.\0

 

 

Библиотека для работы со строками string.h

1 strlen(s), где s – строка

Определяет длину строки (информационной части, без \0)

int l;

l=strlen(“пример”); /* l=6 */

2 strcat(s1,s2) /* s1+=s2 */

s2 конкатенируется к s1(s1 – меняется, s2 – не меняется)

char a[]=”Белеет ”, /* a~Белеет */

b[]=”парус ”; /* b~парус */

strcat(a,b); /* a~Белеет парус */

 

3 strcpy(s1,s2)

Копирование строки s2 в s1 (s1 – меняется, s2 – не меняется)

char a[]=”Белеет ”,

b[]=”парус ”;

char *c;

strcpy(c,a); /* c~”Белеет ” */

strcat(c,b); /* c~”Белеет парус ” */

4 strcmp(s1,s2)

Сравнение строк (в лексико-графическом порядке)

/* Происходит посимвольное вычитание ASCII кодов */

 

0, если s1=s2

=0, иначе ( разница в коде ):

strcmp=

<0, s1<s2

>0, s1>s2

Пример:

int r1,r2,r3;

char a[]=”ПО96а”,

b[]=”ПО96б”ж

char *c;

strcpy(c,a); /* c~”ПО96а” */

r1=strcmp(a,c); /* r1=0 */

r2=strcmp(a,b); /* r2<0 */

r3=strcmp(b,c); /* r3>0 */

 

Библиотека проверки символов ctype.h

Тип всех функций - int . Все функции отвечают на вопрос в соответствии с названием функции:

”Являются ли аргумент этой функции тем, что сформулировано в названии?”

Результат : 1 или 0.

Тип аргумента – int !!! Хотя все функции анализируют символы, но символьная константа имеет тип int .(т.к. в константе могут быть символы, которые в ASCII кодируются 2 байтами, а char только

1 байт.

isdigit( c ) – цифра (0..9) (если цифра, то вернет 1, иначе 0)

isalpha( c ) – буква (латынь)

isalnum( c ) – буква (латынь) или цифра

isupper ( c ) – прописная буква

islower ( c ) – строчная буква

Пример:

int c1=’9’,c2=’s’,c3=’G’,c4=’y’,c5=’=’;

int r1,r2,r3,r4,r5;

r1=isdigit(c1); r1=1

r2=isalpha(c2); r2=1

r3=isalnum(c1); r3=1

r3=isalnum(c5); r3=0

r4=isupper(c3); r4= 1

r5=islower(c4); r5=1

Преобразование символов.

1) atoi(s) - выполняет преобразование строки в int

2) atol(s) - выполняет преобразование строки в длинный int

Строка s – это аргумент содержащий изображение этого числа.

Результатом является целое или длинное целое число.

Пример:

int i;

long l;

i=atoi (”1996”); i=1996

l=atol(”1999000”); l=1999000

 


11 СТРУКТУРЫ В ЯЗЫКЕ СИ

 

Структура языка Си- это эквивалент записи.

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

 

ПР.11.1

/* строка таблицы */

 

Ф.И.О МАТЕМ ФИЗ Р.ЯЗ

 

Элементы разных типов

 

ПР.11.2

Представление

/* точка А в пространстве */ можно выполнить с помощью структуры:

xa ya za

 

Элементы массива безликие.

Элементы структуры имеют имена.

 

ПР.11.3

/* окружность на плоскости */

 

x0 y0 R

 

11.1 Объявление структурного типа в языке СИ

 

синтаксис:

struct [<имя = тег>]

{<декларация..члена1>;

...

<декларация члена N>;

};

- Декларация структуры

 

= тип

- Если после слова struct указать имя (tag), то это есть имя типа, кот. можно далее пользоваться как именем любого другого базового типа (как float, int).

- Имена тегов и членов могут совпадать с именами других переменных.

- Объявление структурного типа – это образец, а не декларация данных ( память не выделяется).

 

- ПР.11.4 /* для 11.2 */

 

Struct без тега struct point c тегом

{ int xa; { int xa;

int ya; int ya;

int za; int za;

}; };

 

ПР.11.5 /* для 11.3 */

 

Struct Struct circle

{ float x0; { float x0;

float y0; float y0;

float r; float r;

}; };

 

11.2. Декларация переменных структурного типа.

 

I сп < декларация типа структ. >

<список переменных>; 1 оператор

 

 

II сп struct < тег><список переменных>; 2 оператора

 

ПР.11.6 /* прямая : через точки А и В */

 

Struct struct point a,b;

{ int xa; см.11.4

int ya;

int za;

} a,b;

 

Инициализация:

 

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

 

ПР.11.7 /* окружность с центром (2;3) и радиусом 5.5 */

 

Без тега

Struct

{ float x0;

float y0;

float r;

} pr = {2.0, 3.0, 5.5};

c тегом

struct circle pr = {2.0, 3.0, 5.5}

 

Доступ к элементам структуры

 

<имя структуры>.<имя члена>

 

Пример 11.8

/*расстояние от начала координат до точки pt*/

struct

{float x;

float y;} pt={20.0,15.0};

double dist;

dist=sqrt((double)pt.x*pt.x+(double)pt.y*py.y);

printf(“От начала координат”);

printf(“до точки (%f, %f)”,pt.x, pt.y);

printf(“расстояние %f”,dist);

 

 








Дата добавления: 2015-12-29; просмотров: 2986;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.563 сек.