Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Операции уменьшения и увеличения.

Поиск

В языке Си широко используются две нетрадиционные операции для увелечения и уменьшения значения переменной, обозначенные соответственно ++ и --. Операция ++ прибавляет единицу к операнду, а -- вычитает.Эти операции могут быть использованны и перед, и после своего операнда. Они оказывают разные действия в выражениях: в записи ++n увеличение происходит до использования значения n, а в n++ увеличение идет уже после того, как используется значение n. Если считать, что значение n равно 5, то переменная m в выражении m=++n,будет иметь значение 6, а в выражение m=n++ переменная m равна 5, в том и этом случае переменная n будет равняться 6. Первый пример в точности соответствует следующей последовательности операторов n=n+1; m=n; а второй последовательности m=n; n=n+1; Операция действует аналагично.Обе операции имеют самый низкий приоритет и выполняются после бинарных операций + и -. Рассмотрим пример 3.1.

Пример 3.1

/*определить двузначные целые числа, которые делятся на сумму своих цифр*/ #include <stdio.h> main() { int a,b,k,s,c; k=0;a=1; while(a<=9) { b=0; while(b<=9) { s=a+b; c=a*10+b; if(c%s==0) { printf("%d",c); k++; } b++; } a++; printf("\n"); } printf("всего: %d\n", k); }

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

& - поразрядное И ^ - поразрядное исключающее ИЛИ >> - сдвиг вправо | - поразрядное ИЛИ << - сдвиг в лево ~ - инверсия

Поразрядная операция И (&) часто используется для выделения некотрой группы двоичных разрядов, напрмер n=n&0177 устанвливает в нуль все двоичные разряды числа n, кроме семи младших. Операция ИЛИ(|) используется для установки отдельных разрядов в единицу. Напрмер. m=m | 0xF0F; "включает" 11,10, 9,8,3,2,1 и 0 разряды числа m. Операции << и >> выполняют сдвиг операдна влево или вправо на заданное число разрядов. Напрмер, m<<3 сдигает значение m на 3 разряда влево, заполняя освобождающиеся младшие разряды нулями. Унарная операция ~ выполняет инверсию двоичных разрядов числа(символа), т.е. преобразует каждый единичный бит в нулевой и наоборот. Применение некоторых поразрядных операций покажем на примерах. В программе на прмере 3.2 исходное число 511 дано в шестнадцатиричной форме: m= 0X|FF; Напомним, что написанная перед константой число 0 указывает на восьмеричное число, а 0X на шестнадцатиричное. Для выода результата предусмотрена функция PRINT. Она для удобства анализа результатов печатает числа в шестнадцатиричном, восьмеричном и десятиричном форматах, используя для этого спецификацию x, o,d. Остальные действия в программе коментируются и дополнительных пояснений не надо.

Пример 3.2

/*поразрядные логические операции*/ #include <stdio.h > PRINT(n) int n; { printf("%5x %5o %5d \n",n,n,n); } main() { int m,n; m=0X1F3; PRINT(m); /*16- ричное число*/ n=m&0177 PRINT(n); /* выделение 7 мл.бит*/ n=m|013; PRINT(n); /*установка 4 мл.бит*/ n=m>>4; PRINT(n); /*сдвиг вправо*/ m=n<<3; PRINT(m); /*сдвиг влево*/ }

Следующяя программа (прмер 3.3), используя команду сдвига числа вправо на один бит (m=n>> 1;) и выделения младшего разряда числа (m&01), подсчитывает кол-во единичных битов исходного числа и печатает результат.

Пример 3.3

/* подсчет единиц */ #include <stdio.h> main() { int m,k; k=0; m=0xf0f; while(m!=0) { if(m&01)k++; m=m>>1; } printf("k=%d\n",k); }

