{ printf("B ы ввели значение %d\n",num); }

Данный цикл будет работать, пока пользователь вводит целочисленные значения и останавливается, если введена буква или вещественное число.

Следует отметить, что цикл while можно принудительно завершить даже при истинном условии цикла. Это достигается путем использования оператора break. Перепишем предыдущий пример так, чтобы цикл завершался, если пользователь введет число 0.

int num;

while(scanf("%d",& num ) == 1)

{ if(num == 0) break;

printf(" Вы ввели значение %d\n",num);}

Цикл завершается сразу после использования оператора break, т.е. в приведенном примере, при вводе с клавиатуры нуля функция printf() выполняться не будет и программа перейдет на следующий оператор после while.

Того же результата можно добиться, если использовать составное условие в цикле:

int num;

while(scanf("%d",& num ) == 1 && num != 0)

{ printf("B ы ввели значение %d\n",num);}

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

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

Синтаксис оператора for следующий:

for ( <инициализация счетчика>;<условие>;<изменение значения счетчика>)

{ <тело цикла> }

Рассмотрим особенность реализации данного оператора на примере вывода таблицы кодов ASCII символов.

char ch;

for(ch = 'a'; ch <= 'z'; ch++)

printf("Значение ASCII для %c - %d.\n",ch,ch);

В данном примере в качестве счетчика цикла выступает переменная ch, которая инициализируется символом ‘a’. Это означает, что в переменную ch заносится число 97 - код символа ‘a’. Именно так символы представляются в памяти компьютера. Код символа ‘z’ - 122, и все малые буквы латинского алфавита имеют коды в диапазоне [97; 122]. Поэтому, увеличивая значение ch на единицу, получаем код следующей буквы, которая выводится с помощью функции printf(). Учитывая все вышесказанное, этот же пример можно записать следующим образом:

for(char ch = 97; ch <= 122; ch++)

printf("Значение ASCII для %c - %d.\n",ch,ch);

Здесь следует отметить, что переменная ch объявлена внутри оператора for. Это особенность языка С - возможность объявлять переменные в любом месте программы.

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

int line_cnt = 1;

double debet;

for(debet = 100.0; debet<150.0; debet=debet*1.1, line_cnt++)

printf("%d. Ваш долг теперь равен %.2f.\n", line_cnt, debet);

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

int exit = 1;

for(int num = 0;num < 100 && !exit; num += 1)

{ scanf("%d",&mov);

if(mov == 0) exit = 0;

printf("Произведение num*mov = %d.\n",num*mov);

}

Оператор for с одним условием:

int i=0;

for( ; i < 100 ; )

i++;

и без условия

int i=0;

for( ; ; ; )

{i++;

if(i > 100) break;

}

В последнем примере оператор break служит для выхода из цикла for, т.к. он будет работать «вечно» не имея никаких условий.

Бывают ситуации, когда целесообразно выполнять проверку условия после того, как будут выполнены операторы, стоящие внутри цикла. Это достигается путем использования операторов do while, которые реализуют цикл с постусловием.

Пример:

const int secret_code = 13;

int code_ent;

do {

printf("Введите секретный код: ");

scanf("%d",&code_ent);

}

while (code_ent != secret_code);

Цикл с постусловием работает до тех пор, пока истинно условие, то есть пока значение введенного кода будет отличаться от значения секретного кода.

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

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

двойного ряда S = ∑∑ ( i* j ) :

long S = 0;

int M = 10, N = 5;

for( int i = 0; i <= N; i++)

{ for( int j = 0; j <= M; j++)

S += i*j; }

Того же результата можно добиться и с помощью оператора цикла while.

М ассивы.

 

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

<тип данных> <имя массива>[число элементов];

Например:

int array_int[100]; //одномерный массив 100 целочисленных

// элементов

double array_d[25]; //одномерный массив 25 вещественных

// элементов

Объявление массивов отличается от объявления обычных переменных наличием квадратных скобок [ ].

Также имена массивов выбираются по тем же правилам, что и имена переменных. Обращение к отдельному элементу массива осуществляется по номеру его индекса.

Пример: запись в массив значений линейной функции

f (х) = kx + b и вывода значений на экран:

double k=0.5, b = 10.0;

double f[100];

for(int x=0; i < 100; i++)

{ f[i] = k*x+b;

printf("%.2f ",f[i]); }

В языке С предусмотрена возможность инициализации массива в момент его объявления, например, таким образом

int powers[4] = {1, 2, 4, 6};

В этом случае элементу powers[0] присваивается значение 1, powers[1] - 2, и т.д.

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

Например, следующая программа приведет к ошибке при компиляции:

int N=100;

float array_f[N]; //ошибка, так нельзя .

Поэтому при объявлении массивов обычно используют такой подход:

#include <stdio.h>

#define N 100

int main()

{ float array_f[N];

return 0; }

Следует отметить, что при инициализации массивов число их элементов должно совпадать с его размерностью.

Рассмотрим вариант, когда число элементов при инициализации будет меньше размерности массива.

#define SIZE 4

int data[SIZE]={512, 1024};

for(int i = 0; i < SIZE; i++)

printf("%d, \n",data[i]);

Результат работы программы будет следующим:

512, 1024, 0, 0

Из полученного результата видно, что неинициализированные элементы массива принимаются равными нулю. В случаях, когда число элементов при инициализации превышает размерность массива, то при компиляции произойдет ошибка. Поэтому, когда наперед неизвестно число элементов, целесообразно использовать такую конструкцию языка C++:

int data[] = {2, 16, 32, 64, 128, 256};

