Сделай Сам Свою Работу на 5

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

/*rooms.c*/int room[10] = {102, 107, 109, 112, 115, 116, 123, 125, 127, 130};int max[10] = {12, 43, 23, 12, 20, 15, 16, 23, 12, 15};main() { int index, choice, num, rooms, flag, found; rooms = 10; puts("1.Показать вместимость всех комнат\n"); puts("2.Определить вместимость определенной комнаты\n"); puts("3.Найти комнату определенной вместимости\n"); printf("Введите Ваш выбор от 1 до 3: "); scanf("%d", &choice); if (choice == 1) { for (index = 0; index < rooms; index++) printf("Комната #%d рассчитана на %dмест\n", room[index], max[index]); } if (choice == 2) { printf("введите номер комнаты: "); scanf("%d", &num); index = 1; found = 0; while (! found && index < rooms) if (room[index] == num) found = 1; else index++; if (! found) puts("Комнаты с таким номером нет в списке\n"); else printf("Комната #%d рассчитана на %d мест\n", room[index], max[index]); } if (choice == 3) { flag = 0; printf("Введите минимальное желательное количество мест:"); scanf("%d", &num); for (index = 0; index < rooms; index++) if (max[index] >= num) { flag = 1; printf("Комната #%d рассчитана на %d мест\n", room[index], max[index]); } if (flag == 0) puts("Комнат с таким количеством мест нет\n"); } }

В этой программе максимальное значение индекса массива присваивается переменной rooms, а затем на экран выводится меню. Выбор одного из пунктов меню определяет, какая из функций будет выполняться. Это осуществляется с помощью последовательности из трех инструкций if. Аналогичную программу можно было написать с использованием инструкции switch или вложенных инструкций if...else.

Первая процедура в цикле for выводит список всех комнат и их вместимость. Здесь необходима только одна индексная переменная, которая используется в качестве индекса как для массива room, так и для массива max.

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

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



Строки

Строкой называется массив символов. При определении строки вы присваиваете ей имя и указываете максимальное количество символов, которое может в ней содержаться. Однако не забывайте о том, что один элемент массива всегда резервируется для нулевого символа (\0), вследствие чего при определении строки следует указывать количество элементов на единицу больше действительно предполагаемой максимальной длины строки.

Си и Си++ позволяют осуществлять ввод и вывод массива символов в виде некой целостности — строки. В то же время, каждый символ является отдельным независимым элементом массива (рис.7). Например, с помощью следующей программы можно ввести строку, а затем отобразить составляющие ее отдельные символы:

main() { char name[20]; int index; printf("ВведитеВашеимя: "); scanf("%s", name); for (index = 0; index < 20; index++) printf("%c\n", name[index]); }


Рис. 7. Каждый из символов, составляющих строку, в действительности является отдельным элементом массива

Если в действительности было введено меньше двадцати символов, элементы массива, следующие за нулевым символом, содержат случайные величины.

Если бы в языке Си отсутствовала функция gets(), то ввод строки можно было осуществить путем последовательного ввода символов и присваивания их в качестве значения отдельным элементам массива, как это продемонстрировано в Листинге 5.

Листинг 5. Имитация функции gets().

/*getstr.c*/main() { char name[10], letter; int index; index = 0; puts("Введите имя, по окончании нажмите Enter\n"); do { letter = getchar(); name[index] = letter; index++; } while (letter !='\r' && index < 9); name[index] = '\0'; putchar('\n'); puts(name); }

К счастью, язык Си расценивает строки как особую разновидность массивов, позволяя осуществлять ввод и вывод строк как единого целого. Однако какие-либо дополнительные приемы обращения со строками в языке Си отсутствуют. В то же время, использование строк настолько распространено в программировании, что большинство Си и Си++ компиляторов имеют специальные функции для работы со строками. Конечно, для этих целей можно написать и собственные функции, но использование стандартных библиотек представляется более эффективным.

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

