Programming Taskbook


E-mail:

Пароль:

Регистрация пользователя   Восстановление пароля

English

ЮФУ SMBU

Электронный задачник по программированию

©  М. Э. Абрамян (Южный федеральный университет, Университет МГУ-ППИ в Шэньчжэне), 1998–2024

 

Решения | C и C++ | Обработка строк

PrevNext


Выполнение задания на обработку строк: String9

Особенности выполнения заданий на обработку символов и строк рассмотрим на примере задания String9.

String9°. Дано четное число N (> 0) и символы C1 и C2. Вывести строку длины N, которая состоит из чередующихся символов C1 и C2, начиная с C1.

Создание программы-заготовки и знакомство с заданием

Проект-заготовку для решения задачи String9 можно создать с помощью модуля PT4Load. Приведем текст функции Solve из файла String9.cpp, входящего в созданный проект (именно в эту функцию требуется ввести решение задачи):

[C/C++]

void Solve()
{
    Task("String9");
}

Функция Solve для языка C выглядит аналогичным образом.

После запуска программы на экране появится окно задачника. На рисунке приведены два варианта представления окна — в режиме с динамической и с фиксированной компоновкой:


Символьные данные в окне задачника заключаются в одинарные и двойные кавычки соответственно; это позволяет отличить числовые данные (например, 2) от символьных и строковых данных, содержащих цифры (например, символа '2'). Кроме того, кавычки дают возможность увидеть пробелы, находящиеся в начале или в конце строк.

Символьные данные в языках C и C++ имеют тип char, строковые данные могут храниться в виде символьных массивов (типа char* или char[]), а также, для языка C++, в виде объектов-строк типа std::string.

Ввод исходных данных

Добавим в функцию Solve фрагмент, обеспечивающий ввод исходных данных. Для ввода данных типа char и int на языке C необходимо использовать функции GetC и GetN. Эти же функции можно применять и в программах на языке C++, однако в них проще воспользоваться специальным потоком ввода-вывода pt:

[C/C++]

Task("String9");
int n;
char c1, c2;
GetC(&c1);
GetC(&c2);
GetN(&n);

[C++]

Task("String9");
int n;
char c1, c2;
pt >> c1 >> c2 >> n;

Мы намеренно ввели данные не в том порядке, в котором они указаны в окне задачника.

Запуск нового варианта программы уже не будет считаться ознакомительным, поскольку в программе выполняется ввод исходных данных. Так как порядок ввода исходных данных является ошибочным, этот вариант решения будет признан неверным и приведет к сообщению «Неверно указан тип при вводе исходных данных. Для ввода 1-го элемента (целого типа) использована переменная символьного типа».

Напомним правило, определяющее порядок ввода и вывода данных для задачника Programming Taskbook: ввод и вывод данных производится по строкам (слева направо), а строки просматриваются сверху вниз.

Исправим функцию Solve, изменив в ней порядок ввода исходных данных:

[C/C++]

GetN(&n);
GetC(&c1);
GetC(&c2);

[C++]

pt >> n >> c1 >> c2;

Теперь исходные данные вводятся правильно. Первый этап решения задачи пройден.

Формирование требуемой строки и ее вывод

При решении задач на обработку строк на языке C необходимо использовать символьные массивы и набор специальных функций, входящих в стандартную библиотеку C (и описанных в заголовочном файле <string.h>). Полученное решение можно использовать и для языка C++ (подключив к программе заголовочный файл <cstring>), однако для этого языка удобнее использовать стандартный класс std::string (описанный в заголовочном файле <string>). Напомним, что для подключения стандартных заголовочных файлов надо использовать директиву #include, например:

[C]

#include <string.h>

[C++]

#include <string>

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

[C++]

using namespace std;

Заметим, что эта директива автоматически добавляется во все создаваемые заготовки для заданий на языке C++.

Вначале приведем решение на языке C, которое можно использовать и для языка C++. В нем мы опишем символьный массив s достаточно большого размера (при выполнении любых заданий, связанных с обработкой строковых данных, достаточно использовать символьные массивы размера 80) и заполним его поэлементно, не забыв добавить в конец записанного набора символов особый нулевой символ '\0', являющийся признаком конца строки (вместо нулевого символа достаточно использовать число 0). Для вывода полученной строки в задачнике предусмотрена функция PutS (функция для ввода строки, записывающая строку в символьный массив, имеет имя GetS).

[C/C++]

char s[80];
int p = 0;
for (int i = 0; i < n; ++i)
{
    s[p++] = c1;
    s[p++] = c2;
}
s[p] = 0;
PutS(s);

Для языка C++ можно получить более краткий вариант решения, если использовать тип string и определенную для него операцию «+» сцепления строк (при описании переменной типа string в нее автоматически заносится пустая строка). Кроме того, для этого языка можно вывести полученную строку с помощью потока вывода pt:

[C++]

string s;
for (int i = 0; i < n; ++i)
    s = s + c1 + c2;
pt << s;
}

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

"a1a1a1a1a1*

Красная звездочка, расположенная в конце строки, отображаемой на экране, означает, что длина результирующей строки превышает длину контрольной (т. е. «правильной») строки. Для того чтобы увидеть на экране всю полученную строку, достаточно подвести курсор мыши к строке со звездочкой; при этом полный текст строки появится во всплывающей подсказке.

Примечание. Красная звездочка может появиться и при выводе ошибочных числовых данных. Например, если ожидается целое число в диапазоне от 1 до 99, а получено число 10000, то на экран будет выведена только первая цифра этого числа, за которой будет указана красная звездочка: 1*.

Правильное решение, его тестирование и просмотр результатов

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

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

[C/C++]

for (int i = 0; i < n / 2; ++i)

После запуска исправленной программы и успешного прохождения 5 тестов мы получим сообщение «Задание выполнено!». Нажав клавишу [F2], мы можем вывести на экран окно результатов, в котором будут перечислены все наши попытки решения задачи (буква «c», которая указывается перед датой, означает, что при выполнении задания использовался язык C++; для языка C используется заглавная буква «C»):

String9   c24/03 11:37 Ознакомительный запуск.
String9   c24/03 11:48 Неверно указан тип при вводе исходных данных.
String9   c24/03 11:49 Запуск с правильным вводом данных.
String9   c24/03 11:49 Ошибочное решение.
String9   c24/03 11:52 Задание выполнено!

Примечание. В варианте решения для языка C можно обойтись без вспомогательного счетчика p, вычисляя индексы символов массив s по параметру цикла i. Приведем соответствующий вариант решения:

[C/C++]

Task("String9");
int n;
char c1, c2;
GetN(&n);
GetC(&c1);
GetC(&c2);
char s[80];
for (int i = 0; i < n / 2; ++i)
{
  s[2 * i] = c1;
  s[2 * i + 1] = c2;
}
s[n] = 0;
PutS(s);

Приведем также полный вариант решения для языка C++, использующий тип string:

[C++]

Task("String9");
int n;
char c1, c2;
pt >> n >> c1 >> c2;
string s;
for (int i = 0; i < n / 2; ++i)
    s = s + c1 + c2;
pt << s;

PrevNext

 

Рейтинг@Mail.ru

Разработка сайта:
М. Э. Абрамян, В. Н. Брагилевский

Последнее обновление:
01.01.2024