WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!


Pages:     | 1 | 2 || 4 | 5 |   ...   | 17 |

При выполнении такого оператора сначала вычисляется значение выражения. Если оно равно 0, то оператор не выполняется и управление передается оператору, следующему за ним. Если значение выражения отлично от 0, то выполняется оператор, затем снова вычисляется выражение и т.д.

Возможно, что тело цикла не выполнится ни разу, если выражение сразу будет равно 0.

Пример 1:

char с;

while ( cin.get(c) ) cout<

Здесь происходит копирование символов, включая пробельные, из потока cin (в данном случае из буфера клавиатуры) в поток cout (в данном случае на экран дисплея). Здесь функция get(c) (член класса) извлекает один символ из входного потока, включая пробельные символы.

Возвращает ненулевое значение до тех пор, пока не достигнет конца файла (признак конца файла – ctrl-z).

Пример 2:

while (1) { операторы... } Это – бесконечный цикл.

Пример 3:

char c;

while (( c = cin.get (c)) = = ‘ ‘ || c = = ‘\n‘ || c = = ‘\t’);

Этот оператор цикла пропускает при считывании из потока cin так называемые пробельные символы. Здесь get( ) – другая форма функции, считывающей из потока один символ. Она возвращает целое число – код символа, или число -1, если встретился признак конца файла.

4.8. Цикл с постусловием do-while Этот оператор цикла проверяет условие окончания в конце, после каждого прохода через тело цикла; поэтому тело цикла всегда выполняется по крайней мере один раз.

Вид оператора:

do оператор while (выражение) Сначала выполняется оператор, затем вычисляется выражение и, если оно отлично от нуля, то оператор выполняется снова и т.д.

Если выражение становится равно нулю, цикл завершается.

Такой цикл удобно, например, использовать при проверке вводимых пользователем данных:

int input=0;

int minvalue=10, maxvalue=150;

do { cout <<“Введите значение input \n”; cin >>input;

cout <<“ input=“ << input << “\n”; } while ( input < minvalue || input > maxvalue );

4.9. Оператор for Этот оператор цикла имеет вид:

for ( оператор1 выражение1; выражение2 ) операторОператор1 может быть объявлением, пустым оператором или оператором-выражением.

Наиболее распространенным является случай, когда оператор1 и выражение2 являются присваиваниями или обращениями к функциям, а выражение1 – условным выражением. Этот цикл эквивалентен следующей конструкции:

операторwhile (выражение1) { оператор2 выражение2; } Иногда оператор1 называют инициализатором цикла, а выражение2 – реинициализатором.

Любая из трех частей может быть опущена, хотя точка с запятой обязательно должна оставаться. Если отсутствует проверка, то есть выражение1, то считается, как будто выражение1 отлично от 0, так что for ( ; ; ){... } – бесконечный цикл и его надо каким-либо образом прервать.

Пример1:

int n=20, s=0;

for ( int i = 1; i <= n; i++ ) s+ = ii;

Здесь вычисляется сумма квадратов целых чисел от 1 до 20.

Пример2:

double s, sum, den = 0.85, eps = 1e-10;

for ( s=1, sum=0; s>eps; s=den ) sum+=s;

Здесь вычисляется сумма геометрической прогрессии 1, 10.85, 10.850.85 и т.д., пока ее очередной член не станет меньше 10-10.

В следующем примере вычислим и выведем на экран дисплея y sin(x2 ) x [0, /2] / таблицу функции для с шагом.

#include #include #include void main(){ int n = 10;

double x0 = 0, xk = M_PI_2, y, h = (xk – x0)/n, xt = xk + h/2;

clrscr();

cout<<” x y\n” for(double x = x0; x < xt; x+ = h){ y = sin(x*x);

cout.width(4); cout.precision(2);

cout<

cout.width(10); cout.precision(4);

cout<

} } В этой программе используется константа M_PI_2, представляю / щая значение и определенная в заголовочном файле math.h. Обращение к функции cout.width(k) устанавливает ширину поля следующего вывода в k позиций, что позволяет выровнять вид таблицы.