Операции присваивания и выражения. Выражение вида i=i+b, где левая часть повторяется в правой части, могут быть заменены в сжатой форме: i+ =b. При этом используется операция присваивания вида +=, которая означает буквально "увеличить i на b". Для большинства бинарных операций допускается запись вида op=, где op - одна из операций: + - / % | ^ & <<>>. Если E1op=E2 эквивалентно E1=(E1)op(E2). Обратите внимание на скобки вокруг E2; присвание x*=y+1 фактически означает x=x*(y+1), а не x=x*y+1. В качестве иллюстраций, поясняющей сказанное, рассмотрим программу (пример 3.4), в которой по заданному натуральному числу n строится число m, написанное теми же цифрами, что и n, но взятыми в обратном порядке. Правду говоря, запись m=m*10+z более прозрачна, чем непривычная последовательность m*=10; m+=z.

Пример 3.4

#include stdio.h main() { int n,z,m=0; printf("введиn n\"); scanf("%d",&n); while(n!=0) { z=n%10; n/=10; m*=10; m+=z } printf("m=%d\n",m); }

Условная операция. Фактически она представляет собой сокращенную форму оператора if - then - else, и в общем виде записывается так: выражение1? выражение2? выражение3?. Если "выражение1" не равно нулю, то результатом операции будет значение "выражение2", в противном случае - значение "выражение3". Условная операция, называемая иногда тенарной, определяет обычное выражение. которое может. в частности, быть использовано в операторе присваивания. Таким образом, вместо if(x > y) max=c; else max=y; достаточно написать: max=(x>y)& x:y. Скобки вокруг "выражения1" ставить не обязательно, так как приоритет операции :? очень низкий, ниже он только у присваивания. Условная операция позволяет писать долее короткие программы. Вот как выглядит в программе (пример 3.5) цикл для печати квадратов натуральныз чисел от 1 до m, по 6 чисел в строке; каждое число занимает 5 позиций и колонки отделяются одним пробелом, а каждая строка, включая последнюю, заканчивается символом перевода на новую строку "печатается" после каждого шестого элемента и после m-го. За любыми другими элементами выводится один пробел.

Пример 3.5

/*квадраты натуральных чисел*/ main() { int m,i=1;scanf("%d",&m); while(i_=m) { printf("5%d%c",i*i,(i%6==0 || i==m)? '\n':' '); i++; } }

Массивы

Как известно, массив - это конечная совокупность данных одного типа. Можно говорить о массивах целых чисел, массивов символов и.т.д. Мы можем даже определить масссив, элементы которого - массивы(массив массивов), определяя, таким образм, многомерные массивы. Любой массив в программе должен быть описан: после имени массива добаляют квадратные скобки [], внутри которых обычно стоит число, показывающее количество элементов массива. Например, запись int x[10]; определяет x как массив из 10 целых чисел. В случае многомерных массивов показывают столько пар скобок, какова размерность массива, а число внутри скобок показывает размер массива по данному измерению. Например, описание двумерного массива выглядит так: int a[2][5];. Такое описание можно трактовать как матрицу из 2 строк и 5 столбцов. Для обрщения к некоторому элементу массива указывают его имя и индекс, заключенный в квадратные скобки(для многомерног массива - несколько индексов, заключенные в отдельные квадратные скобки): a[1][3], x[i] a[0][k+2]. Индексы массива в Си всегда начинаются с 0, а не с 1, т.е. описание int x[5]; порождает элементы x[0], x[1], x[2], x[3], x[4], x[5]. Индекс может быть не только целой константой или целой переменной, но и любым выражением целого типа. Переменная с индексами в программе используется наравне с простой переменной (например, в операторе присваивания, в функциях ввода- вывода). Начальные значения массивам в языке Си могут быть присвоены при компиляции только в том случае, если они объявлены с классом памяти extern или static, например:

static int a[6]={5,0,4,-17,49,1};
обеспечивает присвоения a[0]=5; a[1]=0; a[2]=4... a[5]=1. Как видите, для начального присвоения значений некоторому массиву надо в описании поместить справа от знака = список инициирующих значений, заключенные в фигурные скобки и разделенные запятыми. Двумерный массив можно инициировать так:

static int matr[2][5] = {{3,4,0,1,2},{6,5,1,4,9}};

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

Пример 3.6

