Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка по программированию.doc
Скачиваний:
11
Добавлен:
13.11.2019
Размер:
1.2 Mб
Скачать

Void main()

{

char S[]="This is string";

printf("%d",strlen(S));

}

Для операций с матрицами в математике использу­ются переменные со многими индексами. В С для этой цели используются так называемые многомерные масси­вы, или массивы массивов. В принципе ограничений на количество индексов нет, но мы ограничимся рассмотре­нием двухмерных массивов. Описание int x[2][3]; мож­но рассматривать как два массива, каждый из которых есть набор трех целых чисел. Нам более привычно рас­сматривать такую конструкцию просто как матрицу - набор компонентов с двумя индексами:

В памяти компьютера многомерные массивы распо­лагаются последовательно так, что в первую очередь ме­няется последний индекс, а в последнюю - первый. Та­ким образом, элементы указанного массива расположены в памяти последовательно в следующем порядке: x[0][0], x[0][1], x[0][2], x[1][0], x[1][1], х[1][2]. Работу с двухмер­ными массивами проиллюстрируем простой программой, которая формирует единичную матрицу и выводит ее на экран:

Void main()

{

int i.j, М[5][5];

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

for(j=0; j<5; j++) if(i==j) M[i][j]=1; else M[i][j]=0;

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

{

for(j=0; j<5; j++) printf(“%d ",M[i][j]);

printf("\n");

}

}

Как известно, в единичной матрице по главной диагона­ли стоят единицы, а все остальные элементы равны ну­лю. Два первых вложенных друг в друга цикла for позво­ляют перебрать все возможные комбинации индексов, а условное выражение во внутреннем цикле выполняет со­ответствующее присваивание. Можно предложить более элегантное, хотя и менее наглядное выражение вместо конструкции if - else. Необходимый результат дает присваивание M[i][j] = (i==j); Вторая пара вложенных циклов обеспечивает печать матрицы на экран именно в виде таблицы из пяти строк и пяти столбцов. Внешний цикл работает пять раз. Пять раз выполняется составное выражение, в котором, в свою очередь, два выражения. Первое выражение — печать значений элементов матри­цы. Печать выполняется в одну строчку — печатаются пять чисел, разделенных пробелом. Затем выполняется второе выражение, а это есть переход на новую строку. Далее снова печатается пять чисел и снова производится перевод на новую строку, где, наконец, печатаются по­следние числа. Заметим, что в данной программе мож­но было бы обойтись только одной парой циклов, совме­стив инициализацию матрицы с ее печатью. Разделение на два этапа сделано исключительно для большей наглядности.

Адреса и указатели

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

Начать следует с напоминания того факта, что все данные, необходимые для выполнения программы, такие, как переменные, константы, массивы и многое другое, включая и сам код программы, размещаются в оператив­ной памяти компьютера. Память представляет собой со­вокупность большего числа элементарных ячеек, каждая из которых имеет свой номер или, выражаясь профессио­нально, свой адрес. Такая минимальная адресуемая ячейка на­зывается байтом. Байт, в свою очередь, представляет со­бой совокупность восьми двоичных разрядов (битов), в которых записываются 0 или 1. Мы уже говорили о том, что различные типы данных занимают различное число байтов. Так, один символ размещается в одном байте, це­лое типа int занимает уже два байта и так далее. После загрузки исполняемого кода программы в память каждая переменная обзаводится своим адресом, номером первого из группы занимаемых ею байтов. Адреса принято пред­ставлять в шестнадцатеричной системе счисления, и для операций с адресами в С существует специальный фор­мат р (от английского pointer - указатель), а для раз­мещения адресов существует специальный тип перемен­ных - указатели. В зависимости от того, адреса каких данных помещаются в указатели, изменяются и сами ти­пы указателей. Могут существовать указатели на сим­волы, на целые типа int, на вещественные типа double и многие другие. Указатели в программе описываются так: Тип *Имя. При этом указатели можно объединять с описаниями других данных под общим названием типа. Например, возможно такое описание: double u=7.65,*a; Здесь описана и инициализирована вещественная пере­менная двойной точности u и указатель р на объект типа double, пока не инициализированный, то есть не имею­щий значения. Для получения адреса объекта в С также суще­ствует специальная операция &, знак которой помещает­ся перед именем объекта. Таким образом, &u есть адрес переменной u. Понятно, что инициализация указателя (придание ему конкретного значения) может быть сде­лана простым присваиванием. После выполнения выра­жения а=&u указатель а имеет значение адреса перемен­ной u. Существует операция, обратная операции получе­ния адреса. Такая операция называется разадресацией и имеет вид *Указатель. Применение такой операции по­зволяет получить значение, находящееся по адресу, на который указывает указатель. В нашем примере есть число, находящееся по адресу а. В свою очередь, а есть адрес переменной u, значение которой равно 7.65. В ито­ге - это просто число 7.65. Поскольку & и * - вза­имно обратные операции, очевидно, что &*M есть М и *&N есть N, что бы ни представляли собой переменные М и N.

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