Функция cout.precision(k) задает число цифр, выводимых после десятичной точки. Функция clrscr(), прототип которой находится в conio.h, очищает экран.

Использовать ли циклы while или for – это, в основном дело вкуса. Цикл for предпочтительнее там, где имеется простая инициализация и реинициализация, поскольку при этом управляющие циклом операторы наглядным образом оказываются вместе в начале цикла. Это наиболее очевидно в конструкции for (i = 0; i < n; i ++), которая применяется для обработки первых n элементов массива, аналогично оператору цикла for Паскаля. Аналогия, однако, не полная, так как границы цикла могут быть изменены внутри цикла, а понятие управляющей переменной в С++ отсутствует и переменная i сохраняет свое значение после выхода из цикла, какова бы ни была причина этого выхода.

4.10. Оператор безусловного перехода Оператор безусловного перехода имеет вид goto метка;

Метка – это имя, за которым следует ‘:’. Этот оператор передает управление оператору, помеченному указанной меткой. С его помощью удобно выходить сразу из нескольких вложенных циклов:

for ( i = 0; i < n; i++) for ( j = 0; j < m; j++) for ( k = 0;k < l; k++) { … операторы;

… if ( условие ) goto lab;

операторы;} lab:;...

С помощью оператора goto можно переходить извне в тело блока, если при этом управление не передается через объявления имен, которые присутствуют в этом блоке.

4.11. Оператор break Этот оператор осуществляет выход из тела цикла for, while, dowhile или оператора switch, в котором он появился. При этом управление передается на первый оператор после цикла.



Оператор не может обеспечить выход сразу из двух или более вложенных циклов.

4.12. Оператор continue Этот оператор осуществляет переход на точку сразу за последним оператором тела цикла без выхода из цикла, так что дальнейшие итерации в цикле будут продолжаться.

Пример вывода четных чисел:

for ( int num = 0; num < 100; num++ ){ if ( num % 2 ) continue;

cout << num << “\n“;

} Когда num становится нечетным, выражение num % 2 получает значение 1 и выполняется оператор, который передает управление на следующую итерацию цикла for, не выполняя вывода.

4.13. Оператор return Этот оператор завершает выполнение функции, в которой он задан, и возвращает управление в вызывающую функцию.

Управление передается в вызывающую функцию в точку, непосредственно следующую за вызовом.

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

5. Указатели 5.1. Определение указателей Указатель – это переменная, содержащая адрес некоторого объекта, например, другой переменной. Точнее – адрес первого байта этого объекта. Это дает возможность косвенного доступа к этому объекту через указатель. Пусть x – переменная типа int. Обозначим через px указатель. Унарная операция & выдает адрес объекта, так что оператор px = &x;

присваивает переменной px адрес переменной x. Говорят, что px “указывает” на x. Операция & применима только к адресным выражениям, так что конструкции вида &(x-1) и &3 незаконны.

Унарная операция называется операцией разадресации или операцией разрешения адреса. Эта операция рассматривает свой операнд как адрес и обращается по этому адресу, чтобы извлечь объект, содержащийся по этому адресу.

Следовательно, если y тоже имеет тип int, то y = px;

присваивает y содержимое того, на что указывает px. Так, последовательность px = &x;

y = px;

присваивает y то же самое значение, что и оператор y = x;

Все эти переменные должны быть описаны:

int x, y;

int px;

Последнее – описание указателя. Его можно рассматривать как мнемоническое. Оно говорит, что комбинация px имеет тип int или, иначе, px есть указатель на int. Это означает, что если px появляется в виде px, то это эквивалентно переменной типа int.

Из описания указателя следует, что он может указывать только на определенный вид объекта (в данном случае int). Разадресованный указатель может входить в любые выражения там, где может появиться объект того типа, на который этот указатель ссылается. Так, оператор y = px + 2;

присваивает y значение, на 2 больше, чем х.

Заметим, что приоритет унарных операций и & таков, что эти операции связаны со своими операндами более крепко, чем арифметические операции, так что выражение y = px + берет то значение, на которое указывает px, прибавляет 2 и присваивает результат переменной y.