/*обращение массива*/ #include <stdio.h> main() { int p,i=0; static a[10]={10,11,12,13,14, 15,16,17,18,19}; while(i<10/2) { p=a[i]; a[i]=a[9-i]; a[9-i]=p; i++; } i=0; while(i<10) printf(" %d",a[i++]); }

Следующяя программа (пример 3.7)позволяет в целочисленном массиве найти разность максимального и минимального элемента. Обратите внимание, что функция fmax при первом обращении к ней дает максимальный элемент массива, а при повторном вызове - минимальный, так как предварительно мы изменили знаки элементов на противоположные. Это изменение знаков учитывается при вызове функции printf. В языке Си отсутствует возможность динамически распределять память под массивы: надо при описании массива задать точно его размер. Но если тот же массив описывается еще раз в другой программе, размеры можно не указывать;достаточно после имени сохранить пару квадратных скобок, например int x[]. Если при вызове функции в качестве аргумента ей передается имя массива, то, в отличае от простых переменных, берется фактически адрес начала этого массива. Поэтому записи fmax(a, 10) и fmax(&a[0], 10) равносильны.

Пример 3.7

/*в массиве найти разность мин. и макс. элементов */ int fmax(x,n) int x[],n; { int max, i=0; max=x[0]; while(i<n) { if(x[i]> max) max=x[i]; i++; } return(max); } #include <stdio.h> main() { static int a[10]= {1,-2,3,-4,5,-6,7,-8,9,-13}; max=fmax(a,10); i=0; while(i<10) { a[i]=-a[i]; i++; } main=fmax(a,10); printf("макс-мин=%d\n",max+min); }

В следующем пример 3.8 массив описан как внешний. Функция main подсчитывает наибольшее число одинаковых идущих подряд элементов массива, определенного вне функции main.

Пример 3.8

/*макс одинаковых подряд*/ #include <stdio.h> int a[]={5,6,6,6,4,3,3,3,3,3,8}; int n=10; main() { int i,k,max; i=k=max=1; while(i<n) { if(a[i]==a[i-1]) k++; else { if(k>max)max=k; k=1; } i++; } printf("kmax=%d\n",(k>max)?k:max); }

Если, как в данном примере, размер массива пропущен, то транслятор определит его дляну, считая присваиваемые значения во время начальной инициализации. Условная операция (k>max) ?k:max в операторе printf предусмотрена для того частного случая, когда весь массив состоит из одинаковых элементов. Приведем несколько примеров, в которых ведется обработка двумерных массивов. Но прежде одну полезную возможносить языка Си. Речь идет о препроцессорном утверждении #difine, позволяющем присваивать символические имена константам. В общем случае это утверждение записывают так: #define строка1 строка2 (точка с запятой не ставится).
Прежде чем исходный текст программы будет передан компилятору, он обрабатывается препроцессором, котоый всюду в исходном текстезаменит вхождение "строка1" на "строка2". Например, строка #difine max 80, записанная в начале программы, обеспечит всюду замену указанного имени max на соответствующую константу. Замена имени связана не только числами, но и текстами. А теперь вернемся к примерам. В следующей программе (пример 3.9) строится единичная матрица a[m][m], размер которой определяется с помощью конструкции #difine m 5. Сам алгоритм вычисления элементов матрицы основан на возведении (i/j)*(j/i) равно единице тогда и только тогда. когда i равно j. В остальных случаях оно равно нулю.

Пример 3.9

#define M 5 #include <stdio.h> main() { int a[M][M]; int j,i=0; while(i<M) { j=1; while(j<M) { a[i][j]=(i/j)*(j/i); printf("%d",a[i][j]); j++; } i++;printf("\n"); } }

В программе (пример 4.0) определяется минимальный элемент кажой строки матрицы и выполняется обмен местами найденого и диагональю этой же строки.
Обращаем внимание на следующее обстоятельство. Если двумерный массив надо передать ыункции, то описание параметра в ней должно обязательно включать в себя размер строки массива, а размер столбцов несущественен. Так, массив из трех строк и пяти столбцов можно описать как int a[3][5]; либо int a[][5];

Пример 4.0

/*обмен мин с диагональю*/ #include <stdio.h> #define M 4 main() { static a[M][M]={ { 3,4,1,5), {-1,6,7,0}, { 1,8,7,-1}, { 4,9,7,-1}}; int i, j, jmin, amin; i=0; while(i<M) { amin=a[i][0]; jmin=0;j=1; while(j<m) { if(a[i][j]<amin) { amin=a[i][j]; jmin=j; } j++; } a[i][jmin]=a[i][i]; a[i][i]=amin; i++; } i=0 while(i<M) { j=0; while(j<M) printf("%3d",a[i][j++]); printf("\n"); i++; } }

Массивы символов

Любая символьная константа, например "ОЙ У ПОЛИ КРИНИЧКА", представляет собой массив символов. Во внутреннем представлении компилятор завершает такой массив символом "\0", так что любая программа может по нему легко обнаружить конец строки. Поэтому строка занимает в паямяти на один символ больше, чем записано между двойными кавычками. Нумерация элементов массива начинается с нуля. Надо помнить, что, например 'T' - это символ(буква), а ' T ' - это строка, состоящая из двух символов: 'T' и '\0'. Отсюда следует, что пустых строк не бывает.
Строка в языке Си - это разновидность константы и ее можно присваивать некоторой переменной, представляющей массив символов:

char str[]="ТЕКСТ";

Такая запись и короче и понятнее, чем общепринятая для начальной инициализации массивов:

char str[]={'Т','Е','К','С','Т',};

Если длина строки в квадратных скобках опущена, то она определяется автоматически, по количеству присваеваемых символов. В приведенном выше примере она равна шести.
Запишем программу (пример 4.1), в которой функция main формирует строку по указанному выше правилу и вызывает функцию length, которая в качестве аргумента получает начальный адрес этой строки и вычисляет ее длину(без учета завеершающего символа). Эта функция представляет собой самостоятельный интерес и будет использована нами а дальнейшем как библиотечная.

Пример 4.1

/*длина сторки*/ length(s); char s[]; { int l=0; while(s[l]!='\0') i++; return(i); } #include <stdio.h> main() { static char str[]="ОЙУ ПОЛИ КРИНИЧКА"; printf("%d",length(str)); }

Программа приведенная ниже (пример 4.2), выполняет сцепление двух строк. Собственно, сцепление выполняет функция concat(s,t), которая присоединят строку t к концу строки s. Объединяемые строки str1 и str2 объявлены как внешние, причем размер str1 достаточно большой, чтобы сохранить новую строку. Используя спецификацию формата %s, функция printf выводит всю строку сразу, причем она "знает", что печать остановить при достижении завершающего символа "\0".

Пример 4.2

/*сцепление строк*/ concat(s,t) char s[],t[]; { int i,j; i=j=0; /*поиск конца строки*/ while(s[i]!='\0')i++; while((s[i++]=t[j++])!='\0'); /*копия t*/ #include <stdio.h> char str1[45]="ОЙ ТАМ У ПОЛИ КРИНИЧКА"; char str2[]="ТАМ ХОРОША ВОДИЧКА"; main() { concat(str1,str2); printf("%s",str); }

На пример 4.3 приведена программа с функцией revers(s), переставляющей символы строки s в обратном порядке. В качестве библиотечной исползуется ранее рассматривавшаяся функция length. Функция revers меняет местами символы строки, симетричные относительно ее середины; если в строке нечетное число символов, то средний символ остается на месте.

Пример 4.3

/*вращение строки*/ #include stdio.h #include "length.c" revers(s) char s[]; { int l,i=0; l=length(s); while(i_=l/2) { c=s[i]; s[i]=s[l-i-1]; s[l-i-1]=c; i++; } } main() { static char str[]= "ОЙУ ПОЛИ КРИНИЧКА"; revers(str); printf("%s\n",str); }


Поделиться:


Последнее изменение этой страницы: 2017-01-27; просмотров: 142; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.12.165.68 (0.013 с.)