Символьные данные и их представление в памяти ЭВМ — КиберПедия 

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Символьные данные и их представление в памяти ЭВМ

2020-08-21 112
Символьные данные и их представление в памяти ЭВМ 0.00 из 5.00 0 оценок
Заказать работу

Символьные данные и их представление в памяти ЭВМ

Одиночным символьным данным (константам и переменным) в оперативной памяти ЭВМ выделяется по одному байту, в которых хранятся соответствующие значения – числовые коды конкретных символов в соответствии с их кодировкой в той или иной странице.

Чтобы познакомиться с 866-й кодовой страницей предлагается выполнить следующую программу:

#include <stdio.h>#include <conio.h>void main(){ int i,j; gotoxy(37,1); printf("ASCII"); for (i=32; i<=52; i++) { gotoxy(1,i-29);  for (j=i; j<=255; j+=21)    printf("%c %3d ",j,j); } getch();}

Результат ее работы приведен на рис.1.

Рис. 1. Состав отображаемых символов ASCII (code page 866)

Отображаемые символы в таблице ASCII начинаются с кода 32 (0x20), которому соответствует символ "пробел". Коды больших русских букв начинаются с кода 128 (0x80), однако буква 'Ё' расположена не на своем месте. Наблюдается разрыв в числовой последовательности кодов малых букв – после буквы 'п' расположена группа кодов псевдографики. С их помощью в текстовом режиме работы дисплея строятся одинарные и двойные контуры таблиц. Малая буква 'ё' также расположена не в алфавитном порядке. Все эти нюансы приходится учитывать при построении программы перекодировки русских текстов из кодовой страницы 1251 (т.е. из кодировки Windows) в кодировку MS-DOS. С такой операцией приходится сталкиваться при необходимости включения русских текстов в консольное приложение BCB.

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

'F', '%', '$', 'ы', '5', '+', '"', 'q', 'Я', ' '

Последняя константа в приведенном перечислении соответствует пробелу. Сам символ апострофа таким образом "закодировать" нельзя.

Второй способ заключается в записи шестнадцатеричного кода символа после знака "обратный слэш":

'\x27'    (код символа "апостроф", 39)'\x5C'    (код символа \, 92)

Обратите внимание на то, что шестнадцатеричный код записывается без лидирующего нуля (в отличие от записи числовых шестнадцатеричных констант). Так можно записать любой управляющий код, расположенный в начале таблицы ASCII. Однако в языках C/C++ чаще используются Escape-последовательности:

 Вот несколько примеров:

'\'' – символ "апостроф"'\\' – символ "обратный слэш"

Третий способ заключается в записи восьмеричного кода символа после знака "обратный слэш":

'\47'     (код символа "апостроф", 39)'\134'    (код символа \, 92)

Обратите внимание на то, что восьмеричный код записывается без лидирующего нуля (в отличие от записи числовых восьмеричных констант) и должен принадлежать диапазону [0, 377].

Символьные переменные объявляются с помощью спецификаторов char или unsigned char. Одновременно их можно проинициализировать тем или иным способом:

char ch1='Я',ch2='\x9F',ch3='\237',ch4=0x9F,ch5=0237,ch6=159;

Числовой способ инициализации гарантирует правильность вывода как в DOS-приложении, так и в консольном приложении Windows. Символьной инициализацией в консольных приложениях Windows можно пользоваться без проблем только для символов из первой половины таблицы ASCII.

Ввод текстовых данных во время работы программы

Форматный ввод

Список форматных указателей функции scanf предусматривает возможность ввода значений односимвольных (%c) и многосимвольных (%s) переменных:

#include <stdio.h>void main(){ char ch1,ch2; char str1[10]; scanf("%c %c",&ch1,&ch2); scanf("%s",str1);....................

Обратите внимание на то, что для ввода данных в скалярные переменные ch1 и ch2 в списке ввода необходимо указывать их адреса (&ch1, &ch2), а при вводе в массив str1 – достаточно написать его имя. Дело в том, что имя массива одновременно выполняет роль адреса своего первого элемента. Поэтому str1 и &str1[0] указывают на один и тот же адрес.

Ввод значений символьных переменных ch1 и ch2 можно организовать одним из двух способов. Во-первых, в строке ввода можно набрать два требуемых символа либо слитно, либо разделяя их хотя бы одним пробелом и нажать клавишу Enter. Во-вторых, можно набрать первый символ, предназначенный для переменной ch1, и нажать клавишу Enter. Затем повторить аналогичным образом ввод следующего символа.

Значение, предназначенное для строковой "переменной" str1, не должно содержать более 9 символов (признак конца строки система добавляет автоматически) и среди них не должен присутствовать пробел. Дело в том, что пробел при форматном вводе воспринимается как разделитель данных. Это не означает, что среди символов строки пробел вообще не допустим, просто для организации ввода в строку нескольких слов надо использовать другие средства.