Если px указывает на х, то px = 3;

полагает х равным 3, а px + = 1;

увеличивает х на 1 так же, как и выражение (px) ++ Круглые скобки здесь необходимы. Если их опустить, то есть написать px ++, то, поскольку унарные операции, подобные и ++, выполняются справа – налево, это выражение увеличит px, а не ту переменную, на которую он указывает.

Если py – другой указатель на int, то можно выполнить присвоение py = px;

Здесь адрес из px копируется в py. В результате py указывает на то же, что и px.

5.2. Указатели и массивы Массив – это совокупность элементов одного типа, которые расположены в памяти ЭВМ подряд, один за другим.

Признаком объявления массива являются квадратные скобки.

Объявить массив из 10 элементов типа float можно так:

float a[10];

Чтобы обратиться к элементу этого массива, нужно применить операцию индексирования a[ind]. Внутри квадратных скобок помещается целое выражение, которое называется индексом. Нумерация элементов массива начинается с 0 и поэтому вышеприведенное описание говорит о том, что в памяти ЭВМ зарезервировано место под 10 переменных типа float и эти переменные есть a[0], a[1],..., a[9].

Приведем пример с использованием массива.

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

Число пробельных символов будем хранить в nwhite, прочих символов – в nother, а число появлений каждой из цифр – в массиве ndigit:

# include void main( ) { int c, i, nwhite = 0, nother = 0;

int ndigit [10];

for ( i=0; i<10; i++) ndigit[i]=0;

while ( ( c=cin.get( ) )!=EOF) if(c>=‘0’ && c<=‘9’) ++ ndigit[c – ’0’];

else if (c = = ‘ ‘|| c = = ‘\n‘ || c = = ‘\t‘) ++ nwhite;

else ++ nother;

cout<<“ цифра \n”;

for( i=0; i<10; i ++) cout<

cout<<“ пробельных символов – “<< nwhite <<“ прочих символов – ” << nother <<“\n”; } При объявлении массива его можно инициализировать:

int c[ ] = { 1, 2, 7, 0, 3, 5, 5 };

char array[ ] = { ’h’, ’e’, ’l’, ’l’, ’o’, ’\n’, ’\0’};

Последнюю инициализацию разрешается выполнять проще:

char array[ ] = “hello\n”;

Такой синтаксис инициализации разрешен только для строк. Компилятор сам вычислит необходимый размер памяти с учетом автоматически добавляемого в конец строки символа ’\0’ с кодом 0, который является признаком завершения строки.

В языке С++ имя массива является константным указателем на первый элемент этого массива:

int mas[20];

int pmas;

pmas = &mas[0];

Последний оператор можно записать и так: pmas = mas;





Операция индексирования массива [ ] имеет 2 операнда – имя массива, т.е. указатель, и индекс, т.е. целое: a[i]. В языке С++ любое выражение указатель[индекс] по определению трактуется как (указатель + индекс) и автоматически преобразуется к такому виду компилятором.

Таким образом, a[3] эквивалентно (a + 3). Более того, это можно записать даже так 3[a], так как это все равно будет проинтерпретировано как (3+a). Здесь складываются указатель a и целое 3. В связи с этим рассмотрим так называемую адресную арифметику.

5.3. Адресная арифметика Указатель можно складывать с целым.

Если к указателю pa прибавляется целое приращение i, то приращение масштабируется размером памяти, занимаемой объектом, на который указывает указатель pa.

Таким образом, pa+i – это адрес i-го элемента после pa, причем считается, что размер всех этих i элементов равен размеру объекта, на который указывает pa.

Итак, если a – массив, то a+i – адрес i-го элемента этого массива, т.е.

&a[i] равен a+i и a[i] равняется (a+i).

float b[10];

float pb=b;

pb++; // Это эквивалентно pb=pb+1.

// Здесь указатель pb будет указывать на элемент массива b[1].

pb+=3; // Здесь pb указывает на элемент массива b[4].

Отметим, что нельзя написать b++ или b = b+i, так как имя массива b – это константный указатель и его изменять нельзя.

Указатели можно сравнивать.

