Выполнение задания на обработку строк: String9
Особенности выполнения заданий на обработку символов и строк рассмотрим на
примере задания String9.
String9°. Дано четное число N (> 0)
и символы C1 и C2. Вывести строку длины N,
которая состоит из чередующихся символов C1 и C2,
начиная с C1.
Создание программы-заготовки и знакомство с заданием
Проект-заготовку для решения задания String9 можно создать с помощью
модуля PT4Load. В созданный проект будет входить файл с именем String9; его
расширение зависит от выбранного языка: .cs для C#, .vb для VB.NET и .fs для F#. Приведем
текст этого файла без начальных директив:
[C#]
public static void Solve()
{
Task("String9");
}
[VB.NET]
Sub Solve()
Task("String9")
End Sub
[F#]
let Solve = pt.Task "String9"
После запуска программы на экране появится окно задачника.
На рисунке приведены два варианта представления окна (в режиме с динамической
и с фиксированной компоновкой) в случае использования языка C#:
Данные символьного и строкового типа в окне задачника заключаются в
кавычки; это позволяет, в частности, отличить числовые данные (например, 2) от
символьных и строковых данных, содержащих цифры (например, строки "2"). Кроме
того, кавычки дают возможность увидеть пробелы, находящиеся в начале или в конце
строк.
Ввод исходных данных
Добавим в процедуру Solve фрагмент, обеспечивающий ввод исходных данных.
При этом будем учитывать, что данные символьного типа надо вводить с помощью
функции GetChar, а данные целого типа с помощью функции GetInt:
[C#]
public static void Solve()
{
Task("String9");
char c1 = GetChar(), c2 = GetChar();
int n = GetInt();
}
[VB.NET]
Sub Solve()
Task("String9")
Dim c1 = GetChar(), c2 = GetChar(), n = GetInt()
End Sub
[F#]
let Solve = pt.Task "String9"
let c1 = string(pt.GetChar())
let c2 = string(pt.GetChar())
let n = pt.GetInt()
Мы намеренно ввели данные не в том порядке, в котором они указаны в окне
задачника. В решении на языке F# мы сразу преобразовали введенные символы
к типу string, так как в дальнейшем они будут использоваться в строковых выражениях.
Запуск нового варианта программы уже не будет считаться ознакомительным,
поскольку в программе выполняется ввод исходных данных. Так как порядок ввода
исходных данных является ошибочным, этот вариант решения будет признан
неверным и приведет к сообщению «Неверно указан тип при вводе исходных
данных. Для ввода 1-го элемента (целого типа) использована переменная символьного
типа».
Напомним правило, определяющее порядок ввода и вывода данных для
задачника Programming Taskbook: ввод и вывод данных производится по строкам
(слева направо), а строки просматриваются сверху вниз.
Исправим процедуру Solve, изменив в ней порядок ввода исходных данных:
[C#]
int n = GetInt();
char c1 = GetChar(), c2 = GetChar();
[VB.NET]
Dim n = GetInt(), c1 = GetChar(), c2 = GetChar()
[F#]
let n = pt.GetInt()
let c1 = string(pt.GetChar())
let c2 = string(pt.GetChar())
Теперь исходные данные вводятся правильно. Первый этап решения задачи пройден.
Формирование требуемой строки и ее вывод
Для формирования нужной строки воспользуемся операцией сцепления строк («+»
в языке C# и F#, «&» в языке VB.NET), после чего выведем полученную
строку методом Put:
[C#]
public static void Solve()
{
Task("String9");
int n = GetInt();
char c1 = GetChar(), c2 = GetChar();
string s = "";
for (int i = 0; i < n; i++)
s = s + c1 + c2;
Put(s);
}
[VB.NET]
Sub Solve()
Task("String9")
Dim n = GetInt(), c1 = GetChar(), c2 = GetChar()
Dim s = ""
For i = 1 To n
s = s & c1 & c2
Next
Put(s)
End Sub
[F#]
let Solve = pt.Task "String9"
let n = pt.GetInt()
let c1 = string(pt.GetChar())
let c2 = string(pt.GetChar())
let mutable s = ""
for i in 1 .. n do
s <- s + c1 + c2
pt.Put(string s)
В варианте для VB.NET обратите внимание на новую для языка Visual Basic
возможность описания переменной цикла непосредственно в заголовке цикла.
Операция сцепления в F# работает только для строковых переменных;
именно поэтому мы выполняем преобразование введенных символов к типу string.
Также заметим, что в языке F# переменные по умолчанию считаются
неизменяемыми, поэтому для изменения строковой переменной s необходимо объявить ее с ключевым словом mutable,
а при изменении использовать оператор <- вместо =.
При выполнении этой программы в области результатов будет выведена строка,
оканчивающаяся особым символом красной звездочкой, например:
"a1a1a1a1a1*
Красная звездочка, расположенная в конце строки, отображаемой на экране,
означает, что длина полученной строки превышает длину контрольной (т. е.
«правильной») строки. Для того чтобы увидеть на экране всю
полученную строку, достаточно подвести курсор мыши к строке со звездочкой; при
этом полный текст строки появится во всплывающей подсказке.
Правильное решение, его тестирование и просмотр результатов
Ошибка в предыдущей программе возникла из-за неверного указания количества
итераций цикла. Действительно, на каждой итерации к строке добавляется по два
символа, поэтому после n итераций строка будет содержать 2n символов (а не n, как
требуется в задании).
Для исправления ошибки достаточно вдвое уменьшить число итераций, изменив
заголовок цикла следующим образом (обратите внимание на использование
операции целочисленного деления \ в заголовке цикла для языка VB.NET):
[C#]
for (int i = 0; i < n / 2; i++)
[VB.NET]
For i = 1 To n \ 2
[F#]
for i in 1 .. n / 2 do
После запуска исправленной программы и успешного прохождения 5 тестов
мы получим сообщение «Задание выполнено!». Нажав клавишу [F2],
мы можем вывести на экран окно результатов, в
котором будут перечислены все наши попытки решения задачи (заглавная буква «S»,
которая указывается перед датой, означает, что при выполнении задания
использовался язык C# «C Sharp»):
String9 S24/03 11:37 Ознакомительный запуск.
String9 S24/03 11:48 Неверно указан тип при вводе исходных данных.
String9 S24/03 11:49 Запуск с правильным вводом данных.
String9 S24/03 11:49 Ошибочное решение.
String9 S24/03 11:52 Задание выполнено!
В случае выполнения задания на языке VB.NET перед датой указывается буква
«B» «Basic», а в случае языка F# буква «F»
(для обозначения языков платформы .NET в окне результатов используются заглавные
буквы).
[C#]
public static void Solve()
{
Task("String9");
int n = GetInt();
char c1 = GetChar(), c2 = GetChar();
StringBuilder s = new StringBuilder(n);
s.Length = n;
for (int i = 0; i < n / 2; i++)
{
s[2 * i] = c1;
s[2 * i + 1] = c2;
}
Put(s.ToString());
}
[VB.NET]
Sub Solve()
Task("String9")
Dim n = GetInt(), c1 = GetChar(), c2 = GetChar()
Dim s = New StringBuilder(n)
s.Length = n
For i = 0 To n \ 2 - 1
s(2 * i) = c1
s(2 * i + 1) = c2
Next
Put(s.ToString())
End Sub
[F#]
let Solve = pt.Task "String9"
let n = pt.GetInt()
let c1 = pt.GetChar()
let c2 = pt.GetChar()
let s = new StringBuilder(n)
s.Length <- n
for i in 0 .. n / 2 - 1 do
s.[2 * i] lt;- c1
s.[2 * i + 1] lt;- c2
pt.Put(string s)
[F#]
let Solve = pt.Task "String9"
let n = pt.GetInt()
let c1 = string(pt.GetChar())
let c2 = string(pt.GetChar())
let rec result k s =
if k > 0 then
result (k-1) s + c1 + c2
else
s
pt.Put(result (n / 2) "")
|