Довольно неожиданно, но с помощью задания ширины поля ввода и одного форматного указателя %с можно за один прием ввести несколько символов в элементы символьного массива:

char q[20];............scanf("%20c",q); //ввод 20 символов в массив q

В отличие от ввода по форматному указателю %s в массив q здесь не записывается признак конца строки – вводятся только запрашиваемые символы, которые набираются в одной строке с последующим нажатием клавиши Enter.

Функция scanf предусматривает еще два интересных форматных указателя, которые обеспечивают ввод либо тех символов, которые указаны в заданном множестве, либо всех символов, которые не принадлежат заданному множеству. Например, для ввода цифр из диапазона от 0 до 9 такой указатель имеет вид %[0-9], а для ввода символов, не являющихся цифрами – %[^0-9]. Рассмотрим следующий пример, который не только демонстрирует ввод по таким форматным указателям, но и содержит непредвиденный пассаж, связанный с использованием "грязного" буфера ввода.

#include <stdio.h>#include <conio.h> void main(){ char str[10]; int j; printf("Enter 123ABC\n"); scanf("%[0-9]",str); printf("str=%s\n",str); for(j=0; j<10; j++) printf("%3x",str[j]); printf("\nEnter DEF123\n"); scanf("%[^0-9]",str); printf("str=%s\n",str); for(j=0; j<10; j++) printf("%3x",str[j]); getch();}//=== Результат работы ===Enter 123ABCstr=123 31 32 33 0 0 1 0 0 1 0Enter DEF123str=ABC DEF 41 42 43 a 44 45 46 0 1 0

После ввода первой строки программе были переданы символы '123', вслед за которыми в массив str был записан нулевой байт – признак конца строки. Однако в буфере ввода остались невостребованными символы 'ABC' и код клавиши Enter (код 0xa). После набора второй строки к содержимому буфера ввода добавились еще три символа 'DEF' и т.к. все семь первых символов не являются кодами цифр, то все они были переданы в массив str. При выводе первые три отобразились в одной строке, затем сработал управляющий код 0xa и три следующие символа были выведены в следующей строке. Для наглядности содержимое массива после каждого вывода по формату %s отображалось еще и в шестнадцатеричном формате. Значения байтов, начиная с str[4], объясняются тем, что массив str является локальным, и под него выделяется "грязная память". Если его описание вынести за пределы main, то он станет глобальным и будет расписан нулями.

Чтобы не пострадать от непредвиденного ввода символов, задержавшихся в буфере ввода, рекомендуется после обращения к функции scanf чистить буфер ввода с помощью функции fflush(stdin). Если бы мы включили в предыдущий пример обращение к функции fflush, то после ввода второй строки в массиве str оказались бы только символы 'DEF'.

Потоковый ввод

Потоковый ввод в символьные и "строковые" переменные организуется следующим образом:

#include <iostream.h>void main(){ char ch1,ch2; char str1[10]; cin >> ch1 >> ch2; cin >> str1;....................

Набор вводимой информации на клавиатуре осуществляется точно таким же образом, как и при форматном вводе.

Вывод текстовых данных

При выводе текстовых данных особые проблемы возникают только в том случае, когда сообщения, содержащие русские буквы, готовятся в среде Windows (кодовая страница 1251), а выводятся консольным приложением в 866-й кодовой странице. В этом случае можно написать сравнительно несложную функцию конвертирования текстов из одной кодировки в другую. В кодовой странице 1251 буквы русского алфавита кодируются подряд, начиная с кода 192 (большая буква 'А') до кода 255 (малая буква 'я'). Буквы 'Ё' и 'ё' имеют коды 164 и 184 соответственно. Поэтому при перекодировке необходимо:

  • коды букв, принадлежащие интервалу [192, 239] уменьшить на 64, чтобы вогнать их в интервал [128, 174];
  • коды букв, принадлежащие интервалу [240, 255] уменьшить на 16, чтобы вогнать их в интервал [224, 239];
  • коды букв Ё и ё заменить на 240 и 241 соответственно.
#include <stdio.h>#include <iostream.h>#include <conio.h>#include <string.h> char *to_866(unsigned char *s){ static unsigned char str[80]; int j=0; while (s[j]!='\0') { str[j]=s[j]; if(s[j]>=192 && s[j]<=239) str[j]-=64; if(s[j]>=240 && s[j]<=255) str[j]-=16; if(s[j]==164) str[j]=240; if(s[j]==184) str[j]=241; j++; } str[j]='\0'; return str;} void main(){ char s[]="Привет"; cout << s << endl; cout <<to_866(s) << endl; getch();} //=== Результат работы ===

 

