Главная - Литература

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 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

12.4. Символы и строки

Этот раздел предлагает несколько советов по использованию строк. Первый относится к строкам во всех языках.

Избегайте магических символов и строк Магические

символы - это литеральные символы (например, Л), а ма- вспользовшй мйгических сим-гические строки - это литеральные строки (например, еоцоа и отрок шттты т-Gigamatic Accounting Program), которые разбросаны по всей просам пришнения uwmma программе. Если ваш язык программирования поддерживает " (w. раздел 12,1). применение именованных констант, то лучше задействуйте их. В противном случае используйте глобальные переменные. Далее перечислено несколько причин, по которым надо избегать литеральных строк.

Для таких часто встречающихся строк, как имя программы, названия команд, заголовки отчетов и т. п., вам может понадобиться поменять содержимое. Например, Gigamatic Accounting Program"" в более поздней версии может измениться на ""New and Improved! Gigamatic Accounting Program.

Bee большее значение приобретают международные рынки, и строки, сгруппированные в файле ресурсов переводить гораздо легче, чем раскиданные по всей программе.

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

Символьные и строковые литералы могут быть загадочными. Комментарии или именованные константы проясняют ваши намерения. В следующем примере смысл 0x1В неясен. Константа ESCAPE делает значение более понятным.

Пример сравнений с использованием строк (С++)

- Плохо!

if ( input char == Ох1В ) . . .

- Лучше!

if ( input char ESCAPE ) . . .

Следите за ошибками завышения/занижения на единицу Поскольку подстроки могут индексироваться аналогично массивам, не забывайте об ошибках завышения/занижения на 1, которые приводят к чтению или записи за концом строки.

Узнайте, как ваш язык и система поддерживают Unicode В некоторых языках, например в Java, все строки хра- ШЩМй1ьлтП2Ш нятся в формате Unicode. В других - таких, как С и С++ -

работа со строками в Unicode требует применения отдельного набора функций. Преобразование между Unicode и другими наборами символов часто необходимо для взаимодействия со стандартными библиотеками и библиотеками сторонних про-



изводителей. Если часть строк не будет поддерживать Unicode (скажем, в С или С++), как можно раньше решите, стоит ли вообще использовать символы Unicode. Если вы решились на это, подумайте, где и когда будете это делать.

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

Если вам известно, что нужно поддерживать таль-htt$>: €c2e.com/12a2 один алфавит, рассмотрите вариант использования набора символов ISO 8859 Для приложений, использующих только один алфавит (например, английский), которым не надо поддерживать несколько языков или какой-либо идеографический язык (такой как письменный китайский), расширенный ASCII-набор стандарта ISO 8859 - хорошая альтернатива символам Unicode.

Если вам необходимо поддерживать несколько языков, используйте Unicode Unicode обеспечивает более полную поддержку международных наборов символов, чем ISO 8859 или другие стандарты.

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

Строки в языке С

Строковый класс в стандартной библиотеке шаблонов С++ решил большинство проблем со строками языка С. А тот, кто напрямую работает с С-строками, ниже узнает о способах избежать часто встречающихся ошибок.

Различайте строковые указатели и символьные массивы Проблемы со строковыми указателями и символьными массивами возникают из-за способа обработки строк в С. Учитывайте различия между ними в двух случаях.

Относитесь с недоверием к строковым выражениям, содержащим знак равенства. Строковые операции в С практически всегда выполняются с помощью strcmpO, strcpyO, strlenQ и аналогичных функций. Знаки равенства часто сигнализируют о каких-то ошибках в указателях. Присваивание в С не копирует строковые константы в строковые переменные. Допустим, у нас есть выражение:

StringPtr = "Some Text String";

В этом случае ""Some Text String - указатель на литеральную текстовую строку, и это присваивание просто присвоит указателю StringPtr адрес данной строки. Операция присваивания не копирует содержимое в StringPtr.

Используйте соглашения по именованию, чтобы различать переменные - массивы символов и указатели на строки. Одно из общепринятых соглашений - использование ps как префикса для обозначения указателя на строку, и асЬ - как префикса для символьного массива. И хотя они не всегда ошибочны, от-



носитесь все-таки с подозрением к выражениям, включающим переменные с обоими префиксами.

Объявляйте для строк в стиле С длину, равную КОНСТАНТА-1 В С и С++

ошибки завышения на 1 в С-строках - обычное явление, потому что очень легко забыть, что строка длины п требует для хранения w + i байт, и не выделить место для нулевого терминатора (байта в конце строки, установленного в 0). Эффективный способ решения этой проблемы - использовать именованные константы при объявлении всех строк. Суть в том, что именованные константы применяются всегда одинаково: Сначала длина строки объявляется кж КОНСТАНТА+1, а 32тш КОНСТАНТА используется для обозначения длины строки во всем остальном коде. Вот пример-.

Пример правильных объявлений строк (С)

/* Объявляем строку длиной «константа+1».

Во всех остальных местах программы используем «константа», а не «константа +1». */

г- Эта строка объявлена с длиной NAME LENGTH +1.

->char name[ NAME LENGTH + 1 ] = { О }; /* Длина строки - NAME LENGTH */

/* Пример 1: Заполняем строку символами А, используя константу NAME LENGTH для определения количества символов А, которые можно скопировать. Заметьте: используется NAME LENGTH, а не NAME LENGTH + 1. */

- В действиях со строкой NAME LENGTH используется здесь...

->for ( i = 0; i < NAME LENGTH; i++ ) name[ i ] = A;

/* Пример 2: Копируем другую строку в первую, используя константу для определения максимальной длины, которую можно копировать. */

- ...и здесь.

->strncpy( name, some other name, NAME LENGTH );

Если у вас не будет соглашения по этому поводу, иногда вы будете объявлять строки тиной NAMELENGTH, а в операциях использовать AEZJE/VGTH-i; а иногда вы будете объявлять строки длиной NAME LENGTH- 1 и работать с NAME LENGTH. Каждый раз при использовании строки вам придется вспоминать, как вы ее объявили.

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

Инициализируйте строки нулем во избежание строк щщ ттм Подроб-бесконечной длины Язык С определяет конец строки пу- йнйциапйзаш»» ттж

тем поиска нулевого терминатора - байта в конце строки, ш. раздел 10.3. установленного в 0. Какой предполагалась длина строки, зна-



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 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294



0.0115