Сравнение двух строк

В Си и Си++ нельзя непосредственно сравнить значение двух строк с помощью, например, такого условия:

if (string1 == string2)


Рис. 8. Синтаксисфункцииstrcmp()

Однако большинство библиотек содержит функцию strcmp(), которая возвращает нулевое значение в том случае, если строки одинаковы, либо значение, отличное от нуля, если строки не совпадают. Синтаксис функции strcmp() показан на рис. 8. Эта функция используется в программе следующим образом:

if (strcmp(name1, name2) == 0) puts("Имена совпадают");else puts("Имена не совпадают");

Некоторые компиляторы возвращают отрицательное число, если первая строка оказывается с точки зрения алфавита «меньше» второй, и положительное число, если «больше».

Если компилятор не имеет функции strcmp(), можно написать собственную функцию, которая сравнивала бы две сроки элемент за элементом как параллельные массивы, и останавливалась при обнаружении пары несовпадающих значений:

main() { int index, flag; char name[10], name1[10]; gets(name); gets(name1); flag = 0; for (index = 0; index < 10; index++) if (name[index] != name1[index]) { flag = 1; break; } if (flag == 1) puts("Строкинесовпадают"); else puts("Строки совпадают"); }

Определение длины строки

Длина строки не обязательно должна совпадать с длиной массива. Например, вы можете определить массив name, который содержит 20элементов, но ввести в него имя, состоящее из меньшего числа символов. Большинство компиляторов Си и Си++ имеют функцию strlen(), которая позволяет определить количество символов, действительно содержащееся в строке:

gets(name);count = strlen(name);printf("Строка %sсодержит %dсимволов", name, count);

Функция присваивает значение, отражающее количество символов во введенной строке (в нашем случае она называется name), целочисленной переменной count. Без использования функции strlen() ту же процедуру можно выполнить с помощью следующих инструкций:

main() { int index; char name[10]; gets(name); for (index = 0; index < 10; index++) { if (name[index] == '\0') break; } printf("%d", index); }

В данной программе осуществляется просмотр массива в поисках нулевого символа. Дело в том, что позиция элемента, содержащего нулевой символ, соответствует количеству символов в строке, то есть ее длине.

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

main() { char name[10]; int index, count; gets(name); count = strlen(name); for (index = count; index > 0; index--) putchar(name[index-1]); putchar('\n'); }

Здесь значение длины строки используется в качестве индекса в условии цикла for, причем значение его уменьшается при каждом повторе цикла. Если строка содержит 5символов, цикл будет повторен 5раз, изменяя значение переменной index от 5 до 1. Так как элементы такого массива имеют номера от 0 до 4, то, чтобы получить номер элемента, из значения переменной index вычитается единица.

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

Язык Си не позволяет непосредственно присваивать символы строке, используя инструкции вроде

name = "Сэм";

Для этой цели можно вызвать функцию strcpy(), с которой позволяют работать большинство компиляторов. Синтаксис функции следующий:

strcpy(name, "Сэм");strcpy(name, name1);

В первом примере символы "Сэм" присваиваются строковой переменной с именем name. Во втором примере символы, которые уже были присвоены переменной name1, копируются в переменную name.

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

char name[] = "Алан";main() { char person[10]; int count, index; count = strlen(name); for (index = 0; index <= count; index++) person[index] = name[index]; puts(person); }

В этой программе происходит присваивание символьных значений одного массива соответствующим элементам другого массива.


Рис. 9. Синтаксис функции strcat()

 

Замечания по Си++
Благодаря перегрузке язык Си++ допускает использование оператора + для сложения двух строк с помощью инструкции:   new_string = string1 + string2;

 

Слияние строк