В первой строке вывод реализован без перекодировки, а во второй – с перекодировкой.

Форматный вывод

Для форматного вывода символьных значений в функции printf используется форматный указатель %c, а для вывода строк – форматный указатель %s. При создании консольных приложений Windows можно воспользоваться программой перекодировки, аналогичной функции to_866.

#include <stdio.h>#include <conio.h>void main(){ char ch1='F'; unsigned char ch2='5'; char ch3[]="ABCD"; printf("%c %c %s",ch1,ch2,ch3); getch();}//=== Результат работы ===F 5 ABCD

Потоковый вывод

В потоковом выводе единственная проблема может возникнуть в связи с перекодировкой русских сообщений в консольном приложении Windows.

#include <iostream.h>#include <conio.h>void main(){ char ch1='F'; unsigned char ch2='5'; char ch3[]="ABCD"; cout<<ch1<<' '<<ch2<<' '<<ch3; getch();}//=== Результат работы ===F 5 ABCD

Определение длины строки

strlen(CS) Возвращает количество символов в строке S

Формирование строк

strdup(CS) Запрашивает память, копирует туда содержимое CS и возвращает указатель типа char* на новую строку strcpy(S1,CS2) Копирует содержимое CS2 в S1, возвращает указатель на S1 strncpy(S1,CS2,k) Копирует первые k символов из CS2 в S1, возвращает указатель на S1 stpcpy(S1,CS2) Копирует CS2 в S1, возвращает указатель на конец S1 strset(S,ch) Расписывает строку S символом ch, возвращает указатель на S1 strnset(S,ch,k) Повторяет k раз символ ch в строке S, возвращает указатель на S1

Конкатенация строк

strcat(S1,CS2) Приписывает содержимое CS2 в конец S1, возвращает указатель на S1 (длина массива S1 должна предусматривать такое расширение) strncat(S1,CS2,k) Присоединяет первые k символов CS2 к содержимому S1, возвращает указатель на S1

Смена регистра

strlwr(S) замена символов строки S кодами малых букв, действует только на буквы латинского алфавита strupr(S) замена символов строки S кодами больших букв, действует только на буквы латинского алфавита

Переворот строки

strrev(S) Перестановка символов строки S в обратном порядке

Преобразование в числовые данные

strtol(CS,ptr,r) Число, представленное в символьном виде в CS и записанное в системе счисления с основанием r, преобразуется в машинный формат числа типа long. В указатель ptr заносится адрес символа, прервавшего преобразования. Возвращаемое значение – результат преобразования. strtoul(CS,ptr,r) Аналогичное преобразование в длинное целое число без знака strtod(CS,ptr) Преобразование вещественного числа из символьного представления в машинный формат числа типа double.

Сравнение строк

strcmp(CS1,CS2) Возвращаемое значение равно 0, если CS1=CS2, больше 0, если CS1>CS2, и меньше 0, если CS1<CS2 strncmp(CS1,CS2,k) Сравниваются только первые k символов строк CS1 и CS2 stricmp(CS1,CS2) При сравнении игнорируется разница между кодами больших и малых букв strcmpi(CS1,CS2) Аналогичная операция, разница только в названии функций strnicmp(CS1,CS2,k) Сравнение первых k символов с игнорированием разницы между кодами больших и малых букв strncmpi(CS1,CS2,k) Аналогичная операция, разница только в названии функций

Поиск символа

strchr(CS,ch) Строка CS сканируется слева направо до обнаружения символа ch. Если он найден, возвращаемый указатель "смотрит" на этот символ в строке CS, если такого символа нет, то возвращаемый указатель равен null (т.е. 0) strrchr(CS,ch) Аналогичный поиск с конца строки CS.

Поиск строки

strstr(CS1,CS2) Поиск первого вхождения строки CS2 в строку CS1. Если поиск завершен успешно, возвращается указатель на первый символ найденной подстроки. В противном случае возвращается null

Специальный поиск

strpbrk(CS1,CS2) В строке CS1 ищется первый символ, содержащийся в CS2. Возвращается указатель на найденный символ или null. strspn(CS1,CS2) Определяется длина начального фрагмента CS1, целиком состоящая из символов CS2 (порядок символов роли не играет) strcspn(CS1,CS2) Определяется длина начального фрагмента CS1, который не содержит ни одного символа из CS2 strtok(S1,CS2) Поиск в строке S1 лексем, разделенных символами CS2

Некоторые из функций, приведенные в табл. 2, нуждаются в дополнительных пояснениях.