Если p и q указывают на элементы одного и того же массива, то такие отношения, как < >= и т.д. работают надлежащим образом. Например, p < q истинно, т.е. = = 1, если p указывает на более ранний элемент массива, чем q. Любой указатель можно сравнить на равенство или неравенство с так называемым нулевым указателем NULL, который ни на что не указывает. Однако не рекомендуется сравнивать указатели, указывающие на различные массивы.

Указатели можно вычитать.

Если p и q указывают на элементы одного и того же массива, то p – q дает количество элементов массива между p и q.

5.4. Символьные массивы и строки Строка является массивом символов. Значением строки является указатель на первый ее символ:

char string = “строка\n”;

Здесь указатель на символы string будет содержать адрес первого символа ‘c’ строки “строка\n”, которая размещается в некоторой области памяти, начиная с этого адреса:

string с т р о к а \n \Здесь string[3] = = ’о’.

Рассмотрим фрагмент программы:

char buffer[ ] =“ ”; // Инициализация // строки из 10 пробелов.

char *string = buffer; // string указывает на начало буфера.

string=“проба\n”; // Присваивание! При инициализации создается строка buffer и в нее помещаются символы (здесь 10 пробелов). Инициализация char *string=buffer устанавливает указатель string на начало этой строки.

Операция же присваивания в последней строке не копирует приведенную строку “проба\n” в массив buffer, а изменяет значение указателя string так, что он начинает указывать на строку “проба\n”:

buffer \string п р о б а \n \Чтобы скопировать строку “проба\n” в buffer, можно поступить так:

char buffer[ ] = “ ”;

char p =“проба\n”;

int i =0;

while ( ( buffer[i] = p[i] ) != ’\0’ ) i++;

Или так:

char buffer[ ] = “ ” char p = “проба\n”;

char buf = buffer;

while (buf ++ = p ++ );

Здесь сначала p копируется в buf, т.е. символ ‘п’ копируется по адресу buf, который совпадает с адресом buffer, т.е. buffer[0] становится равен ‘п’. Затем происходит увеличение указателей p и buf, что приводит к продвижению по строкам “проба\n” и buffer соответственно. Последний скопированный символ будет ’\0’, его значение – 0 и оператор while прекратит цикл.

Еще проще воспользоваться библиотечной функцией, прототип которой находится в файле string.h:

strcpy( buffer, “проба\n”);

При копировании необходимо обеспечить, чтобы размер памяти, выделенной под buffer, был достаточен для хранения копируемой строки.

5.5. Многомерные массивы Двумерный массив рассматриваются как массив элементов, каждый из которых является одномерным массивом. Трехмерный – как массив, элементами которого являются двумерные массивы и т.д.

После объявления int a[5][6][7];

в программе могут появиться выражения:

a[i][j][j] – объект типа int;

a[2][0] – объект типа int* – одномерный массив из 7 целых;

a[1] – двумерный массив из 6*7 = 42 целых;

a – сам трехмерный массив.

Так как элементом массива a является двумерный подмассив размером 6*7, то при выполнении выражения a + 1 происходит смещение на величину элемента массива a, т.е. переход от a[0] к a[1]. Значение адреса при этом увеличивается на 6*7*sizeof(int) =84.

Для двумерного массива mas выражение mas[i][j] интерпретируется как *(*(mas+i)+j). Здесь mas[i] – константный указатель на i-ю строку массива mas.

В памяти массивы хранятся по строкам, т.е. при обращении к элементам в порядке их размещения в памяти быстрее всего меняется самый правый индекс.

Так, для массива c[2][3] его шесть элементов расположены в памяти так:

c[0][0] c[0][1] c[0][2] c[1][0] c[1][1] c[1][2].

Многомерные массивы также можно инициализировать при описании:

int d[2][3]={ 1, 2, 0, 5 };

В этом случае первые 4 элемента массива получат указанные значения, а остальные два инициализируются нулями.

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

int f [ ][2] = { 2, 4, 6, 1 }; // массив f [2][2];

Pages:     | 1 | 2 || 4 | 5 |   ...   | 17 |










© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.