В результате инициализируется одномерный массив размерностью 6 элементов.

Если значение индекса при обращении к элементу массива превысит его размерность, то этом случае ни программа, ни компилятор не выдадут значение об ошибке, но в программе могут возникать непредвиденные ошибки.

Поэтому программисту следует обращать особое внимание на индексы, которые при обращении к элементам массива не выходили за его пределы.

Также следует отметить, что первый элемент массива всегда имеет индекс 0, второй - 1, и т.д.

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

int array2D[100][20]; //двумерный массив 100x20 элементов

Нумерация элементов также начинается с нуля, т.е. array2D[0][0] соответствует первому элементу, array2D[0][1] - элементу первой строки, второго столбца и т.д.

Для начальной инициализации двумерного массива может использоваться следующая конструкция:

long array2D[3][2] = {{1, 2},{3, 4},{5, 6}};

или

long array2D[][] = {{1, 2},{3, 4},{5, 6}};

В общем случае можно задать массив любой размерности и правила работы с ними аналогичны правилам работы с одномерными и двумерными массивами.

 

Р абота со строками в языке С .

 

В языке С нет специального типа данных для строковых переменных. Для этих целей используются массивы символов (тип char).

Пример:

char str_1[100] = {'П,,,р,,,и,,,в,,,е,,,т,,,\0'};

char str_2[100] = "Привет";

char str_3[ ] = "Привет";

printf("%s\n%s\n%s\n",str_1,str_2,str_3);

В приведенном примере показаны три способа инициализации строковых переменных.

Первый способ является классическим объявлением массива,

второй и третий используются специально для строк. Причем в последнем случае, компилятор сам определяет нужную длину массива для записи строки.

Cпециальные управляющие коды, которые показывают, где заканчивается строка или где используется перенос внутри одной строки и т.п.

В частности символ ‘\0’ означает в языке С++ конец строки и все символы после него игнорируются как символы строки.

Пример :

char str1[10] = {'Л','е','к','ц','и','я','\0'};

char str2[10] = {'Л','е','к','ц', '\0','и','я'};

char str3[10] = {'Л','е', '\0','к','ц','и','я'};

printf("%s\n%s\n%s\n",str1,str2,str3);

Результатом работы данного кода будет вывод следующих трех строк:

Лекция

Лекц

Ле

Из этого примера видно как символ конца строки ‘\0’ влияет на длину строк. Таким образом, чтобы подсчитать длину строки (число символов) необходимо считать символы до тех пор, пока не встретится символ ‘\0’ или не будет достигнут конец массива. Функция вычисления размера строк уже реализована в стандартной библиотеке языка С string.h и имеет следующий синтаксис:

int strlen(char* str);

где char* str - указатель на строку.

Пример использования функции strlen() :

#include <stdio.h>

#include <string.h>

int main(void)

{ char str[ ] = "Привет мир!";

int length = strlen(str);

printf("Длина строки = %d.\n",length);

return 0; }

Результатом работы программы будет вывод на экран числа 11. Учитывая, что первый символ имеет нулевой индекс, то можно заметить, что данная функция считает и символ ‘\0’.

Пусть объявлены две строки

char str1[ ] = "Это первая строка";

char str2[ ] = "Это вторая строка";

и необходимо выполнить оператор присваивания

str1 = str2;

При такой записи оператора присваивания компилятор выдаст сообщение об ошибке.

Для того чтобы выполнить копирование необходимо перебирать по порядку элементы одного массива и присваивать их другому массиву. Данная функция реализована в библиотеке языка С string.h и имеет следующее определение:

char* strcpy(char* dest, char* src);

Она выполняет копирование строки src в строку dest и возвращает строку dest.

Пример использования функции strcpy() :

#include <stdio.h>

#include <string.h>

int main(void)

{

char src[] = "Привет мир!";

char dest[100];

strcpy(dest,src);

printf("%s\n",dest);

return 0; }

Кроме операций вычисления длины строки и копирования строк важной является операция сравнения двух строк между собой.

В языке С две строки считаются одинаковыми, если равны их длины и элементы одной строки равны соответствующим элементам другой. Функция сравнения двух строк имеет вид:

int strcmp(char* str1, char* str2);

и реализована в библиотеке string.h. Данная функция возвращает нуль, если строки str1 и str2 равны и не нуль в противном случае.

Пример использования данной функции:

char str1[ ] = "Это первая строка";

char str2[ ] = "Это вторая строка";

if(strcmp(str1,str2) ==0)

printf("С т рока %s равна строке %s\n",str1,str2);

else printf("С т рока %s не равна строке %s\n",str1,str2);

В языке С имеется несколько функций, позволяющих вводить строки с клавиатуры. Самой распространенной из них является ранее рассмотренная функция scanf(), которой в качестве параметра передается ссылка на массив символов:

char str[100];

scanf("%s",str);

В результате выполнения этого кода, переменная str будет содержать введенную пользователем последовательность символов. Кроме функции scanf() также часто используют функцию gets() библиотеки stdio.h, которая в качестве аргумента принимает ссылку на массив символов:

get s (str);

Данная функция считывает символы до тех пор, пока пользователь не нажмет клавишу Enter, т.е. введет символ перевода строки ‘\n’.

Затем она записывает вместо символа ‘\n’ символ ‘\0’ и передает строку вызывающей программе.

Для вывода строк на экран помимо функции printf() можно использовать также функцию puts() библиотеки stdio.h, которая более проста в использовании. Пример:

#define DEF "Заданная строка"

char str[ ] = "Это первая строка";

puts(str);

puts (DEF);

puts(&str[4]);

Результат работы следующий: