§ 9. Строковые величины

9.6. Преобразование строк

Пример 9.14. По правилам орфографии новое предложение начинается всегда с заглавной буквы. Текстовые редакторы автоматизируют ввод заглавной буквы, т. е. если пользователь написал первое слово в предложении со строчной буквы, то она заменяется на заглавную. Написать программу, которая производит такую автозамену для текста, набранного латинским буквами. Считать, что текст набран корректно и после каждого знака препинания, означающего конец предложения («.», «!», «?»), стоит пробел.

Этапы выполнения задания

I. Исходные данные: переменная st (введенная строка).

II. Результат: преобразованная строка.

III.  Алгоритм решения задачи.

1. Ввод исходных данных. 
2. Вычисление длины строки. 
3. Для хранения символов конца предложения создадим строку z.
4. В цикле for проверяем каждый символ строки st.

4.1. Если текущий символ является символом конца предложения, то нужно заменить символ, стоящий на две позиции дальше, если этот символ — строчная буква. 
4.2. Символ с является строчной буквой тогда, когда выполнено условие ’a’  ≤ c ≤ ’z’ (для латинских букв) и ’a’  ≤ c ≤ ’я’   (для русских букв). 
4.3. Для замены символов можно воспользоваться тем фактом, что разница в кодах между заглавной и соответствующей ей строчной буквой равна 32. Для проверки и замены символов создадим функцию up_char.

5.Вывод результата.

IV. Описание переменных: st – string, n – int.

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

Пример 9.15. Написать программу, которая заменит в тексте каждую цифру 2 словом «two».

Этапы выполнения задания

I. Исходные данные: переменная st (введенный текст).

II. Результат: преобразованный текст.

 III. Алгоритм решения задачи.

1. Ввод исходных данных.
2. 
В цикле while проверяем каждый символ текста st.

2.1. Если текущий символ текста «2», то удаляем его и вставляем подстроку «two». 
2.2.  Переходим к следующему символу.

 3. Вывод результата.

IV. Описание переменных: st – string, i – int.

При правильном наборе компьютерного текста между любыми двумя словами должен быть ровно один пробел. Однако иногда случайно вставляют несколько пробелов. В этом случае Word подчеркивает пробелы голубой волнистой линией (пример 9.16).

Пример 9.17. Написать программу, которая проверяет правильность расстановки пробелов в тексте и, если между словами более одного пробела, — удаляет лишние.

Этапы выполнения задания

I. Исходные данные: переменная st (введенный текст).

II. Результат: преобразованный текст.

III. Алгоритм решения задачи.

1. Ввод исходных данных.
2. Поскольку длина строки будет изменяться при обработке строки, то количество повторений цикла заранее не известно. Будем использовать цикл while
3. В цикле while проверяем соседние символы текста st.

3.1. Если оба соседних символа являются пробелами, то удалим один из них. Соседние символы имеют индексы, отличающиеся на один: i и i + 1.
3.2. Поскольку в цикле есть обращение к элементу с номером i + 1, то условием выполнения цикла будет неравенство i < length(st) — 1.
3.3. Переходим к следующему символу только тогда, когда удаление не проводили.

4. Вывод результата.

VI. Описание переменных: st – string, i– int.

Пример 9.18. Написать программу, которая проверяет правильность расстановки пробелов вокруг тире. Если пробелы пропущены, то вставляет их. Предполагается, что в тексте нет слов, которые пишутся через дефис, двух знаков «-» подряд и лишних пробелов.

Этапы выполнения задания

I. Исходные данные: переменная st (введенный текст).

II. Результат: преобразованный текст.

III. Алгоритм решения задачи.

1. Ввод исходных данных.
2. 
В цикле while проверяем каждый символ на совпадение с «-». При совпадении проверяем соседние символы.

2.1. Если соседний справа символ (i + 1) не пробел, то вставляем пробел. 
2.2. Если символ слева (i1) не пробел, то вставляем пробел и увеличиваем i на 1. 
2.3. Поскольку в цикле есть обращение к элементу с номером i + 1, то условием выполнения цикла будет неравенство i < length(st)-1
2.4. Поскольку в цикле есть обращение к элементу с номером i – 1, то начальное значение i = 1.

3. Переходим к следующему символу.
4.  Вывод результата.

IV. Описание переменных: st – string, i– int.

Пример 9.19. Написать программу, которая выведет слова-палиндромы [3] (слова, которые одинаково читаются слева направо и справа налево), входящие в заданный текст. Слова в тексте могут быть разделены одним или несколькими пробелами. Пробелы могут быть в начале и в конце текста.

Этапы выполнения задания

I. Исходные данные: переменная st (введенный текст).

II. Результат: слова-палиндромы.

 III. Алгоритм решения задачи.

1. Ввод исходных данных. 
2. Будем выделять первое слово из исходного текста, проверять его и затем удалять. 
3. Логическая переменная p изменит значение с false на true, если будет выведен палиндром. 
4. В цикле while, до тех пор пока строка не станет пустой, выполняем следующее.

4.1. Удалим пробелы в начале строки. Выделим первое слово из строки.
4.2. Проверим выделенное слово и, если оно является палиндромом, то выведем его. Слово может выделяться со знаками препинания («,.;:?!»), поэтому их нужно удалить перед проверкой его на палиндром. 
4.3. Удалим слово из строки.

5. Опишем три вспомогательных алгоритма.

5.1. Функцию DelSpace для удаления пробелов в начале строки. Пробелы удаляются из строки только тогда, когда она не пуста. Если пробелов в начале строки нет, то функция не изменит исходную строку. 
5.2. Функцию FirstWord, которая скопирует из строки первое слово. Если в строке только одно слово (нет пробелов), то оно же и является первым. 
5.3. Функцию CheckPalindrom для проверки, является ли слово палиндромом. Для проверки будем сравнивать первый символ с последним, второй с предпоследним и т. д. Символ с номером i будет сравниваться с символом с номером (n – i– 1), где n — длина слова.

