Анимация
JavaScript
|
Главная Библионтека 1.4. Преобразование между символами и ASCII-кодами 35 Формат %с в функциях printf и sprintf также преобразует число в символ- $char = sprintf( %с , $num), # Медленнее чем chr{$nuni) printf{ Number %d is character %c\n , $num, $num) Number 101 is character e Шаблон С*, используемый в функциях pack и unpack, позволяет быстро преобразовать несколько символов: (51ASCII = unpack( С* Sstring) (aSTRING = раск( С* $ascii), Комментарий в отличие от низкоуровневых, нетипизованных языков вроде ассемблера, Perl не считает эквивалентными символы и числа; эквивалентными считаются строки и числа. Это означает, что вы не можете произвольно присвоить вместо символа его числовое представление, или наоборот. Для преобразования между символами и их числовыми значениями в Perl существуют функции chr и ord, взятые из Pascal: $ascii value = ord{ е ) » Теперь 101 $character = chr{101), # Теперь е Символ в действительности представляется строкой единичной длины, поэтому его можно просто вывести функцией print или с помощью формата %s функций printf и sprintf Формат %с заставляет printf или sprintf преобразовать число в символ, однако он не позволяет вывести символ, который уже хранится в символьном формате (то есть в виде строки). printf( Number %d is character %c\n 101 101), Функции pack, unpack, chr и ord работают быстрее, чем sprintf. Приведем пример практического применения раек и unpack. @ascii character numbers = unpack( С* , sample ), print (5iascii character numbers\n , 115 97 109 112 108 101 $word = pack( C* ascii character nurabers), Sword = pack( C* 115, 97, 109, 112, 108 101), # To же самое print $word\n sample A вот как превратить HAL в IBM: $hal = HAL , @ascii = unpack{ C* , $hal), foreach $val (@ascii) { $val++, # Увеличивает каждый ASCII-код на 1 $ibm = pack( С*), (siascii), print $ibm\n » Выводит IBM Функция ord возвращает числа от О до 255. Этот диапазон соответствует тину данных unsigned char языка С. О Смотри также- Описание функций chr, ord, printf, sprintf, pack и unpack вperlfunc{\). 1.5. Посимвольная обработка строк Проблема Требуется последовательно обрабатывать строку по одному символу. Решение Воспользуйтесь функцией split с пустым шаблоном, чтобы разбить строку на отдельные символы, или функцией unpack, если вам нужны лишь их ASCII-коды: (Эаггау = split( , Sstring); (Эаггау - unpackCC*", Sstring); Или последовательно выделяйте очередной символ в цикле: while (/(.)/g) { # . здесь не интерпретируется как новая строка # Сделать что-то полезное с S1 Комментарий Как говорилось выше, фундаментальной единицей текста в Perl является строка, а не символ. Необходимость посимвольной обработки строк возникает достаточно редко. Обычно такие задачи легче решаются с помощью высокоуровневых операций Perl (например, поиска по шаблону). Пример приведен в рецепте 7.7, где для поиска аргументов командной строки используются подстановки. Если вызвать split с шаблоном, который совпадает с пустой строкой, функция возвращает список отдельных символов строки. При намеренном использованин эта особенность оказывается удобной, однако с ней можно столкнуться и случайно. Например, /X*/ совпадает с пустой строкой. Не исключено, что вам встретятся и другие ненамеренные совпадения. Ниже приведен пример, который выводит символы строки "an apple а day, отсортированные в восходящем порядке ASCII-кодов: %seen = 0; Sstring = "an apple a day"; foreach Sbyte (split , Sstring) { $seen(S1)++; print "unique chars are: ", sort(keys %seen), "\n"; unique chars are: adelnpy 1.5. Посимвольная обработка строк 37 Решения с функциями split и unpack предоставляют массив символов, с которым можно работать. Если массив не нужен, воспользуйтесь поиском по шаблону в цикле while с флагом /д, который будет извлекать по одному символу: %seen = 0; $string = "an apple a day"; while ($string =~ /(.)/g) { $seen($1)++; print "unique chars are: ", sort(keys %seen), "\n"; unique chars are: adelnpy Как правило, посимвольная обработка строк не является оптимальным решением. Вместо использования index/substr или split/unpack проще воспользоваться шаблоном. В следующем примере 32-разрядная контрольная сумма вычисляется вручную, но лучше поручить работу функции unpack - она сделает то же самое намного эффективнее. Следующий пример вычисляет контрольную сумму символов Sstring в цикле foreach. Приведенный алгоритм не оптимален; просто мы используем традиционную и относительно легко вычисляемую сумму. За более достойной реализацией контрольной суммы обращайтесь к модулю MD5 на CPAN. Ssum = 0; foreach $ascval (unpack("C*", Sstring)) { $sum += $ascval; print "sum is $sum\n"; # Для строки "an apple a day" выводится сумма 1248 Следующий вариант делает то же самое, но намного быстрее: $sum = unpack("%32C", Sstring); Это позволяет эмулировать программу вычисления контрольной суммы SysV: #!/usr/bin/perl й sura - Вычисление 16-разрядной контрольной суммы всех входных файлов #checksum = 0; while (о) ! Schecksum += unpack("%16C*", S ) } Schecksum %= (2 16) - 1; print "$checksura\n"; Ha практике пример использования выглядит так: % perl sum /etc/termcap 1510 Если у вас установлена GNU-версия sum, для получения идентичного ответа для того же файла ее следует вызвать с параметром -sysv: % sum -sysv /etc/termcap 1510 851 /etc/termcap В примере 1.1 приведена еще одна крошечная программа, в которой также реализована посимвольная обработка входных данных. Идея заключается в том, что- 0 1 2 3 4 5 [ 6 ] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |