Подсчет частоты появления символа в строке
1.13.1. Определить, сколько раз в заданной строке встречается некоторый символ
В школьном алгоритмическом языке величина строкового (в терминах языка Паскаль) типа рассматривается как массив, элементами которого являются отдельные символы. Это позволяет обратиться к тому или иному символу строки как к элементу массива — по имени строковой величины и его (символа) номеру[X].
Рассмотреть же все символы строки можно, подсчитав их количество, что, в свою очередь, можно сделать с помощью функции длин:
Количество := О
Нц для Номер От 1 До Длин(строка)
Если Строка[номер] = симв
То
Количество := количество + 1
Все
Кц
Вывод нс, Количество
Где строка — величина строкового типа — заданная строка; симв — символ, число вхождений которого в строку ищется.
Rolichestvo := 0;
For Nomer := 1 To Length(Stroka) Do
If Coρy(strokaz nomerz 1) = simvol Then Kolichestvo := kolichestvo + 1;
Write(kolichestvo);
Попытка по аналогии с предыдущей задачей решить рассматриваемую задачу так:
Искомый_номер := О
Нц для Номер От 1 До Длин(строка)
Если Строка[номер] = симв То Искомый_номер := номер Все кц |Вывод ответа Вывод нс, Искомый—НОмер
Даст неправильный результат— при наличии в строке нескольких вхождений заданного символа ответом будет номер последнего (а не первого!) вхождения.
Можно решить задачу, использовав величину логического типа впервые, определяющую, впервые ли в строке встретился заданный символ: искомый_номер := О впервые := Да нц для Номер От 1 До Длин(строка) Если Строка[номер] = симв И Впервые То Искомый_номер := номер I Следующие вхождения символа будут уже не первыми впервые := Нет все кц
Можно также прекратить проверки, как только встретится заданный символ: номер := 1 найден := Нет нц пока Номер <= длин(строка) И не Найден Если Строка[номер] = симв То !Встретился искомый символ найден := Да Искомый_номер :- номер Иначе I Переходим к следующему символу номер := номер + 1 Все
КЦ
I Вывод ответа Вывод нс, Искомый номер
Где найден — величина логического типа, фиксирующая факт нахождения первого вхождения заданного символа в строку.
И, конечно, можно решить задачу, исследовав заданную строку с ее конца.
В программе на языке Паскаль решение задачи значительно упрощается за счет того, что в этом языке имеется функция Pos, возвращающая позицию (индекс) первого вхождения некоторой подстроки (в том числе и отдельного символа) в заданную строку или 0, если подстрока в строке отсутствует: write(Pos(simvz stroke));
1.13.3. Определить, есть ли в заданной строке некоторый символ
Прежде всего, заметим, что такой вариант решения:
Нц для Номер От 1 До Длин(строка) Если Строка[номер] = симв
То
Вывод «Заданный символ в строке есть»Иначе
Вывод «В строке нет заданного символа»Все кц
Ошибочный — на экран ответ будет выводиться многократно.
Неправильный результат дает также такой способ, использующий величину логического типа есть, которая фиксирует факт наличия заданного символа в заданной строке:
Нц для Номер От 1 До Длин(строка) Если Строка[номер] = симв
То есть := да иначе есть := нет все
КЦ если Есть То вывод «Заданный символ в строке есть»Иначе вывод «В строке нет заданного символа»Все
Его особенности проанализируйте самостоятельно.
Наиболее простой правильный способ решения задачи такой:
1. Подсчитать число вхождений заданного символа в заданную строку (см. задачу 1.14.1).
2. По найденному значению получить ответ.
Можно также не рассматривать весь массив, а прекратить проверки, как только встретится заданный символ (см. решение Задачи 1.14.2С использованием величины найден): номер : = 1 найден := Нет нц пока Номер <= длин(строка) И не Найден Если Строка[номер] = симв То
Найден := Да
Иначе !Переходим к следующему символу nomer := номер + 1 Все кц если Найден То
Вывод «Заданный символ в строке есть»Иначе
Вывод «В строке нет заданного символа»Все
В программе на языке Паскаль задачи также решаются просто, благодаря использованию функции Pos: If Pos(simv, stroka) >О Then Write(’Заданный символ в строке есть’) Else Write(‘В строке нет заданного символа’);
1.15. Работа с подстроками данной строки с разбиением на слова по пробельным символам.
Поиск подстроки внутри данной строки, замена найденной подстроки на другую строку
1.15.1. Определить, сколько раз в заданной строке встречается некоторая подстрока
Решение задачи во многом аналогично решению Задачи 1.14.1.Единственное отличие в том, что проверять надо не по одному символу, а по несколько. При анализу будем называть несколько последовательных символов строки термином ’’вырезка». При этом возникает вопрос: чему равен номер последнего символа строки, ■ачиная с которого следует формировать вырезку символов?
Обозначим количество символов в заданной строке— длинах, в подстроке — длина2. Рассмотрим несколько возможных значений (табл. 1.4):
Таблица 1.4
Длина! |
Длина2 |
Номер последнего символа строки для формирования вырезки |
10 |
2 |
9 |
10 |
3 |
8 |
15 |
5 |
11 |
15 |
6 |
10 |
Из табл. 1.4 можно установить, что номер последнего символа строки для формирования вырезки определяется по формуле: длина! — длина2 + 1.
Кроме того, теперь надо сравнивать с заданной подстрокой сформированные вырезки. В школьном алгоритмическом языке вырезку из строки можно получить, указав имя переменной, из которой формируется вырезка, и в квадратных скобках— начальный и конечный номера символов вырезки, например: строка[1:5], строка [10:12], строка [ki: k2 ] и т. п. В языке Бейсик для этого используется функция мю$, в языке Паскаль — функция сору. В этих функциях — три параметра: величина строкового типа, начальный номер символа для вырезки и длина вырезки.
Обратим внимание на то, что, хотя мы используем термин ’’вырезка’’, из самой строки ничего не вырезается — ее значение не изменяется.
Итак, фрагмент программы решения задачи:
Длина1 := длин(строка) длина2 := длин(подстрока) количество := 0
Нц для Номер От 1 До Длина1 — длина2 + 1
Если Строка[номер:(номер + длина2 -1)] = подстрока
То количество := количество +1
Все
Кц
Где подстрока — подстрока, число вхождений которой в строку ищется.
Dlinal := Length(Stroka);
Dlina2 := Length(podstгока);
Kolichestvo := 0;
For Nomer := 1 To Dlinal — dlina2 + 1 Do
If Copy (stroka, nomer, dlina2) = podstroka Then Kolichestvo := kolichestvo + 1;
1.15.2. Определить позицию (номер) первого вхождения некоторой подстроки в заданную строку
(если подстроки в строке нет, то вывести 0)
Сразу же заметим, что, как уже отмечалось (см. задачу 1.14.3), В языке Паскаль имеется стандартная функция Pos, используя которую можно решить данную задачу. Тем не менее считаем полезным решить ее и на Паскале, условно допустив, что такой функции нет.
Решение данной задачи также во многом аналогично решению Задачи 1.14.2. Неправильные варианты мы рассматривать не будем, а приведем два правильных варианта.
I) Длина1 := длин(строка) длина2 := длин(подстрока) искомый_номер : — О впервые := Да нц для Номер От 1 До Длина1 — длина2 + 1 Если Строка[номер:(номер + длина2 -1)] = подстрока И Впервые То Искомый_номер := номер I Следующие вхождения будут уже не первыми впервые :=Нет все
Кц
Вывод нс, Искомый_номер
[ Язык Паскаль
Dlinal := Length(Stroke);
Dlina2 := Length(podstroka);
Iskomiy_nomer := 0;
Vpervie := true;
For Nomer := 1 To Dlinal — dlina2 + 1 Do
If (Copy(stroka, nomer, dlina2) = podstroka) And Vpervie Then
Begin
Iskomiy_nomer := nomer;
{Следующие вхождения будут уже не первыми} vpervie := false
End;
(Вывод ответа}
⅛ wr i tе (is komiy_nomeг) ;
2) Длина1 := длин(строка) длина2 := длин(подстрока) искомый_номер := О номер := 1 найден := Нет
Нц пока Номер <= длина1 - длина2 + 1 И не Найден Если Строка[номер:(номер + длина2 — 1)] = подстрока
То
Искомый_номер := номер найден := Да
Иначе I Переходим к следующему символу номер := номер + 1 Все кц вывод нс, Искомый_номер
Язык Паскаль i
Dlinal := Length(Stroka);
Dlina2 := Length(podstroka);
I s komi y_nome г := О;
Naiden := false;
Nomer := 1;
While (nomer <= dlinal - dlina2 + 1) And not Naiden Do
If Copy(stroka, nomer, dlina2) = podstroka Then
Begin
I s komi y_nome r := nome r; naiden := true
End
Else {Переходим к следующему символу} nomer := nomer + 1;
{Вывод ответа}
Write (iskomiy_nomer);
Конечно, и здесь можно решить задачу, исследовав заданную строку с ее конца, точнее — с (dlinal — diina2 + ι)-ro символа.
1.15.3. Определить, есть ли в заданной строке некоторая подстрока
Наиболее простой правильный способ решения задачи такой:
1. Подсчитать число вхождений подстроки в заданную строку (см. задачу 1.15.1).
2. По найденному значению получить ответ.
Можно также не рассматривать весь массив, а прекратить проверки, как только встретится заданная подстрока (см. решение Задачи 1.14.3С использованием величины найден).
1.15.4. Удалить из заданной строки все вхождения некоторой подстроки
В программе на школьном алгоритмическом языке удалить из строки подстроку можно, присвоив вырезке с подстрокой (см. разд. 1.15.1)«пустое» значение, например для подстроки из четырех символов, начиная с 7-го: строка[7:10] :=
Еще две важные особенности программы решения задачи:
1. Поскольку в ходе обработки строки ее длина меняется, использовать оператора цикла с параметром, в конечном значении которого применяется величина длина 1 (количество символов в заданной строке), нельзя. Следует применить оператор цикла с условием следующего вида: номер <= длин(строка) — длина2 + 1
Где длина2 — количество символов в удаляемой подстроке.
2. При рассмотрении начальных номеров подстрок после нахождения искомой подстроки и ее удаления величина номер не меняется (убедитесь в этом!), а в случае, когда искомая подстрока не встретилась, — увеличивается на 1.
C учетом сказанного фрагмент программы, решающей задачу, имеет вид: номер := 1 Нц пока Номер <= длин(строка) — длина2 + 1
Если Строка[номер:(номер + длина2 —1)] = подстрока То !Встретилась искомая подстрока
I Удаляем ее строка[номер:(номер + длина2 —1)] : = «» !Величина Номер — Не меняется Иначе
I Переходим к следующему символу для проверки номер := номер + 1 Вое
Кц
Вывод нс, строка
ЬЯзыкПаскаль ιι,’ |
Nomer := 1;
While Nomer <= Length(Stroka) - dlina2 +Ido
If Copy(stroka, nomer, dlina2) = podstroka Then {Встретилась искомая подстрока.
Удаляем ее}
Delete(stroka, nomer, dlina2) {Величина Nomer — не меняется} Else
{Переходим к следующему символу для проверки} nomer := nomer + 1;
Write(stroka);
1.15.5. Заменить в заданной строке
Все вхождения некоторой подстроки на другую подстроку
Используем в программе величины:
П Строка — заданная строка;
ΓJ Подстрока! — заменяемая подстрока;
□ подстрока2 — новая подстрока;
О Длина! — количество символов в величине подстрока!;
Cl Длина2 — ТО же, В величине подстрока2.
Приводя фрагмент программы, обращаем внимание на условие в операторе цикла (см. предыдущую задачу), а также на особенности изменения величины номер: длина1 := длин(подстрока!) длина2 := длин(подстрока2) номер := 1 Нц пока Номер <= длин(строка) - длина! + 1 Если Строка[номер:(номер + длина! — 1)] = подстрока! То !Встретилась искомая подстрока! Заменяем ее строка[номер:(номер + длина! — 1)] := подстрока2 !Изменяем значение величины Номер Номер := номер + длина2 Иначе
!Переходим к следующему символу для проверки номер := номер + 1 Все кц вывод нс, Строка
В языке Паскаль для замены одной подстроки на другую следует использовать Процедуры Delete И Insert.
Dlinal := Length(podstrokal);
Dlina2 := Length(podstroka2);
Nomer := 1;
While Nomer <= Length(Stroka) - dlinal + 1 Do
If Copy(stroka, nomer, dlinal) = podstrokal Then [Встретилась искомая подстрока)
Begin
{Удаляем ее)
Delete(stroka, nomer, dlinal);
{Вставляем новую подстроку)
Insert(podstroka2, stroka, nomer);
{Изменяем значение величины Nomer} Nomer := nomer + dlina2
End
Else
{Переходим к следующему символу для проверки) nomer := nomer + 1;
Write(stroka);
В языке Бейсик для замены предназначена процедура Mid$,Однако (!) она работает, только когда число символов в обеих подстроках одинаковое.
Основные величины, используемые в программе:
□ Фраза — заданная фраза;
П слово — очередное слово фразы;
□ число слов — счетчик количества слов во фразе;
А массив слов — массив для хранения слов (его размер должен быть описан с запасом);
П номер — номер очередного рассматриваемого символа фразы.
Прежде чем приводить фрагмент программы, заметим, что:
1) структуру заданной фразы можно представить в виде (рис. 1.4):
Слово |
Пробел |
Слово |
Пробел |
Слово |
Рис. 1.4. Структура фразы
2) признак окончания очередного слова — встретившийся пробел.
Итак, фрагмент программы:
Число_слов := О номер := 1 слово :=
Нц пока Номер <= длин(фраза) Если Фраза[номер] о ” «I Если символ — не пробел
То
!Добавляем его к величине Слово Слово := слово + фраза[номер]
Иначе I Пробел
I Очередное слово кончилось
I Его номер число_слов := число_слов + 1
I Записываем его в массив массив_слов[число_слов] := слово
I Готовимся формировать новое слово слово := «»
Все
I Переходим к следующему символу для проверки номер := номер + 1 Кц
I Записываем в массив последнее слово, которое было сформировано, |но не записано (см. рис. 1.4) число_слов := число_слов + 1 массив_слов[число_слов] := слово
IЯзык Паскаль………………………….. …………………………………………………………………………………………………………………………………………………………………. .λ.. ;
Chislo_slov := 0;
Nomer := 1;
Slovo := » ;
While Nomer <= Length(fraza) Do
Begin if Fraza[nomer] <>’ ’ {Если символ — не пробел] Then
{Добавляем его к величине Slovo} Slovo := slovo + fraza[nomer] Else {Встретился пробел — очередное слово кончилось] Begin
{Его номер] chislo_slov := chislo_slov + 1; {Записываем его в массив] massiv_slov[chislo_slov] := slovo; {Готовимся формировать новое слово] slovo := ’’ End;
{Переходим к следующему символу для проверки] nomer := nomer + 1 End;
{Записываем в массив последнее слово, которое было сформировано, но не записано (см. рис. 1.4)}
Chislo_slov := chislo_slov + 1; massiv~slov[chislo_slov] := slovo;
Сформированный массив слов может быть использован для решения различных задач, таких как: нахождение слова максимальной (минимальной) длины или его номера, подсчет количества тех или иных букв в каждом слове, поиск заданных слов и т. п.
ГЛАВА 2
Другие типовые задачи программирования
Задачи, рассматриваемые в данной главе, наряду с задачами, методика решения которых обсуждена в Главе7, используются как вспомогательные при решении задач С4 ЕГЭ, а также как задачи С2.
2.1. Группа задач на выделение частей строки
В Задачах 2.1.1-2.1.4Обрабатывается задаваемая во время выполнения программы строка символов с именем строка, имеющая в общем случае следующую структуру:
C |
И |
… |
Л |
Ц |
В |
Е |
Я |
||||||||
1-е слово |
77 |
2-е слово |
П |
К-е слово |
Где IJ— пробел.
2.1.1. Выделение первого слова
Соответствующий фрагмент имеет вид:
Слово1 := «‘,!Формируемое слово (начальное значение) номер_симв := 1 I Номер очередного символа строки
Нц пока Строка[номер_симв] о «»∣∏oκa не встретится 1-й пробел! Добавляем текущий символ к «старому” значению величины Слово! Слово1 := слово1 + строка[номер_симв] !Переходим к следующему символу номер_симв := номер_симв + 1
Кц
Аналогичный фрагмент на языке Паскаль:
Slovol := {Формируемое слово (начальное значение)} nomer_simv := 1; {Номер очередного символа строки} While Stroka[nomer_simv] о ’ ‘ {Пока не встретится 1-й пробел} Do Begin
{Добавляем текущий символ к «старому» значению величины Слово!} Slovol := slovol + stroka[nomer_simv];
{Переходим к следующему символу} nomer_simv := nomer_simv + 1 End;
Можно также применить оператор цикла с постусловием: слово1 : = ”” номер_симв := 1 Нц
Слово1 := слово! + строка [номер__симв] номер_симв := номер_симв + 1
Кц_при Строка[номер_симв] = «» !Встретился 1-й пробел
Slovol :=
Nomer simv := 1;
Repeat
Slovol := slovol + stroka[потеr_simv];
Nomer_simv := nomer_simv + 1
Until Stroka[nomer_simv] = ’ ’{Встретился 1-й пробел}
Заметим здесь же, что при оформлении фрагмента в виде:
Слово1 := «»
Номер_симв := О |Начальный номер равен нулю
НЦ
Номер—Симв := номер_симв + 1
Слово1 := слово1 + строка[номер_симв]
Кц_при Строка[номер_симв] = ” ”
Пробел будет включен в состав первого слова.
Если в языке программирования имеется функция, возвращающая позицию первого вхождения в строку той или иной подстроки (а в языке Паскаль, как указывалось в Главе7, такая функция есть), то для решения задачи можно не использовать оператор цикла:
Slovol := Copy(stroka, 1, Pos(stroka, ’ ’) — 1);
Так же можно обойтись без использования оператора цикла, если длина первого слова известна (и равна длинах∕diinai):
□ в программе на школьном алгоритмическом языке:
Слово1 := строка[1:длина1]
□ в программе на Паскале:
Slovol := Copy(stroka, 1, dlinal);
Программа на языке Паскаль может быть также улучшена за счет того, что вводимые символы строки можно считывать сразу во время их ввода, используя оператор read с параметром символьного типа:
Repeat
{Считываем очередной введенный символ} read(с) ;
{и добавляем его к «старому» значению величины Slovol} Slovol := Slovol + с
Until С = ’ ’;
Это позволяет отказаться от использования переменной поте г_simv и от переменной stroka строкового типа. Однако в этом случае пробел будет включен в состав первого слова.
Обратим внимание на то, что в решениях на языке Паскаль, приведенных в [2-5, 7, 12, 16], используется именно этот способ— он более эффективен с точки зрения использования памяти по сравнению с предварительным запоминанием всей строки в целом.
2.1.2. Выделение второго слова
Для этого следует сначала пропустить первое слово: номер_симв := 1 |Номер очередного символа сороки нц
I Переходим к следующему символу номер_симв : = номер_симв + 1 I пока не встретится 1-й пробел Кц_при Строка[номер_симв] = » ” !Величина Номер_симв указывает на 1-й пробел После этого можно сформировать второе слово: слово2 := «» I Формируемое слово (начальное значение) I Переходим к 1-му символу 2-го слова номер_симв := номер_симв + 1 Нц пока Строка [номер_симв] о «» |Пока не встретится 2-й пробел
I Добавляем текущий символ к «старому» значению величины Слово2 Слово2 := слово2 + строка[номер_симв] I Переходим к следующему символу номер_симв := номер_симв + 1 Кц
В программе на языке Паскаль можно также первое слово пропустить, использовав функцию Pos (см. выше) — установить значение величины ∏omer simv, равное номеру символа после первого пробела.
Кроме того, в программе на этом языке, как и применительно к предыдущей задаче, вводимые символы строки можно считывать сразу во время их ввода, используя оператор read с параметром символьного типа: {Пропускаем первое слово} repeat
Read(с); until с = , ,;
{Формируем второе слово} Repeat
{Считываем очередной введенный символ} read(с);
{и добавляем его к «старому” значению величины Slovol} Slovol := slovol + с
Until С = ’ ’ ;
Обращаем внимание на тот факт, что и здесь второй пробел будет включен в состав второго слова.
2.1.3. Выделение двух первых слов как единой величины
В программах на Паскале, приведенных в [2-5, 7, 12, 16] для вариантов, в которых такая задача возникает, пробел между словами и пробел после второго слова включается в выделяемую величину. Поступая аналогично, можем использовать отмеченный при решении Задачи 2.1.1Вариант: слово12 := номер_симв := О! Начальный номер равен нулю Нц
I Переходим к следующему символу номер_симв := номер_симв + 1 !Переходим к следующему символу слово12 := слово12 + строка[номер_симв] КЦ—При Строка [номер_симв] = » ’’ I Первое слово и пробел после него I включены в состав величины Cjiobo^L2 I Обрабатываем второе слово
НЦ
Номер_симв := номер_симв + 1 слово12 := слово12 + строка[номер симв] Кц_при Строка[номер_симв] = «» ¾
Т I Второй пробел также учтен
Где слово12 — формируемая величина.
Можно также несколько сократить фрагмент, использовав вложенный оператор цикла: слово 12 := номер_симв : = О Нц для I От 1 До 2 Нц
Номер_симв := номер_симв + 1
Слово12 := слово12 + строка[номер_симв] Кц_при Строка[номер_симв] = ” «
Кц
Конечно, когда выделяемых слов три и более, применение вложенного оператора цикла дает больший эффект.
К………….. -~.∙o,…………………………………………………………………………………………………………………………………………………………….. .λ÷<.i....t>……………………. i.√….i:….,……………………………………………………………………………………………………………….. -……………………………………………… -**∙∙-•……………………. .∖4i……………………………………………..
{Формируем первое слово}
Repeat
{Считываем очередной введенный символ} read(с);
{и добавляем его к «старому» значению величины Slovol2}
Slovol2 := slovol2 + с
Until C=»;
{Добавляем второе слово}
Repeat
Read(с) ;
Slovol2 := slovol2 + с
Until С=’ ‘;
{Второй пробел также учтен}
2.1.4. Выделение последнего слова
В программе на школьном алгоритмическом языке задача решается аналогично Задаче 2.1.2:
1. Пропускаются все слова, кроме последнего.
2. Формируется последнее слово.
В программе на языке Паскаль после пропуска всех слов, кроме последнего, его можно считать, применив оператор readi∏ с параметром, соответствующим искомому слову: readln(slovo) ;
![]() |
В Задачах 2.1.5-2.1.8Обрабатываемая строка символов с именем строка имеет
Ц в е … я
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Где IJ— пробел; 1-е число, 2-е число и 3-е число— символы строки, представляющие собой запись чисел.
2.1.5. Выделение числа после первого слова
Будем считать, что искомым числом строка заканчивается.
Для решения задачи необходимо сначала пропустить первое слово и пробел после него:
I Пропускаем 1-е слово номер_симв := 1 !Номер очередного символа строки Нц !Переходим к следующему символу номер_симв := номер__симв + 1 !пока не встретится 1-й пробел Кц_при Строка[номер_симв] = ” ” !Величина Номер_сммв указывает на 1-й пробел! Пропускаем его номер_симв := номер_симв + 1
После этого надо получить последовательность символов-цифр и преобразовать ее в число: !Получаем символы строки, представляющие собой запись числа, I путем копирования соответствующей подстроки I и преобразуем ее в число число := лит_в_цел(строка[номер_симв : длин(строка)], успех) где длин — функция, возвращающая общее количество символов в строке; лит в цел— функция, возвращающая числовое представление числа— ее аргумента, представленного символами-цифрами (подробнее об этой функции см. в разд. 2.5.3).
Программа на языке Паскаль существенно упрощается, если после пропуска первого слова и пробела считать оставшиеся символы-цифры как единое число, применив оператор readl∏: readln(chislo);
Считанное значение присваивается величине числового типа chisio, т. е. преобразование строки в число не требуется.
Если длина числа известна (и равна длина 1/diinai), то искомое значение можно получить без использования оператора цикла, учитывая, что «местоположение” числа в строке известно: число := лит_в_цел(строка[длин(строка) — длина! + 1 : длин(строка)], успех) Соответствующий оператор в программе на языке Паскаль: Val(Copy(stroka, Length(Stroka) — dlinal + 1, dlinal), chislo, code);
2.1.6. Выделение числа после второго слова
Будем считать, что искомым числом строка заканчивается.
Задача решается аналогично предыдущей с той разницей, что пропустить необходимо два первых слова и пробел после второго слова: !Пропускаем 1-е слово номер_симв := 1 !Номер очередного символа строки Нц !Переходим к следующему символу номер_симв := номер_симв + 1 [пока не встретится 1-й пробел Кц_при Строка[номер_симв] = » ”
I Величина Номер_симв указывает на 1-й пробел I Пропускаем 2-е слово
Нц
I Переходим к следующему символу номер_симв := номер_симв + 1 I пока не встретится 1-й пробел Кц_при Строка[номер_симв] = «»I Пропускаем 2-й пробел номер_симв : = номер_симв + 1 I Получаем символы строки, представляющие собой запись числа, I путем копирования соответствующей подстроки I и преобразуем ее в число число := лит_в_цел(строка[номер_симв : длин(строка)], успех)
В программе на языке Паскаль можно также после пропуска слов и пробелов считать оставшиеся символы-цифры как единое число: readln(chislo);
Если длина числа известна, то искомое числовое значение можно получить без использования оператора цикла (см. предыдущую задачу и разд. 1.15.1).
2.1.7. Выделение двух чисел после второго слова
Будем считать, что количество цифр в каждом числе известно и равно соответственно длина1(dlinal) И длина2(dlina2).
Соответствующий фрагмент:
I Пропускаем два первых слова I и второй пробел… (см. предыдущую задачу) I Получаем первое число число1 := лит_в_цел(строка[номер_симв : номер_симв + длина! — 1], успех) ,⅛∣Пропускаем первое число и пробел после него Номер_симв := Номер_симв + Длина1 + 1 I Получаем второе число число2 := лит_в_цел(строка[номер_симв : номер_симв + длина2 — 1], успех)
В программе на языке Паскаль можно также после пропуска слов и пробелов считать оставшиеся символы-цифры как два отдельных числа: readln(chislol, chislo2);
Если длина чисел известна, то необходимые значения можно получить, зная их «местонахождение» в конце строки (см. выше).
2.1.8. Выделение трех чисел после второго слова
Такая задача, используемая, например, в [3], решается аналогично.
Задания для самостоятельной работы
1. Задана строка с информацией об ученике в формате:
<Фамилия><Номер школы>
Где <Фамилия>— значение, состоящее не более чем из 30 символов без пробелов; <номер школы> — целое число в диапазоне от 1 до 99. Эти данные записаны через один пробел (т. е. всего в строке один пробел).
Получить фамилию ученика:
1) включая пробел после нее;
2) без указанного пробела.
Задачу 2) решить также для случая, когда длина величины <Фамилия>известна.
2. Задана строка с информацией о стоимости бензина на АЗС в формате:
<Компания><Улица><Цена>
Где <компания>— строка, состоящая не более чем из 20 символов без пробелов; <Улица> — строка, состоящая не более чем из 20 символов без пробелов; <цена> — целое число в диапазоне от 1000 до 3000, обозначающее стоимость одного литра бензина в копейках. <компания>и <Улица>, <Улица>и <цена>разделены ровно одним пробелом (т. е. всего два пробела).
Получить название улицы, на которой находится данная АЗС.
Задачу решить двумя способами:
1) с использованием оператора цикла;
2) без его использования.
3. Задана строка с информацией об ученике в формате:
<Фамилия><Имя><0ценка>
Где <Фамилия> — значение, состоящее не более чем из 30 символов без пробелов; <имя>— строка, состоящая не более чем из 20 символов без пробелов; <оценка> — целое число в диапазоне от 2 до 5. Эти данные записаны через один пробел, причем ровно один между каждой парой (т. е. всего два пробела в строке).
Получить фамилию и имя ученика как одну величину:
1) включая пробелы до и после имени;
2) без пробела после имени.
4. Задана строка с информацией о футбольной команде в формате:
<Название><Количество>
Где <название> — значение, состоящее не более чем из 20 символов без пробелов; <количество> — число раз, которое команда участвовала в чемпионате. Эти данные записаны через один пробел (т. е. всего в строке один пробел).
Определить, сколько раз данная команда участвовала в чемпионате.
4 Зак. 517
5. Задана строка с информацией о городе в формате:
<Название города><Год основания>
Где <название города> — значение, состоящее не более чем из 20 символов без пробелов; <год основания>— четырехзначное число. Эти значения записаны через один пробел (т. е. всего в строке один пробел).
Определить год основания данного города. Задачу решить без использования оператора цикла.
6. Задана строка с информацией об ученике в формате:
<Фамилия><Имя><Номер школы>
Где <Фамилия> — значение, состоящее не более чем из 30 символов без пробелов; <имя>— строка, состоящая не более чем из 20 символов без пробелов; <номер шко - лы> — целое число в диапазоне от 1 до 1599. Эти данные записаны через один пробел, причем ровно один между каждой парой (т. е. всего три пробела в строке).
Определить номер школы.
7. Задана строка с информацией об ученике в формате:
<Фамилия><Имя><Год рождения>
Где <Фамилия> — значение, состоящее не более чем из 20 символов без пробелов; <имя>— строка, состоящая не более чем из 15 символов без пробелов; <год рожде - ния>— четырехзначное число. Эти значения записаны через один пробел (т. е. всего в строке два пробела).
Определить год рождения данного ученика. Задачу решить без использования оператора цикла.
8. Задана строка с информацией о марке и стоимости бензина на АЗС в формате:
<Компания><Улица>
Где <компания> — строка, состоящая не более чем из 20 символов без пробелов; <Улица> — строка, состоящая не более чем из 20 символов без пробелов;
Получить марку и стоимость бензина.
9. Задана строка с информацией об оценках ученика по 5-балльной системе по трем предметам в формате:
<Фамилия><Имя><Оценка1><0ценка2><ОценкаЗ>
Где каждые значения отделены друг от друга одним пробелом (т. е. всего в строке четыре пробела).
Определить каждую из оценок.
Задачу решить двумя способами:
1) с использованием оператора цикла;
2) без его использования.
2.2. Группа задач на подсчет количества каждого из значений
Прежде чем обсуждать задачи данной группы, решим задачу подсчета количества чисел в заданной последовательности, равных некоторому числу. Решение последней задачи во многом аналогично решению такой же задачи применительно к массиву (см. разд. 1.11.2).
I Ввод общего количества чисел последовательности п Ввод П количество := О
НЦ ДЛЯ 1 от 1 до п
I Ввод очередного числа а последовательности Ввод А
I Если оно равно заданному числу X Если А = X То
I Учитываем его в искомом количестве количество := количество + 1 Вое кц !Вывод ответа Вывод нс, ’’Количество чисел, равных X: «, количество
Λ.w…,√.∙..√.ΛΛi…….
{Ввод общего количества чисел последовательности л} readln(п);
Rolichestvo := 0;
For I : = 1 To N Do
Begin
{Ввод очередного числа а последовательности} readln(п);
{Если оно равно заданному числу X}
If А = X Then {Учитываем его в искомом количестве} Rolichestvo := Rolichestvo + 1; {или Inc(Rolichestvo)} {Вывод ответа} write(’Количество чисел, равных X: ,, Rolichestvo);
2.2.1. Подсчет количества каждой из цифр в заданной последовательности
Задача: ’’Даны П цифр. Подсчитать количество каждой из них. Массив для хранения цифр заданной последовательности не использовать”.
Анализ решения
Прежде всего, учитывая требование, связанное с массивом цифр, каждую цифру последовательности следует ’’обрабатывать” сразу после ее ввода. Это же надо делать и с другими аналогичными данными в задачах, рассматриваемых ниже.
Далее, ясно, что нужно получить 10 значений. Но хранить искомое количество каждой из цифр с помощью десяти переменных величин нерационально — лучше использовать массив кол цифр из десяти элементов с индексами от 0 до 9.
Обсудим, как учесть очередную цифру в этом массиве.
Проверка каждой из цифр с использованием оператора выбора (варианта) следующим образом:
Выбор
При Цифра = 0:
!Увеличиваем количество цифр 0 кол_цифр[0] := кол_цифр[ 0 ] +1 При Macc∏Bl[i] = 1:
I Увеличиваем количество цифр 1 кол_цифр[1] := кол_цифр[1] + 1
При Массив1[1] = 9:
I Увеличиваем количество цифр 9 кол_цифр[9] := кол_цифр[9] + 1 Все
Кц
— также является нерациональной.
Подумаем, значение какого элемента массива кол цифр должно быть увеличено на 1, если очередная цифра равна цифра? Ответ— элемента с индексом цифра. Это позволяет записать оператор для подсчета количества каждой из цифр в последовательности очень компактно: Ввод П Нц для I Оф1 До П
!Вводим очередную цифру Ввод Цифра
!Увеличиваем ее ’’счетчик» на 1 кол_цифр[цифра] := кол_цифр[цифра] + 1 КЦ
Readln(п);
{Рассматриваем все заданные цифры} For I := 1 To N Do
Begin
{Вводим очередную цифру}
Readln(zifra);
{Увеличиваем ее «счетчик» на 1}
Inc(kol_zifr[zifга])
End;
Примечание
Как уже отмечалось в Главе 1,В школьном алгоритмическом языке начальное присваивание переменным, в том числе и элементам массива, нулевых значений не происходит, поэтому следует предварительно обнулить все элементы массива кол цифр.
2.2.2. Подсчет количества каждой из цифр в заданной строке. Вариант 1
Задача:«Дана строка, состоящая из цифр. Подсчитать количество каждой из цифр. Массив для хранения отдельных цифр заданной строки не использовать».
Анализ решения
Здесь, как и в предыдущей задаче, искомое количество каждой из цифр запишем в массив кол цифр из 10 элементов с индексами от 0 до 9.
Идея решения задачи достаточно понятная:
1) выделить отдельную цифру строки в виде числа (пусть ее имя — цифра);
2) учесть ее в массиве кол цифр.
Соответствующий фрагмент:
I Ввод строки Ввод Строка I Обнуляем элементы массива Кол_цифр Нц для 1 От 0 До 9 кол_цифр[1] := 0 Кц
I Рассматриваем все символы заданной строки Нц для I От 1 До Длин(строка)
!Преобразуем I-й символ в число цифра := лит_в_цел(строка[i], успех) I Увеличиваем счетчик этой цифры на 1 кол_цифр[цифра] := кол_цифр[цифра] + 1 Кц
{Ввод строки}
Readln(Stroka);
{Обнуляем элементы массива Kol_Zifr} For I := 0 To 9 Do Kol_zifr(i] := 0; {Рассматриваем все символы заданной строки} For I := 1 To Length(Stroka) Do
Begin
{Преобразуем символ-цифру Stroka[1] в число}
Val(stroka[i], zifra, code);
{Учитываем его в массиве Kol_Zifr}
Inc(kol_zifг[zifra] ) End;
Программа на языке Паскаль может быть упрощена за счет того, что значениями индексов элементов массива koi_zifr в этом языке могут быть данные символьного типа. Это позволит отказаться от преобразования символов в число:
Var
Kol_zifr: array [‘О’..’9’] of byte;
BEGIN
{Ввод строки} readln(stroka);
{Рассматриваем все символы заданной строки}
For I := 1 To Length(Stroka) Do
{Для символа-цифры stroka[i] увеличиваем на 1
Его значение в массиве Kol_Zifr}
Inc(kol_zifr[stroka[i]] ) ;
Как отмечалось в Разд. 2.1.1,В программе на языке Паскаль можно отдельно не вводить всю заданную строку и потом обрабатывать ее, а выделять символы-цифры сразу во время ввода исходных данных. Это можно сделать благодаря использованию оператора read, аргументом которого является величина символьного типа (char):
Var
Dlina: integer; simv: char; …
BEGIN
Write (’Задайте длину строки ‘); read(dlina);
{Считываем по одному символу заданной строки} i := 1;
Writein(’Введите строку ’);
Repeat
Read(simv);
{Для очередного символа
Увеличиваем на 1 его значение в массиве Kol_Zifr}
Inc(kol_zifr[simv]);
{Переходим к следующему символу} i := i + 1
Until I > dlina;
Аналогично на языке Паскаль можно решать задачи, в которых известна не длина строки, а ее последний символ. В этом случае величина dlina не используется:
Var Simv: char; . . .
BEGIN
Writein (’Введите строку ’);
{Считываем первый символ} read(simv);
While Simv о posled Do
Begin
{Для очередного символа
Увеличиваем на 1 его значение в массиве Kol_Zifr}
Inc(kol_zifг[simv]);
{Считываем следующий символ} read(simv);
End;
Где posled — последний символ строки.
Заметим, что применение оператора цикла с постусловием:
Writein(’Введите строку ’) ;
Repeat
{Считываем очередной символ} read(simv);
{Для очередного символа
Увеличиваем на 1 его значение в массиве Kol_Zifr}
Inc(kol_zifr[simv]);
Until Simv = posled;
В данном случае невозможно, т. к. для последнего символа — «нецифры» нельзя выполнить процедуру inc.
2.2.2. Подсчет количества каждой из цифр в заданной строке. Вариант 2
Задача». ’’Дана строка, в которой есть цифры. Подсчитать количество каждой из цифр. Массив для хранения отдельных цифр заданной строки не использовать».
Анализ решения
Здесь новым является то, что в заданной строке, кроме цифр, имеются и другие символы, и наша задача— выделить и обработать только символы-цифры. Выделение цифр можно провести так:
I Ввод строки
Ввод Строка
I Рассматриваем все символы заданной строки Нц для I От 1 До Длин(строка)
I Если i-й символ — цифра
Если Строка[i] >= «О»И Строка[i] <= "9"
То
I Преобразуем его в число цифра := лит_в_цел(строка[i], успех) !Учитываем цифру в массиве Кол_цифр Кол_цифр[цифра] := кол_цифр[цифра] + 1 Вое
Кц
{Ввод строки}
Readln(Stroka);
For I := 1 To Length(Stroka) Do
If (simv >= ‘0’) And (simv <= '9') {Если I-й символ — цифра} Then Inc(kol_zifr[stroka[i]]);
Задачи такого типа, в которых известна не длина строки, а ее последний символ, на языке Паскаль можно решать так же, как и предыдущую задачу:
Writein(‘Введите строку ‘);
{Считываем первый символ}
Read(simv);
While Simv о posled Do
Begin
If (s imv >= ‘О’) And (s imv <= ' 9 ')
Then Inc(kol_zifr[simv]);
{Считываем следующий символ}
Read(simv);
End;
Где posled — последний символ строки.
Интересно, что в этой задаче применение оператора цикла с постусловием возможно:
Writein(‘Введите строку ‘);
Repeat
{Считываем очередной символ}
Read(simv);
If (simv >= ‘0’) And (simv <= '9')
Then Inc(kol_zifr[simv]);
Until Simv = posled;
2.2.3. Подсчет количества каждой из букв в заданной строке.
Вариант 1
Задача: ’’Дана строка, состоящая из прописных букв латинского алфавита. Подсчитать количество каждой из букв алфавита. Массив для хранения отдельных букв заданной строки не использовать”.
Анализ решения
В программе на Паскале задача решается во многом аналогично первому варианту Задачи 2.2.2,Если использовать массива koi~bykv с индексами от ”а” до ”Z”: Var
Kol_bykv: array [,A,..,Z,] of byte;
BEGIN
{Ввод строки} readln(stroka);
{Рассматриваем все буквы заданной строки} For I := 1 To Length(Stroka) Do
{Для буквы stroka[i] увеличиваем на 1 ее значение в массиве ko2_bykv} Inc(kol_bykv[stroka[i]]);
В программе на школьном алгоритмическом языке заполняемый массив кол букв должен иметь индексы, соответствующие кодам прописных букв латинского алфавита:
Цел таб Кол_букв[65:90]
А в программе должны использоваться коды букв:
I Ввод строки Ввод Строка! Обнуляем элементы массива Кол_букв Нц для I От 65 До 90 кол_букв[i] := О
КЦ
I Рассматриваем все буквы заданной строки Нц для I От 1 До Длин(строка) !Выделяем i-ю букву буква := строка[i]
I Увеличиваем счетчик этой буквы на 1 кол_букв[код(буква)] := кол_букв[код(буква)] + 1 КЦ
2.2.3. Подсчет количества каждой из букв в заданной строке. Вариант 2
Задача: ’’Дана строка, в которой есть прописные буквы латинского алфавита. Подсчитать количество каждой из букв алфавита. Массив для хранения отдельных букв не использовать”.
Анализ решения
Здесь, как и в аналогичной Задаче 2.2.2,Особенность в том, что в заданной строке кроме прописных букв латинского алфавита имеются и другие символы, и наша задача — выделить и обработать только нужные буквы.
Это можно сделать так:
I Ввод строки
Ввод Строка
I Рассматриваем все символы заданной строки
Нц для I От 1 До Длин(строка)
I Если 1-й символ — прописная буква латинского алфавита Если Строка[i] >= «А»И Строка[i] <= nZn
То
Соответствующий фрагмент на языке Паскаль:
{Ввод строки} readln(Stroka);
{Рассматриваем все символы заданной строки}
For I + 1 To Length(Stroka) Do
{Если 2-й символ — прописная буква латинского алфавита} If (stroka[i] >= ’A’) And (stroka[i] <= 'Z') Then
Примечание
Если в двух последних задачах предполагается, что в строке есть строчные буквы, а искомое количество каждой из букв необходимо найти без учета регистра, то в программах на Паскале можно использовать функцию UpCase или LowerCase.
2.2.4. Подсчет количества каждого из числовых значений в заданной последовательности чисел
Задача: ’’Даны П чисел со значениями от О до 50. Подсчитать количество каждой из них. Массив для хранения чисел заданной последовательности не использовать”.
Задача решается аналогично Задаче 2.2.1(используется массив кол чисел/koi chisei из 51 элемента).
2.2.5. Подсчет количества каждого из числовых значений в заданном наборе строк
Задача:«Даны П строк, в каждой из которых находится информация в формате:
<Подстрока><Число>
Где <подстрока> — последовательность не более чем из 30 букв без пробелов; <число> — целое число в диапазоне от 1 до 99. Эти данные записаны через пробел (т. е. всего один пробел в каждой строке). Подсчитать количество каждого из чисел».
Анализ решения
Общая схема решения задачи заполнения массива с количествами каждого из значений от 1 до 99:
1. Ввод значения п
2. Цикл для 1 от 1 до л
2.1. Ввод 2-й строки
2.2. Выделение числа
2.3. Учет этого числа в массиве ’’счетчиков» конец цикла
Возможные методы выполнения этапа 2.2 рассмотрены в Разд. 2.1.Учет числа в массиве «счетчиков» проводится так же, как и в Задачах 2.2.1-2.2.4(естественно, с учетом диапазона значений).
Здесь же заметим, что в программе на Паскале использование массива с индексами строкового типа от «1»до «99»недопустимо.
Задания для самостоятельной работы
1. Известны оценки каждого из 25 учеников класса на контрольной работе по физике. Подсчитать количество двоек, троек, четверок и пятерок. Массив для хранения оценок и четыре переменные для хранения искомых значений не использовать.
2. Дана строка, состоящая из цифр 3, 4, 5, 6, 7. Подсчитать количество каждой из таких цифр. Массив для хранения отдельных цифр заданной строки и пять переменных для хранения искомых значений не использовать.
3. Дана строка, в которой есть числовые значения. Подсчитать количество каждой из цифр. Массив для хранения отдельных цифр заданной строки не использовать.
4. Дан текст, состоящий из не более чем 250 прописных букв латинского алфавита. Подсчитать количество каждой из букв алфавита. Массив для хранения отдельных букв заданной строки не использовать.
5. Дан текст, состоящий из не более чем 250 букв латинского алфавита. Подсчитать количество каждой из прописных букв алфавита. Массив для хранения отдельных букв заданной строки не использовать.
6. Даны П строк, в каждой из которых находится информация в формате:
<Фамилия><Номер школы>
Где <Фамилия>— строка, состоящая не более чем из 30 символов без пробелов; <номер школы> — целое число в диапазоне от 1 до 99. Эти данные записаны через пробел (т. е. всего один пробел в каждой строке).
Подсчитать количество учеников в каждой из школ. Массив для хранения номеров школ не использовать.
2.3. Группа задач на подсчет количества и вывод значений, удовлетворяющих некоторому условию
2.3.1. Подсчет количества тех чисел последовательности, которые удовлетворяют некоторому условию
Задача в общем виде’. ’’Даны П чисел. Определить количество чисел, удовлетворяющих некоторому условию».
Анализ решения
В приведенном далее фрагменте решения задачи <условие> — заданное условие для подсчета чисел (это может быть равенство, неравенство, сложное условие и т. п.), количество — искомое количество:
I Ввод общего количества чисел последовательности П Ввод П количество := О Нц для I От 1 До П
I Ввод очередного числа а
Ввод А…
I Если заданное условие соблюдается Если <условие>То
I Учитываем число а в искомом количестве количество := количество + 1 Вое кц вывод Hcz«Количество чисел, удовлетворяющих условию, равно «, количество Заметим, что <условие> зависит от: 1) значения числа а;
2) Значения числа а и от порядкового номера i.
Если оно зависит только от порядкового номера i, то задача может быть решена без использования оператора цикла (убедитесь в этом!).
В случае если обрабатываемое число является частью строки, необходимо предварительно нужное значение из строки (см. типовые задачи группы 2.1).
Применительно к массиву чисел задача решалась в Главе 1 (см. разд. 1.11.2).
{Ввод общего количества чисел последовательности n} readln(п);
Rolichestvo := 0;
For i := 1 to n do
Begin
{Ввод очередного числа а} readln(а);
{Если заданное условие соблюдается} If <условие>Then
{Учитываем число А в искомом количестве}
Kolichestvo := kolichestvo + 1 {или inc (Rolichestvo)} End;
Write(‘Количество чисел, удовлетворяющих условию, равно ‘, Rolichestvo);
Задача в общем виде’. ’’Даны два массива. Вывести на экран те элементы первого массива, которые соответствуют элементам второго массива с заданными свойствами”.
Пример задачи’. ’’Даны два массива с информацией о 25 людях: 1) с их фамилиями;
2) со значениями их роста в сантиметрах.
Вывести на экран фамилии людей, рост которых превышает 170 см. Известно, что такие люди среди представленных имеются».
Решение в общем виде
Соответствующий фрагмент:
Нц для i от 1 до n[XI]
I Если очередной элемент второго массива обладает заданными свойствами Если <условие, связанное со вторым массивом>
То
[Выводим соответствующий элемент 1-го массива Вывод Маесив1[i], «»Вое кц
Решение для приведенной задачи
Нц для I От 1 До П Если Pocτ[i] > 170
То вывод Фамилия[i], «»Все
Кц
Где рост и фамилия — заданные массивы.
Язык Паскаль
For i := 1 to n do
{Если очередной элемент второго массива обладает заданными свойствами}
If <условие, связанное со вторым массивом>
Then {Выводим соответствующий элемент первого массива} write(massivl[i], ‘ ’);
Примечание
При решении задачи такого типа с использованием языка Паскаль можно вместо двух массивов использовать один массив с данными типа запись.
В заключение заметим, что методика решения задач на подсчет количества макси — мал ьных/минимальных значений рассмотрена в Разд. 2.4.
Задания для самостоятельной работы
1. Известны оценки 22 учеников класса по алгебре. Определить количество четверок.
2. Дан массив целых чисел из 12 элементов. Определить количество чисел, оканчивающих нулем (известно, что такие числа в массиве есть).
3. Дан массив натуральных чисел из 10 элементов. Вывести на экран те из них, которые кратны трем, а на следующей строке — количество таких чисел. Известно, что числа, о которых идет речь, в массиве есть.
4. В массиве записана информация о росте каждого из 20 человек (в см). Вывести значения роста, большие 190 см. Если таких значений в массиве нет, вывести сообщение «Нет людей с таким ростом».
5. Дан массив из 15 элементов с вещественными значениями. Вывести отрицательные элементы. Если такой элемент единственный, то на следующей строке вывести его индекс. Известно, что в массиве есть как минимум один отрицательный элемент.
6. В массиве записано количество участников олимпиады из каждой из школ с номерами от 10 до 20. Вывести номера школ, число участников из которых больше двух, а затем на отдельной строке — количество таких школ.
7. В массиве записана информация о количество баллов, набранных каждым из 20 учащихся на ЕГЭ по информатике. Вывести условные номера учащихся, набравших более 90 баллов (условный номер соответствует порядковому номеру баллов учащихся в массиве). Если таких учащихся нет, вывести сообщение «Нет таких учащихся».
8. Дан массив с общим количеством учащихся в каждой из параллелей школы (от 1-й до 11-й). Вывести номера параллелей, общее число учащихся в которых превышает 60. Если такая параллель — единственная, то на следующей строке вывести число учащихся в ней. Известно, что в массиве есть как минимум одна параллель с указанным числом учащихся.
9. В массиве записаны значения роста 15 человек в формате???.??, где? — цифра. Определить число людей, рост которых равен среднему значению роста.
10. Даны два массива с информацией о 30 участниках олимпиады по информатике:
1) с их фамилиями;
2) с суммой набранных ими баллов.
Вывести на экран фамилии участников, набравших не более 30 баллов. Известно, что такие учащиеся имеются.