6. Вывод сообщения «нет палиндромов» в случае, если значение p осталось false.

IV. Описание переменных: st, sl – string, i, n – int, p - bool.


[3] В мире интересных слов. Палиндромы. http://www.tramvision.ru/words/pal.htm.

Пример 9.14.

V. Программа:

#include <iostream>

#include <string>

#include <windows.h>

 

using namespace std;

using namespace std::__cxx11;

 

char up_char(char c)

{

  bool u1 = 'a' <= c && c <= 'z';

  bool u2 = 'а' <= c && c <= 'я';

  if (u1 || u2)

    return (- 32);

}

 

int main()

{

  SetConsoleCP(1251);

  SetConsoleOutputCP(1251);

  string st, z = ".?!";

  cout << "Text" << endl;

  getline(cin, st);

  int n = st.length();

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

    if (z.find(st[i]) != -1)

      st[i + 2= up_char(st[i + 2]);

  cout << endl << "New text" << endl;

   cout << st << endl;

  return 0;

}

VI. Тестирование [2].

Пример 9.15.

V. Программа:

#include <iostream>

#include <string>

 

using namespace std;

using namespace std::__cxx11;

 

int main()

{

  string st;

  cout << "Text" << endl;

  getline(cin, st);

  int i = 0;

  while (< st.length()){

    if (st[i] == '2'){

      st.erase(i,1);

      st.insert(i, "two");

    }

    i++;

  }

  cout << endl << "New text" << endl;

  cout << st << endl;

  return 0;

}

VI. Тестирование.

VII. Анализ результата.

Вместо двух функций erase и insert можно воспользоваться функцией replace.

   st.replace(i, 1, "two");   

Пример 9.16. Выделение лишних пробелов в Word.

Пример 9.17.

V. Программа:

#include <iostream>

#include <string>

 

using namespace std;

using namespace std::__cxx11;

 

int main()

{

  string st;

  cout << "Text" << endl;

  getline (cin, st);

  int i = 0;

  while (< st.length() - 1){

    if (st[i] == ' ' &&

        st[i + 1== ' ')

          st.erase(i, 1);

    else

      i++;

  }

  cout << endl << "New text" << endl;

  cout << st << endl;

  return 0;

}

VI. Тестирование.

Рассмотрим подробнее ситуацию, когда в тексте стоят подряд два или более пробелов. В примере такая ситуация встречается между словами «правильном» и «наборе». Условие (st[i] == ' ' && st[i + 1== ') для i = 14 выполнится, и пробел, стоящий на 14 месте, удалится. Тогда пробел, стоящий на месте 15, сдвинется влево и получит номер 14. При следующем выполнении тела цикла снова удалится пробел на месте 14, а пробел на месте 15 сдвинется влево. Переход на следующий символ осуществится только тогда, когда условие (st[i] == ' ' && st[i + 1== ' ') будет ложным — между словами останется только один пробел.

Пример 9.18.

V. Программа:

#include <iostream>

#include <string>

 

using namespace std;

using namespace std::__cxx11;

 

int main()

{

  string st;

  cout << "Text" << endl;

  getline(cin, st);

  int i = 1;

  while (< st.length() -1){

    if (st[i] == '-'){

      if (st[i + 1!= ' ')

        st.insert(+ 1, " ");

      if (st[i - 1!= ' '){

        st.insert(i, " ");

        i++;

      }

    }

    i++;

  }

  cout << endl << "New text" << endl;

  cout << st << endl;

  return 0;

}

 VI. Тестирование. Введите текст:

«Жизнь прожить-не поле перейти. Родимая сторона- мать, чужая -мачеха. Сделал дело — гуляй смело.»

Результат:

VII. Анализ результата. В примере встречаются все четыре возможных ситуации: пробелов нет ни слева, ни справа от тире; пробел только слева; пробел только справа; пробелы с двух сторон. В результате выполнения все пробелы расставлены правильно.

Пример 9.19.

V. Программа:

#include <iostream>

#include <string>

#include <windows.h>

 

using namespace std;

using namespace std::__cxx11;

 

string DelSpace (string s)

{

  while (!s.empty() && s[0]== ' ')

    s.erase(0, 1);

  return s;

}

 

string FirstWord (string s)

{

  int i = s.find(' ');

  if (!= 0)

    return s.substr(0, i);

  else

    return s;

}

 

bool CheckPalindrom(string s)

{

  int n = s.length();

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

    if (s[i] != s[- i - 1])

      return false;

  return true;

}

 

int main()

{

  SetConsoleCP(1251);

  SetConsoleOutputCP(1251);

  string st, z = ",.;:?!";

  cout << "Текст" << endl;

  getline(cin, st);

  bool p = false;

  while (!st.empty()){

    st = DelSpace(st);

    if (st.empty()) break;

    string sl = FirstWord(st);

    int n = sl.length();

    if (z.find(sl.back()) != -1)

      sl.pop_back();

    if (CheckPalindrom(sl)){

        cout << sl << endl;

        p = true;

    }

    st.erase(0, n);

  }

  if  (!p)

    cout << "нет палиндромов" << endl;

  return 0;

}

VI.  Тестирование. Введите текст:

«На берегу стоит шалаш из камыша. Для трафаретной печати предназначен ротатор,  или мимеограф. Пшеничная лепёшка наан является блюдом индийской национальной кухни».

Результат:



[2] Куприн, А. И. Гранатовый браслет // http://ilibrary.ru/text/1022/p.7/index.html