Книга: Язык Си - руководство для начинающих
МАССИВЫ
МАССИВЫ
Массивы являются важнейшим средством языка, применяемым во многих программах. Их использование позволяет удобным способом размещать в памяти большое количество необходимой информации. Позже мы посвятим массивам целую главу, но, поскольку они очень тесно связаны с циклами, мы хотим начать их использовать уже сейчас.
Массив - это набор переменных, имеющих одно и то же базовое имя и отличающихся одна от другой числовым признаком. Например, с помощью описания
float debts [20];
объявляется, что debts - массив, состоящий из двадцати членов, или "элементов". Первый элемент массива называется debts[0], второй - debts[l], и т. д. вплоть до debts[19]. Заметим, что перечисление элементов массива начинается с 0, а не с 1. Поскольку мы объявили, что массив имеет тип float, каждому его элементу можно присвоить величину типа float. К примеру, можно писать так:
debts[5] = 32.54;
debts[6] = 1.2е+21;
Массивы могут быть образованы из данных любого типа:
int nannies[22]; /* масснв, содержащий 22 целых чнсла */
char alpha[26]; /* масснв, содержащий 26 символов */
long big[500]; /*массив, содержащий 500 целых чисел типа long */
Раньше, например, мы говорили о строках, являющихся частным случаем массива типа char. (В общем массив типа char - это массив, элементами которого являются величины типа char. Строка - массив типа char, в котором нуль-символ '' используется для того, чтобы отмечать конец строки.)
РИС. 8.6. Массивы символов и строки
Числа, используемые для идентификации элементов массива, называются "подстрочными индексами" или просто "индексами". Индексами должны быть целые числа, и, как уже упоминалось, индексирование начинается с 0. Элементы массива размешаются в памяти последовательно, друг за другом, как показано на рис. 8.6.
РИС. 8.7. Размещение в памяти массивов с элементами типа char и int
Существует огромное количество возможностей применения массивов. Ниже приводится сравнительно простой пример. Предположим, вы хотите написать программу, осуществляющую ввод 10 различных результатов спортивной игры, которые будут обрабатываться позже. Используя понятие массива, вы сможете избежать придумывания 10 различных имен переменных - по одной для каждого счета. Кроме того, для чтения данных вы можете воспользоваться циклом for:
/* ввод счета*/
main( )
{
int i, score[10];
for (i = 0; i <= 9; i++)
scanf(" %d", &a[i]); /* ввод десяти результатов*/
printf("Введены следующие результаты :n" );
for (i = 0; i <= 9; i++)
printf(" %5d", a[i]); /* проверка правильности ввода*/
printf("n");
}
В понятие хорошего стиля программирования входит эхо-печать только что введенных величин. Она даст уверенность, что в программе будут обрабатываться те данные, для которых она предназначена.
Применяемый здесь способ гораздо более удобен, чем использование 10 различных операторов scanf() и 10 отдельных операторов printf() для ввода и проверки десяти результатов, определяющих число набранных очков. Цикл for обеспечивает очень простои и удобный способ использования индексов массивов.
Какого типа операции могли бы мы выполнить над этими данными? Мы могли бы найти их среднее, величину стандартного отклонения (мы знаем даже, как это сделать) и максимальное значение счета, а также произвести их сортировку в некотором порядке. Займемся двумя простейшими задачами: нахождением среднего и максимального результатов.
Чтобы вычислить среднее, мы можем добавить к нашей программе приведенный ниже фрагмент:
int sum, average;
for(i = 0, sum = 0; i <= 9; i++) /* две инициализации*/
sum + = a[i]; /* суммирование элементов массива */
average = sum/10; /*классический метод усреднения */
printf(" Средний результат равен %d.n", average);
Для нахождения максимального результата к программе можно добавить следующий фрагмент:
int highest;
for(highest = а[0], i = 1; i <= 9; i++)
if(a[i] > highest) highest = a[i];
printf ("Максимальный результат равен %d.n", highest);
Здесь мы начинаем с того, что полагаем переменную highest равной величине а[0]. Затем производится сравнение значения highest с каждым элементом массива. Когда обнаруживается, что некоторая величина больше текущего значения переменной highest, ей присваивается эта новая большая величина.
Теперь объединим все части программы. На псевдокоде алгоритм ее работы можно записать следующим образом:
ввод результатов.
эхо-печать результатов.
вычисление и печать среднего значения.
вычисление и печать максимального значения.
Кроме того, мы несколько обобщим нашу программу:
/* результаты*/
#define NUM 10
main( )
{
int i, sum, average, highest, score [NUM];
printf(" Укажите10 результатов. n");
for(i = 0; i < NUM; i++)
scanf(" %d" , &scorc[i]); /* ввод десяти результатов */
printf(" Введены следующие результаты:n");
for(i = 0; i<NUM; i++)
printf("%5d", score[i]);/* проверка правильности ввода*/
printf("n");
tor(i = 0, sum = 0; i < NUM; i++)
sum + = score[i]; /* суммирование элементов массива */
average = sum/NUM; /* классический метод усреднения */
printf(" Средний результат равен %d.n", average);
for(highest = score[0], i = 1; i < NUM; i++)
if(score[i] > highest) /* какая из величин больше*/
highest = score[i];
printf(" Максимальный результат равен %d.n", highest);
}
Мы заменили число 10 символической константой и воспользовались тем, что выражения i <=(NUM-1) и i < NUM эквивалентны.
Давайте сначала посмотрим, как это программа работает, а затем сделаем несколько замечаний.
Укажите 10 результатов:
76 85 62 48 98 71 66 89 70 77
Введены следующие результаты:
76 85 62 48 98 71 66 89 70 77
Средний результат равен 74. Максимальный результат равен 98.
Первый момент, который необходимо отметить, состоит в том, что мы использовали четыре различных цикла for. Вас может заинтересовать вопрос: является ли это на самом деле необходимым или мы можем некоторые из данных операций объединить в одном цикле? Такая возможность существует, и она позволила бы сделать программу более компактной. Однако мы побоялись следовать такому подходу (видите, какие мы впечатлительные люди!), поскольку это противоречит принципу модульности. Смысл, заключенный в данной фразе, состоит в том, что программа должна быть разбита на отдельные единицы, или "модули", причем каждый из них должен выполнять одну задачу. (Наша запись на псевдокоде отражает деление программы на четыре модуля.) Такое разбиение облегчает чтение текста программы. Возможно, еще более важным является то, что если отдельные части программы не перемешаны, ее коррекция или модификация упрощаются. Для этого необходимо только исключить из программы требуемый модуль, заменить его новым, а оставшуюся часть программы не изменять.