Си. Представление символов




Зачем нужны кодировки символов?

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

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

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

Таблица ASCII

ASCII ‑ A merican s tandard c ode for i nformation i nterchange – американский стандартный код обмена информацией.

ASCII – 8-ми разрядный код. Для кодирования символов используется 8 битов. С помощью 8 битов можно закодировать 256 символов. Но только первую половину кодовой таблицы (коды от 0 до 127) занимают полностью стандартизированные символы US-ASCII, а вторую (128 ‑ 255) — разные другие символы, часто соответствующие национальным стандартам. В настоящее время «ASCII» практически всегда означает «US-ASCII».

Таблица US-ASCII

  .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
0. NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI
1. DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2.   ! " # $ % & ' ( ) * + , . /
3.                     : ; < = > ?
4. @ A B C D E F G H I J K L M N O
5. P Q R S T U V W X Y Z [ \ ] ^ _
6. ` a b c d e f g h i j k l m n o
7. p q r s t u v w x y z { | } ~ DEL

Шестнадцатеричный код каждого символа составляется из шестнадцатеричного номера строки и столбца. Строки и столбцы нумеруются с нуля. Например, код латинской буквы A равен шестнадцатеричному числу 41 (номер строки 4, номер столбца 1). Шестнадцатеричные числа в Си начинаются с префикса 0x. То есть код буквы A равен 0x41.

Значения символов с кодами от 0x0 до 0x1F можно узнать из Приложения 1.

Упражнение.

1. Запишите шестнадцатеричный код латинской буквы a. Чему равна разность кодов буквы a и A? Повторите упражнение для других латинских букв.

2. Как по коду прописной буквы получить код строчной буквы? Как по коду строчной буквы получить код прописной буквы?

3. Запишите последовательность кодов цифр от 0 до 9. Как по коду цифры получить ее числовое значение?

Си. Представление символов

Символьная константа в Си есть целое, записанное в виде символа, обрамленного одиночными кавычками. Например, символу 'A' соответствует десятичное число 65 (шестнадцатеричное 0x41). Символьные константы считаются данными типа int. Символами можно оперировать, как числами. Например, переменные и константы символьного типа можно использовать в арифметических выражениях.

В языке программирования Си тип данных char – это обычный числовой тип. Объект типа char имеет внутреннее представление как объект целого типа в диапазоне от 0 до 255. Однако в операциях ввода-вывода объекты целого типа могут быть представлены символами кодировочной таблицы.

Пример ввода (чтения) символа и его вывода разными способами:

  #include <stdio.h>   int main(void) { unsigned char c; c = getchar(); putchar(c); printf("\n%c %d\n", c, c); getchar(); return 0; }

Строка 1 — #include <stdio.h> — означает «включи заголовок stdio.h». В файле с заголовком stdio.h объявляются функции, связанные с вводом и выводом данных. Аббревиатуру stdio можно перевести как стандартный ввод-вывод (англ. standard input/output). Буква «h» после точки означает заголовок (англ. header). В заголовках, которые, как правило, представлены отдельными заголовочными файлами, обычно объявляются предоставляемые соответствующими им библиотеками функции, типы данных, константы и определения препроцессора.

Строка 3определение функции main. Оно начинается с объявления:

int main (void)[1]

что значит: «функция с именем main, которая не имеет аргументов (void) и возвращает целое число (число типа int от англ. integer)»

Английское слово void можно перевести как «пустота». Далее открывается фигурная скобка и идёт тело функции, в конце фигурная скобка закрывается. Тело функции определяет последовательность действий, выполняемых данной. В данном примере тело функции состоит из операторов в строках с 5-й по 10-ю.

Функция main() — главная функция программы, именно с нее начинается выполнение программы.

Строка 5 — объявление переменной c как без знаковой переменной целого типа char:

char c;

Переменная типа char имеет своим значением целое число unsigned char в диапазоне от 0 до 255. Но в операциях ввода-вывода переменные типа char могут быть представлены символами кодировочной таблицы ASCII. Поэтому, хотя для чтения значений переменных обычно используется функция scanf(), для чтения значений переменных типа char уместно использовать функцию getchar() (строка 6). Парная ей функция putchar()(строка 7) используется для вывода значения переменной типа char именно в виде символа кодировочной таблицы.

Строка 8 — стандартная функция форматированного вывода printf():

printf("\n%c %d\n", c, c);

Строка в кавычках (строковая константа) задает формат вывода. Обратите внимание на комбинацию \n — она включает в выводимую строку управляющий код (или управляющий символ) перевода (также разрыва или завершения) строки. Комбинация, начинающаяся с символа %, определяет формат вывода значений переменных из списка, следующего после строки формата. Здесь список вывода состоит из двукратного повторения переменной c. В первый раз она выводится как символ, второй раз – как десятичное целое число – код символа. На скриншоте ниже в первой строке латинская буква A отобразилась как результат ввода с клавиатуры (действие в строке 6). Заметьте, что ввод символа A был завершен нажатием клавиши Enter, то есть вводом управляющего кода перевода строки. Во второй строке та же буква A появилась в результате действия putchar(c) в 7-й строке. Третья строка – результат действия printf("\n%c %d\n", c, c) ‑ сначала выводится символ, потом его код.

Но в 9-й строке повторно указана инструкция getchar(). Она потребовалась для того, чтобы прочитать управляющий код перевода строки, которым был завершен ввод символа. Обычно такая инструкция используется для задержки окна работы программы.

При запуске программы непосредственно из графического окружения (в данном случае это среда Dev-Cpp), отведенное программе окно обычно закрывается сразу же после завершения программы. Функция getchar() ожидает ввод пользователя, тем самым «откладывая» завершение программы. Какие именно действия могут прервать это ожидание — зависит от системы, однако можно надеяться, что нажатие клавиши ⏎ Enter завершит эту функцию в любой системе.

В среде Dev-Cpp для задержки окна программы можно использовать функцию system("PAUSE"). Именно она здесь используется и сообщение «Для продолжения нажмите любую клавишу…» ‑ это приглашение пользователю от функции system()завершить работу программы. Однако, если бы предыдущий getchar()не прочитал управляющий код, он был бы обработан системной функцией и завершил выполнение программы (инструкция return в 10-й строке).

Задания

1. Проверьте работу программы вводом символа B. Код этого символа равен 66.

2. По введенному символу получите следующий символ и его код. Не забывайте, что тип char – это числовой тип.

3. Разработайте вариант программы, выводящий код введенного символа в шестнадцатеричном и восьмеричном представлениях. (Указание: воспользуйтесь материалом Приложения 3)

4. Для символов, составляющих слово SUM, выведите сумму их кодов.

5. Для введенной прописной латинской буквы получите разность между кодом этой буквы и кодом буквы ‘A’.

6. Напишите программу, которая выведет четвертую, четырнадцатую и двадцать четвертую букву латинского алфавита.

7. Напишите программу, которая выведет подряд четыре буквы латинского алфавита, начиная с заданной буквы.

8. По введенной прописной латинской букве получите соответствующую строчную букву и ее код.

9. По введенной строчной латинской букве получите соответствующую прописную букву и ее код.

10. По введенной цифре получите ее код и разность между этой цифрой и нулем.

11. По введенной цифре, отличной от нуля и девяти, получите предыдущую и следующую цифру.

12. Для двух введенных цифр выведите их сумму (как сумму однозначных чисел) и сумму их кодов. Например, для цифр 5 и 6 их сумма равна 11, а сумма их кодов равна 107.

13. Попробуйте напечатать как символ число больше 255. Что получается?

Рекомендую к чтению материалы из Викиучебника — Язык Си в примерах

Кроме латиницы

Функция setlocale

#include <locale.h>char *setlocale(int type, const char * locale);

Функция setlocale() позволяет получить или установить некоторые параметры, которые зависят от геополитической среды выполнения программы. Если указатель locale является нулем, функция setlocale() возвращает указатель на строку текущей локализации. В противном случае функция setlocale() попытается использовать строку locale для установки локальных параметров в соответствии с параметром type. Для задания стандартных С-параметров региональной привязки используйте строку "С", а для задания собственных параметров среды — пустую строку (""). Чтобы получить подробную информацию о строках локализации, поддерживаемых конкретным компилятором, обратитесь к документации.

Стандарт предусматривает ряд средств для поддержки письменностей, отличных от «базовой» (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.) Соответственно меняются тип (int → wint_t) и константа признака исчерпания входного потока (EOF → WEOF.)[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> intmain (){ 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])



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-08-27 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: