Анимация
JavaScript
|
Главная Библионтека Помните, что функция size() не имеет отношения к объему памяти, выделяемой для хранения строки. После проверки всех специальных условий происходит основная обработка данных. Расширение файла заменяется расширением .tmp, обычно используемым для временных файлов; tmpname = filename; tmpname.replace Cidx+1. string;:npos, suffix): Конструкция string::npos в данном случае обозначает «все остальные симво-лы>. Иначе говоря, все символы после точки заменяются строкой suffix. Замена работает н в том случае, если имя файла содержит точку без дальнейших символов - «пустое расширением» заменяется строкой suffix. Команда вывода имен исходного и временного файлов показывает, что для отображения строк могут применяться стандартные потоковые операторы вывода: cout « filename « " => " « tmpname « endl: 1ример чтения слов и вывода символов I обратном порядке Во втором примере отдельные слова читаются из стандартного входного потока данных и символы каждого слова выводятся в обратном порядке. Слова разделяются стандартным символом пропуска (пробелом, новой строкой, табуляцией), запятой, точкой с запятой или двоеточием, string/5tring2.cpp #include <i05tream> #include <string> using namespace std: int main (int argc. char** argv) { const string delimsC" \t..;"): string line; Для каждой успешно прочитанной строки while CgetlineCcin,line)) { string::size type begldx. endldx: Поиск начала первого слова begldx - line.find first not ofCdelims): Пока удается найти начало очередного слова... while Cbegldx != string::npos) { Существование двух эквивалентных функций связано с фактическим слиянием двух архитектурных подходов. Функция Iength() возвращает длину строки и является аналогом функции str!en() для обычных С-строк, тогда как функция size() по;шерживает-ся всеми контейнерными классами и возвращает количество элементов в соответствии с архитектурными канонами STL. Поиск конца текущего слова endldx = 1ine.find first of Cdelims. begldx): if (endldx == string: ;npos) { Конец слова совпадает с концом строки endldx = line.lengthO: Вывод символов в обратном порядке for (int i=endldx-l: i>=static cast<int>(begldx): --i) { cout « line[i]: cout « : Поиск начала следующего слова begldx = line.find first not of (delims. endldx): cout « end!: В этой программе все символы, используемые для разделения слов, определяются в специальной строковой константе: const string delimsC \t..:"): Символ новой строки тоже используется как разделитель. Тем не менее он не требует особой обработки, поскольку программа читает данные по строкам. Внешний цикл работает до тех пор, пока в переменную line успешно читается очередная строка: string line; wtiile (getline(cin,line)) { i" Функция getllne() предназначена для чтения из потока данных в строковую переменную. Она читает все символы до ближайшего разделителя строк, которым по умолчанию является символ новой строки. Разделитель извлекается из потока данных, но не присоединяется к прочитанным данным. Передавая собственный разделитель строк в необязательном третьем аргументе, можно перевести функцию getline() в режим чтения лексем, разделенных заданными символами. Внутри внешнего цикла производится поиск и вывод отдельных слов. Первая команда ищет начало первого слова: begldx = line.find first not of(del1ms): Функция find first not of() возвращает индекс первого символа, не входящего в переданный строковый аргумент. Иначе говоря, функция возвращает первый символ, не указанный в переменной delims как разделитель. Как и прочие функции поиска, при отсутствии совпадения функция find first not of() возвращает string: inpos. Внутренний цикл выполняется до тех пор, пока в потоке данных обнаруживается начало очередного слова: while Cbegldx != string::npos) { ) Первая команда внутреннего цикла ищет конец текущего слова: endldx - l1ne.find f1rst of (delims. begldx): Функция find first of() ищет первое вхождение одного из символов, составляющих первый аргумент. Необязательный второй аргумент определяет позицию, с которой начинается поиск. В нашем случае он начинается за началом слова. Если символ не найден, конец слова совпадает с концом строки: if (endldx « string::npos) { endldx = line.lengthO: Количество символов определяется при помощи функции length(), которая для строк эквивалентна функции size(). В следующей команде все символы слова выводятся в обратном порядке: for (int 1"endldx-l: i>=static cast<lnt>(begldx): --1) { cout « line[1]; Для обращения к отдельным символам строки используется оператор []. Помните, что этот оператор не проверяет действительность индекса. Это означает, что вы должны сами заранее убедиться в правильности индекса (как это сделано в нашем примере). Более безопасный способ обращения к символам основан на применении функции at(). Лишние проверки замедляют работу программы, поэтому обычно при обращении к символам указанная проверка не предусмотрена. С индексами строк связана и другая неприятная проблема. Если забыть о приведении типа begldx к типу int, возможно зацикливание или аварийное завершение программы. Как и в первом примере, это объясняется тем, что string::size type является беззнаковым целым типом. Без преобразования типа знаковое значение i автоматически преобразуется в беззнаковое значение из-за сравнения с другим беззнаковым значением. В этом случае выражение i>=begldx всегда равно true, если текущее слово начинается с начала строки. Дело в том, что переменная begldx в этом случае равна О, а любое беззнаковое значение всегда больше либо равно нулю. Программа зацикливается и прерывается только в результате сбоя при нарушении защиты памяти. По этой причине автор старается избегать применения конструкций string: :slze type и string::npos. На с. 478 описано более безопасное (хотя и не идеальное) обходное решение. Последняя команда внутреннего цикла переводит begldx к началу следующего слова, если его удается найти: begldx = line.find f1rst not of (delims. endldx): В отличие от первого вызова функции find fir5tLnot of() поиск начинается от конца предыдущего слова. Если предыдущее слово завершалось в конце строки, то endldx содержит индекс конца строки. В этом случае поиск начнется от конца строки и вернет string; :npos. 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 |