Язык Си в примерах/Верхний регистр

Материал из Викиучебника — открытых книг для открытого мира
Перейти к навигации Перейти к поиску

Язык Си в примерах


  1. Компиляция программ
  2. Простейшая программа «Hello World»
  3. Учимся складывать
  4. Максимум
  5. Таблица умножения
  6. ASCII-коды символов
  7. Верхний регистр
  8. Скобочки
  9. Факториал
  10. Степень числа
  11. Треугольник Паскаля
  12. Корень уравнения
  13. Система счисления
  14. Сортировка
  15. Библиотека complex
  16. Сортировка на основе qsort
  17. RPN-калькулятор
  18. RPN-калькулятор на Bison
  19. Простая грамматика
  20. Задача «Расчёт сопротивления схемы»
  21. Простая реализация конечного автомата
  22. Использование аргументов командной строки
  23. Чтение и печать без использования stdio
  24. Декодирование звукозаписи в формате ADX
Дано
текст — последовательность кодов ASCII — на стандартном вводе программы. Последовательность конечна, но ее длина заранее неизвестна.
Надо
вывести на стандартный вывод исходный текст, заменив в нем строчные буквы латиницы (a, …, z) прописными (A, …, Z).
Указание
воспользоваться особенностью кодовой таблицы ASCII: коды прописных букв отличаются от кодов соответствующих строчных на постоянную величину (а именно: 32.)
Дополнительно
предполагая поддержку средой русскоязычной локали, реализуйте аналогичное преобразование для кириллических текстов (используя стандартные функции языка.)

Решение[править]

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

Обратите внимание на то, что с символами (переменными типа char) можно оперировать как с числами. В частности, 'Z' - 'A' есть число, равное разности кодов символов A и Z, то есть (при использовании кодовой таблицы ASCII) 25 — число букв в латинском алфавите минус 1. Символы можно также сравнивать друг с другом, при этом сравниваются их коды.

#include <assert.h>
#include <stdio.h>

int
main ()
{
  int c;
  while ((c = getchar ()) != EOF) {
    if ('a' <= c && c <= 'z') {
      c += 'A' - 'a';
    }
    putchar (c);
  }
  assert (! ferror (stdin));

  return 0;
}

Главный циклусловие корректности ввода) этой программы почти полностью совпадают с рассмотренными в разделе ASCII коды символов. Однако, вместо использования printf для вывода значений считанных кодов, здесь мы используем функцию putchar для вывода самих кодов (знаков), возможно — после преобразования.[1] В коде по-прежнему используются функции getchar и ferror.[2][3]

Обратите внимание, что сформировать условие «конец потока» при вводе с клавиатуры можно вводом (в зависимости от системы и предполагая настройки по-умолчанию) Control-d или Control-z (также обозначаются C-d, ^D, C-z, ^Z.)

Использование стандартной библиотеки[править]

Приведенный выше код можно еще более упростить, если воспользоваться стандартной функцией преобразования регистра toupper, объявленной в заголовке ctype.h.[4]

Некоторые реализации языка, кроме того, определяют функции strlwr и strupr, которые переводят в нижний и верхний регистр строки, а не отдельные символы. Эти функции, однако, не являются стандартными и их наличие (или отсутствие) зависит от выбранной реализации языка.

#include <assert.h>
#include <ctype.h>
#include <stdio.h>

int
main ()
{
  int c;
  while ((c = getchar ()) != EOF) {
    putchar (toupper (c));
  }
  assert (! ferror (stdin));

  return 0;
}

Кроме латиницы[править]

Стандарт предусматривает также ряд средств для поддержки письменностей, отличных от «базовой» (26-символьной) латиницы. В основе такой поддержки — два следующих понятия:

  1. локаль — набор сведений о письменности, языке и культуре, включающий, помимо прочего, таблицы соответствия символов верхнего и нижнего регистров;
  2. широкие символьные типы (wchar_t, wint_t; англ. wide character) — для представления ряда письменностей (например — основанных на иероглифах), а равно для представления текстов на нескольких языках, «байтового» типа char оказывается недостаточно; как следствие, в задачах, связанных с обработкой многоязычных текстов, его заменяет тип wchar_t; аналогично, в операциях ввода-вывода используется тип wint_t (и константа WEOF.)

Соответственно, в исходный вариант вносятся следующие изменения.

  1. Появляется вызов setlocale (LC_ALL, ""), инициализирующий локаль в соответствии с текущими настройками. (По-умолчанию, при запуске программы полагается setlocale (LC_ALL, "C") — установка «стандартной» локали.)[5]
  2. Функции getwchar, towupper, putwchar заменяют соответствующие для «узких» символов (getchar, toupper, putchar.) Соответственно меняются тип (intwint_t) и константа признака исчерпания входного потока (EOFWEOF.)[6][7][8]
  3. Включаются соответствующие заголовки (locale.h, wchar.h, wctype.h.)

#include <assert.h>
#include <locale.h>
#include <stdio.h>
#include <wchar.h>
#include <wctype.h>

int
main ()
{
  char *rl
    = setlocale (LC_ALL, "");
  assert (rl != 0);

  wint_t c;
  while ((c = getwchar ()) != WEOF) {
    putwchar (towupper (c));
  }
  assert (! ferror (stdin));

  return 0;
}

Отметим, впрочем, что принятые в конкретном языке правила обращения со строчными и заглавными могут оказаться сложнее простой зависимости символ—символ, предполагаемой в данном примере. Так, например, правила немецкого языка ставят в соответствие строчной «ß» пару заглавных — «SS» (например: Straße → STRASSE), что ни коим образом не может быть реализовано функцией towupper.

Задания[править]

  1. Проверьте работу программы вводом строк Hello! и Привет!. Удостоверьтесь, что «базовые» варианты решения выполняют заданное преобразование лишь для для первой из них, в то время как «интернационализованное» решение действует и в отношении кириллического ввода.
  2. Разработайте варианты программы, выполняющие (вновь для латиницы) a. преобразование верхнего регистра в нижний и b. «переключение» регистра — Hello!hELLO!. (Указание: воспользуйтесь стандартными функциями islower и isupper.[9][10])

См. также[править]

Примечания[править]

  1. 7.21.7.8 The putchar function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  2. 7.21.7.6 The getchar function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  3. 7.21.10.3 The ferror function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  4. 7.4.2 Character case mapping functions(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  5. 7.11.1.1 The setlocale function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  6. 7.29.3.7 The getwchar function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  7. 7.30.3.1.2 The towupper function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  8. 7.29.3.9 The putwchar function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  9. 7.4.1.7 The islower function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.
  10. 7.4.1.11 The isupper function(англ.) WG14 N1570 Committee Draft. ISO/IEC (2011-04-12). Проверено 2012-11-19 г.