Инициализация массивов при их объявлении. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Инициализация массивов при их объявлении.



Инициализация одномерного массива при объявлении выглядит так:

тип имя[константа] = {список инициализаторов};

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

int a[5]={7,-3,8,-2,4};

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

float b[3]={2.}; заполнит массив b числами 2.,0.,0.

Если есть список инициализаторов, то количество элементов массива при объявлении можно не указывать, транслятор сам отведет ему место в соответствии со списком инициализаторов. Например, объявление int c []={2,0,5}; создаст массив c из трех чисел.

При инициализации двумерного массива значения его элементов нужно указывать в порядке их расположения в памяти, т.е. по строкам. Например, объявление int d [3][2]={1,3,5,7}; создаст матрицу

1 3 ,

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

5 7     1 3 5 7 0 0  
0 0                  

Если нужно изменить порядок заполнения (т.е. указывать не все элементы строк), то каждую строку нужно указывать в { }.Например, объявление int d [3][2]={{1},{3,5},{7}}; создаст матрицу

1 0 ,

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

3 5     1 0 3 5 7 0  
7 0                  

Размер для первого индекса (т.е. количество строк) можно не указывать, транслятор сам определит его в соответствии со списком инициализаторов. Например, объявление int d [][2]={1,3,5,7}; создаст массив (2´2).

Инициализация массивов вводом с клавиатуры.

Заполнение массивов значениями с клавиатуры производится поэлементно.

1) Ввод одномерного массива из n элементов через пробел:

cout << " \nВведите " << n << " чисел через пробел\n ";

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

cin >> a[i];

2) Ввод двумерного массива размером ( n ´ m ) построчно:

printf (" \nВведите матрицу (%d´%d) построчно\n ", n, m);

for (i =0; i < n; i ++)  // Для каждой строки

for (j =0; j < m; j ++) // ввод m чисел через пробел

cin >> d[i][j];

Вывод массивов.

Вывод массивов на экран также производится поэлементно.

1) Вывод одномерного массива из n элементов через пробел:

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

cout >> a[i] >> " ";

2) Вывод двумерного массива размером ( n ´ m ) построчно:

for (i =0; i < n; i ++)  // Для каждой строки

{ for (j =0; j < m; j ++) // вывод m чисел через 2 пробела

printf ("%5.1 f ", a [ i ][ j ]); // число в 5 позициях

cout << ' \n ';     // переход на след.строку экрана

}

Работа с массивами.