Процедура слияния двух строк состоит в том, что символы, содержащиеся в одной строке, добавляются в конец другой, сдвигая нулевой символ. Этот процесс называется конкатенацией (concatenation). В стандарте языка Си K&R определена функция strcat(), работа которой продемонстрирована на рис. 9. Символы из строки, которая передается функции в качестве второго параметра, добавляются в конец строки, передаваемой в качестве первого параметра.

Массивы строк

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

Двухмерный массив можно представить себе как таблицу, имеющую ряды и колонки. Такой массив следует определять с двумя индексами, один из которых определяет количество рядов таблицы, а второй устанавливает количество колонок. Ниже приведены инструкции, определяющие массив, имеющий 10 рядов и 20 колонок, то есть содержащий 200 целочисленных переменных:

inttable[10][20];

Представим себе каждый элемент как целое число, занимающее собственную


Рис. 10. Определение массива строк

клеточку в таблице 10х20. Элемент table[0][0] находится в левом верхнем углу таблицы, а элемент table[0][1] занимает соседнюю клетку справа в том же ряду.

Определяя массив строк, также необходимо использовать два индекса. Первый определяет максимальное количество строк в массиве, а второй указывает максимальную длину каждой строки. Таким образом, определение

charnames[10][20];

задает десять строковых переменных names длиной не больше 19 символов в каждой (рис.10).

Если вы хотите задавать строки путем ввода значений отдельных символов, следует использовать вложенные циклы. Внешний цикл будет повторяться 10 раз, по одному на каждую строку, а внутренний должен иметь 19 повторов для ввода значений одной строки. На рис. 11 приведена программа, в которой вводятся значения 10 имен (строковых переменных) в массив, а затем все эти 10 строк с помощью цикла for последовательно выводятся на экран.

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

name[index][index2] = letter;

Первый индекс указывает номер нужной строки внутри массива, а второй определяет позицию символа внутри строки. Например, на рис. 12 элемент name[0][3] является четвертым символом (буква м) первой строки ("Адам") в


Рис. 11. Программирование массива строк

 


Рис. 12. Строки и элементы массива строк

массиве имен. Чтобы вывести на экран строку целиком, нужен только один индекс, указывающий номер строки:

puts(name[index]);

К счастью, Си и Си++ позволяют ввести всю строку как единое целое, используя только один цикл, повторяющийся по одному разу на каждую строку массива:

main() { char name[10][20]; int index; for (index = 0; index < 10; index++) gets(name[index]); for (index = 0; index < 10; index++) puts(name[index]); }

Проектирование программы

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

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

Таким образом, вы оказываетесь между Сциллой и Харибдой. Поэтому планируйте размеры массива с особенной тщательностью. Старайтесь оставлять допуск не слишком большой, но достаточный для того, чтобы быть уверенным, что номер индекса никогда не превысит максимального количества элементов массива.

  Вопросы
1. Что такое массив? 2. Может ли массив содержать переменные нескольких типов? 3. Как вы будете определять массив? 4. Что такое двухмерный массив? 5. Как вы будете определять двухмерный массив? 6. Какова взаимосвязь между значением индекса и значением элемента массива? 7. Как сравнить две строки? 8. Как присвоить значение строковой переменной?

 

  Упражнения
1. Напишите программу, в которой массивы используются для хранения имен, адресов и номеров телефонов 20 человек. 2. Внесите в программу из упражнения 1 изменения так, чтобы иметь возможность ввода имени и последующего просмотра массива в поисках номера телефона соответствующего человека. 3. Объясните, почему следующая программа написана неправильно: main() { int temps(31); int index, total; for (index = 0; index < 31; index++) { printf("Введитезначение температуры #%d: ", index); scanf("%d", &temps(index)); } high = temps(0); low = temps(0); index = 1; while (index < 31) { if (temps(index) > high) high = temps(index); else low = temps(index); index++; } printf("Минимальное значение температуры равно %d\n", low); printf("Максимальное значение температуры равно %d\n", high);}

 



©2015- 2019 stydopedia.ru Все материалы защищены законодательством РФ.