В функциях strtol и strtoul, выполняющих преобразование символьного представления числа в соответствующий машинный формат, допускается задание r=0. В этом случае основание системы определяется символьной записью числа. Если строка начинается с символа '0', за которым следуют символы цифр, не превосходящих 7, то число считается восьмеричным. Если строка начинается с комбинации '0x' или '0X', вслед за которой располагаются шестнадцатеричные цифры, то считается, что r=16.

В функции strtok лексемой считается цепочка символов, завершающаяся одним из предусмотренных символов-разделителей. При первом обращении к этой функции в строке S1 находится начальная лексема и возвращаемое значение является указателем на ее начальный символ. Одновременно в строку S1 на место обнаруженного символа-разделителя заносится нулевой байт. Это позволит в дальнейшем работать с найденной лексемой как со строкой. Для поиска следующих лексем в повторных обращениях к функции strtok вместо первого аргумента нужно задавать нулевой аргумент. Функция будет искать следующую лексему, расположенную правее принудительно вставленного нулевого байта. И так можно последовательно обнаружить все лексемы, содержавшиеся в строке S1. Для пояснения приведем следующий пример:

#include <stdio.h>#include <conio.h>#include <string.h>void main(){ char *ptr; ptr=strtok("FEB.14,2006",".,-/"); while(ptr!=NULL) { printf("ptr=%s\n",ptr); ptr=strtok(NULL, ".,-/"); } getch();}//=== Результат работы ===ptr=FEBptr=14ptr=2006

Символьные данные и их представление в памяти ЭВМ

Одиночным символьным данным (константам и переменным) в оперативной памяти ЭВМ выделяется по одному байту, в которых хранятся соответствующие значения – числовые коды конкретных символов в соответствии с их кодировкой в той или иной странице.

Чтобы познакомиться с 866-й кодовой страницей предлагается выполнить следующую программу:

#include <stdio.h>#include <conio.h>void main(){ int i,j; gotoxy(37,1); printf("ASCII"); for (i=32; i<=52; i++) { gotoxy(1,i-29);  for (j=i; j<=255; j+=21)    printf("%c %3d ",j,j); } getch();}

Результат ее работы приведен на рис.1.

Рис. 1. Состав отображаемых символов ASCII (code page 866)

Отображаемые символы в таблице ASCII начинаются с кода 32 (0x20), которому соответствует символ "пробел". Коды больших русских букв начинаются с кода 128 (0x80), однако буква 'Ё' расположена не на своем месте. Наблюдается разрыв в числовой последовательности кодов малых букв – после буквы 'п' расположена группа кодов псевдографики. С их помощью в текстовом режиме работы дисплея строятся одинарные и двойные контуры таблиц. Малая буква 'ё' также расположена не в алфавитном порядке. Все эти нюансы приходится учитывать при построении программы перекодировки русских текстов из кодовой страницы 1251 (т.е. из кодировки Windows) в кодировку MS-DOS. С такой операцией приходится сталкиваться при необходимости включения русских текстов в консольное приложение BCB.

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

'F', '%', '$', 'ы', '5', '+', '"', 'q', 'Я', ' '

Последняя константа в приведенном перечислении соответствует пробелу. Сам символ апострофа таким образом "закодировать" нельзя.

Второй способ заключается в записи шестнадцатеричного кода символа после знака "обратный слэш":

'\x27'    (код символа "апостроф", 39)'\x5C'    (код символа \, 92)

Обратите внимание на то, что шестнадцатеричный код записывается без лидирующего нуля (в отличие от записи числовых шестнадцатеричных констант). Так можно записать любой управляющий код, расположенный в начале таблицы ASCII. Однако в языках C/C++ чаще используются Escape-последовательности:

 Вот несколько примеров:

'\'' – символ "апостроф"'\\' – символ "обратный слэш"

Третий способ заключается в записи восьмеричного кода символа после знака "обратный слэш":

'\47'     (код символа "апостроф", 39)'\134'    (код символа \, 92)

Обратите внимание на то, что восьмеричный код записывается без лидирующего нуля (в отличие от записи числовых восьмеричных констант) и должен принадлежать диапазону [0, 377].

Символьные переменные объявляются с помощью спецификаторов char или unsigned char. Одновременно их можно проинициализировать тем или иным способом:

char ch1='Я',ch2='\x9F',ch3='\237',ch4=0x9F,ch5=0237,ch6=159;

Числовой способ инициализации гарантирует правильность вывода как в DOS-приложении, так и в консольном приложении Windows. Символьной инициализацией в консольных приложениях Windows можно пользоваться без проблем только для символов из первой половины таблицы ASCII.


Поделиться с друзьями:

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

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

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

Индивидуальные очистные сооружения: К классу индивидуальных очистных сооружений относят сооружения, пропускная способность которых...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.009 с.