Приведем в качестве примера работы с массивами фрагменты программы нахождения суммы и максимального элемента массива a из n чисел (блок-схемы соответствующих алгоритмов были приведены в 1.2.4. 

# define MAX _ SIZE 100 // Определение именованной константы

float a[MAX_SIZE];

float s,max;

int i,n;

············ // Ввод n и массива a из n чисел, n должно быть ············ // не больше MAX_SIZE

s=0;       // Сумма элементов массива a

max=a[1];  // Максимальный элемент массива

for (i=1;i<n;i++) // Для каждого элемента

{ s+=a[i];   // Увеличение суммы на a[i]

if (a[i]>max) // Если элемент больше максимального, то

max=a[i]; // он становится максимальным

}

············ // Вывод n, массива a, s и max

Указатели.

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

Напомним, что память ЭВМ представляет собой последовательность пронумерованных ячеек, каждая из которых имеет свой адрес. Там хранятся как команды программы, так и данные, ею используемые. Данные типа char в языке Си занимают один байт, данные целого типа - обычно два байта, а вещественного - 4 байта.

Если рассмотреть операцию a =5, то для компилятора это означает: занести число 5 по адресу переменной с именем a, т.е. в ячейку с адресом 2008 (см.таблицу).

Имя ptr   a d
Адрес 2000 2004 2008 2012
Значение 2012   5 32

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

тип_объекта *имя_указателя;

Это означает, что в этом указателе будет храниться адрес какого-либо объекта (например, переменной) указанного типа. Например,

int *ptr, d;

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

Занести в указатель адрес можно, используя специальную операцию адресации: &имя_переменной, например, ptr=&d означает: занести в указатель ptr адрес переменной d. Говорят, что ptr указывает (или ссылается) на d.

Чтобы изменить значение переменной, используя ее указатель (т.е. значение по указанному адресу), нужно вместо имени этой переменной в левой части оператора присваивания использовать имя указателя на эту переменную со знаком * перед ним. Например, операторы *ptr=32; и d=32; равнозначны, если ptr ссылается на d.

Операцию * называют операцией раскрытия ссылки, она означает переменную, на которую ссылается указатель. Выражение *указа­тель может использоваться вместо имени соответствующей переменной в любых выражениях Си (в нашем случае *ptr вместо d). Унарные операции & и * имеют тот же приоритет, что и унарный минус (см. таблицу в 2.4.3.5).

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

Пусть описаны целые массив a, переменная s и указатель на целое p.

int *p,a[5]={7,-3,8,-2,4},s;

В языке Си имя массива (например, a) означает на самом деле адрес его нулевого элемента, т.е. адрес ячейки a[0]. Поэтому операторы

p=&a[0]; и p=a;

эквивалентны и предписывают занести в p адрес нулевого элемента массива a (т.е. 2004). Оператор s=*p; копирует в s содержимое a[0].

Имя p a[0] a[1] a[2] a[3] a[4] s
Адрес 2000 2004 2006 2008 2010 2012 2014
Значение 2004 7 -3 8 -2 4 7

Если p указывает на нулевой элемент массива a, то по определению p+1 указывает на следующий элемент, т.е. на a[1], а значением выражения *(p+1) является значение этого элемента, т.е. -3. Аналогично p+i (также, как и a+i) указывает на i -й элемент массива a, следовательно значения выражений a[ i], p[ i], *(a+i) и *(p+i) равны.

Отличием в использовании имени массива и указателя на массив является то, что указатель - это переменная и в нее можно занести в дальнейшем какой-либо другой адрес, например, записать p++ (тогда в p будет находиться адрес 2006. С именем массива такое сделать нельзя, т.к. адрес массива определен компилятором раз и навсегда.

Строки и указатели.

Наибольшее распространение указатели получили в Си при работе со строками. Строковые константы, т.е. объекты вида "текст" (см.2.3), представляются в Си в виде массива символов, который заканчивается символом '\0'. Количество элементов этого массива на единицу больше количества символов между двойными кавычками. Например, "Си" представляется массивом из 3 символов 'С', 'и' и '\0'.

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

char *p_error;

p_error="Ошибка!";

заносят в указатель p_error адрес нулевого элемента символьного массива (символа 'О'). Это же можно сделать и так:

char *p_error=" Ошибка!"; 

Описание же следующего вида

char m_error[]="Ошибка!"; создает символьный массив m_error из 8 элементов. Отдельные его символы можно будет изменить, но m_error всегда ссылается на одно и то же место памяти Значение же p_error в будущем можно будет изменить, записав туда адрес другой константы, например, p_error="Ошибочные данные!";.

Для ввода строки с клавиатуры предусмотрена функция gets( имя_массива ), которая заносит введенные с клавиатуры символы в указанный символьный массив. Размер массива должен быть таким, чтобы вместить все введенные символы. Если же в качестве аргумента функции указан указатель на char, то он также должен указывать на область памяти, достаточную, чтобы вместить все введенные символы.

При вводе строки после нажатия пользователем клавиши Enter символы заносятся в массив, за последним введенным символом автоматически добавляется символ ‘\0’. Затем выполнение программы продолжается.

Чаще всего строки используются в качестве аргументов функций, как, например, в функции fprintf() или в потоках вывода cout.

Рассмотрим некоторые приемы работы со строками в Си. Основным является то, что длина строки заранее неизвестна. Признаком ее окончания является символ '\0'.

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

int i,equal=0;   // Признак совпадения строк пока равен 0

unsigned char mas[81], *parol="Мой пароль";

 

gets(mas);         // Ввели пароль (<=80 символов)

for (i=0; mas[i] == *(parol+i);i++)

if (mas[i] == '\0') // Строки совпали полностью

{equal=1;break;} // Признак совпадения = 1

if (!equal)

printf("Пароль %s не годится\n",mas);

else

cout << "Пароль" << mas << "годится\n";

На вводимое значение пароля мы отвели 80 символов, указатель parol ссылается на массив с его верным значением. После ввода пароля он посимвольно сравнивается с правильным значением до нахождения отличающихся символов. Если же дошли до конца строки (символа ‘\0’), не встретив отличий, то выходим из цикла, установив признак совпадения строк в 1.

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

Ограничим длину предложения 300 символами, признаком окончания слова будем считать пробел, а признаком буквы – значение кода символа в пределах от 65 (латинская А) до 239 (русская я). Поскольку будем использовать коды кириллицы (т.е. > 127), то необходимо описывать символы как unsigned char.

int i=0;              // Номер текущего символа

int k_sl=1,k_sim=0;   // Количество слов и символов

unsigned char mas[300],ch; // Предложение и текущий символ

gets(mas);

while ((ch = *(mas+i++))!= '\0')

if (ch==' ')          // Текущий символ - пробел -

k_sl++;             // увеличили кол-во слов

else if (ch>64 && ch<240) // Текущий символ - буква -

k_sim++;            // увеличили кол-во букв

printf("Слов - %d,,букв - %d",k_sl,k_sim);

Просматриваем по порядку все введенные символы, записывая их в ch, пока не дойдем до конца строки '\0'. Выражение (ch = *(mas+i++))!= '\0' означает: взять то, что находится по адресу mas+i, и занести в ch. Затем сравнить это значение с '\0' и результат сравнения считать значением всего выражения. Затем увеличить i на 1.

Внешние скобки здесь обязательны, иначе в ch занесется резуль­тат сравнения *(mas+i) и '\0', поскольку логическая операция != обла­дает более высоким приоритетом, чем операция присваивания =.

Отметим, что в операторе while вместо mas+i++ использовать сдвиг значения mas путем mas++ нельзя, т.к. mas - имя массива, а не указатель. Можно сделать указатель на mas:

insigned * p;

p = mas; // и тогда правомерна конструкция

while ((ch = *(p++))!= '\0')



Поделиться:


Последнее изменение этой страницы: 2020-12-09; просмотров: 122; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.224.95.38 (0.037 с.)