Полезное:
Как сделать разговор полезным и приятным
Как сделать объемную звезду своими руками
Как сделать то, что делать не хочется?
Как сделать погремушку
Как сделать так чтобы женщины сами знакомились с вами
Как сделать идею коммерческой
Как сделать хорошую растяжку ног?
Как сделать наш разум здоровым?
Как сделать, чтобы люди обманывали меньше
Вопрос 4. Как сделать так, чтобы вас уважали и ценили?
Как сделать лучше себе и другим людям
Как сделать свидание интересным?
Категории:
АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника
|
Арифметические циклы
Для арифметического цикла заранее известно сколько раз выполняется тело цикла. Задача №2 Дана последовательность целых чисел из n элементов. Найти среднее арифметическое этой последовательности. #include <stdio.h> #include <math.h> void main() { int t, n, i, kol=0,sum=0; printf("\nEnter n:"); scanf(“%d”,&n); for(i=0;i<n;i++) { рrintf(“\nEnter a:"); scanf(“%i”,&t); sum+=t; ++kol; } printf(“\nSr. arifm=%.2lf\n", (double)sum/kol); }
Тесты к приведенному примеру описаны в таблице 5.2. Таблица 5.2 – Тесты к приведенной в примере программе
Замечание: т.к. среднее арифметическое не обязательно будет целым, то нужно либо sum описать как double, либо при выводе результата деления sum/kol числитель или знаменатель привести к типу double (вспомним, что тип результата выполнения арифметической операции совпадает с наивысшим из типов операндов, а т. к. они оба целые, то и результат будет целым, и мы потеряем точность). Второй способ предпочтительнее: в нем преобразование целого к плавающему выполняется лишь один раз, в то время как в первом варианте оно выполнялось бы в цикле при каждом сложении sum+=tmp.
Задача №3. Найти сумму первых N натуральных чисел. N ввести с клавиатуры. S=1+2+3+4+... +N #include <stdio.h> #include <math.h> void main() { int n,i,sum=0; printf("\nEnter n:"); scanf(“%d”,&n); if(n<=0) { printf(“\nN<=0\n”); return; } for(i=1;i<=n;i++) sum+=i; printf("\nSumma=%d\n",sum); } Тесты к программе приведставлены в таблице 5.3. Таблица 5.3 – Тесты к приведенной в примере программе
Замечание: здесь можно было использовать формулу суммы членов арифметической прогрессии sum=(1+n)*n/2 (и это было бы правильнее!). Задача №4. Найти сумму S =15-17+19-21+..., всего n слагаемых. #include <stdio.h> #include <math.h> void main() { int n,i,sum=0,tmp=15; cout<<"\nEnter n:"; cin>>n; if(n<=0) { cout<<”\nN<=0”;return;} for(i=1; i<=n; i++){ if(i%2==1) sum+=tmp; else sum-=tmp; tmp+=2; } cout<<"\nS="<<s<<"\n"; } Тесты к этой программе представлены в таблице 5.4. Таблица 5.4 – Тестовые примеры к программе
Замечание: в этом примере использованы объекты cin и cout для ввода и вывода данных.
Итерационные циклы Для итерационного цикла известно условие выполнения цикла. Задача №5 Дана последовательность целых чисел, за которой следует 0. Найти минимальный элемент этой последовательности. #include <stdio.h> int main(){ int tmp,min; printf(“\nEnter number:"); scanf(“%d”,&tmp); min=tmp; while(tmp!=0){ printf("\nEnter number:"); scanf(“%d”,&tmp); if (tmp!=0 && tmp<min) min=tmp; } printf(“\nmin=%d\n”,min); return 0; }
или (вариант 2) #include <stdio.h> #include<limits.h> int main(){ int tmp,min; min=INTMAX; while(1){ printf("\nEnter number:"); scanf(“%d”,&tmp); if (tmp==0) break; if (tmp<min) min=tmp; } printf(“\nmin=%d\n”,min); return 0; }
или (вариант 3) #include <stdio.h> #include<limits.h> int main(){ int tmp,min; min=INTMAX; for(;;){ printf("\nEnter number:"); scanf(“%d”,&tmp); if (tmp==0) break; if (tmp<min) min=tmp; } printf(“\nmin=%d\n”,min); return 0; }
или (вариант 4) #include <stdio.h> #include<limits.h> int main(){ int tmp,min; min=INTMAX; do{ printf("\nEnter number:"); scanf(“%d”,&tmp); if (tmp && tmp<min) min=tmp; }while(tmp); printf(“\nmin=%d\n”,min); return 0; }
Тесты: min в средине входных данных
min слева
min справа
Задача №6: Найти сумму чисел Фибоначчи, меньших заданного числа q. #include<stdio.h> int main() { int f1=1,f2=1, f3=f1+f2, sum=2,q; printf(“\nEnter q:”); scanf(“%d”,&q); if(q<=0) printf("\nError in q\n"); else if(q==1) printf("\nSum=1\n"); else { while(f3<q) { sum+=f3; f3=f1+f2; f1=f2; f2=f3; } printf("\nSum=%d\n",sum)"; } return 0; } Тесты к приведенному примеру описаны в таблице 5.5. Таблица 5.5 – Работа программы на тестовых примерах
Вложенные циклы Задача №7: Вывести N простых чисел. #include<stdio.h> int main() { int a=1,n,d; printf(“\nEnter N:"); scanf(“%d”,&n); for(int i=0;i<n;){ //внешний цикл a++; d=1; do { //внутренний цикл d++; } while(a % d!=0); //конец внутреннего цикла if(a==d){ // а – очередное простое число printf(“%d “,a); i++; } } // конец внешнего цикла return 0; }
или (вариант 2) #include<stdio.h> int main() { int a=1,n,d; printf(“\nEnter N:"); scanf(“%d”,&n); for(int i=0;i<n; ++i){ // внешний цикл do{ // внутренний цикл a++; int d=2; for (; d*d<=a; ++d) if(a%d==0) break; if(d*d>a) { printf(“%d “,a); break; // выход из цикла do-while, нашли очередное простое }while(1); // конец внутреннего цикла do-while } // конец внешнего цикла return 0; } Указатели 6.1. Понятие указателя Указатели являются специальными объектами в программах на Си++. Указатели предназначены для хранения адресов памяти. Пример: когда компилятор обрабатывает оператор определения переменной, например, int i=10;, то в памяти выделяется участок памяти в соответствии с типом переменной (int => 4байта) и записывает в этот участок указанное значение. Все обращения к этой переменной компилятор заменит на адрес области памяти, в которой хранится эта переменная. а
Программист может определить собственные переменные для хранения адресов областей памяти. Такие переменные называются указателями. Указатель не является самостоятельным типом, он всегда связан с каким-то другим типом. Указатели делятся на две категории: указатели на объекты и указатели на функции. Рассмотрим указатели на объекты, которые хранят адрес области памяти, содержащей данные определенного типа. В простейшем случае объявление указателя имеет вид: тип *имя; Тип может быть любым, кроме ссылки. Примеры: int *i; //указатель i на целое double *f, *ff; //два указателя f и ff на double char *c; //указатель c на символ Размер указателя зависит от модели памяти. Можно определить указатель на указатель: int**a; // указатель a на указатель на целое Указатель может быть константой или переменной, а также указывать на константу или переменную. Примеры: int i; //целая переменная const int ci=1; //целая константа int *pi; //указатель на целую переменную const int *pci; //указатель на целую константу Указатель можно сразу проинициализировать: int *pi=&i; //указатель на целую переменную const int *pci=&ci; //указатель на целую константу int*const cpi=&i; //указатель-константа на целую переменную const int* const cpc=&ci; //указатель-константа на целую константу Если модификатор const относится к указателю (т. е. находится между именем указателя и *), то он запрещает изменение указателя, а если он находится слева от типа (т. е. слева от *), то он запрещает изменение значения, на которое указывает указатель. Для инициализации указателя существуют следующие способы: 1) с помощью операции получения адреса int a=5; int *p=&a; // или int p(&a); 2) с помощью проинициализированного указателя int *r=p; 3) адрес присваивается в явном виде char*cp=(char*)0х В800 0000; где 0х В800 0000 – шестнадцатеричная константа, (char*) – операция приведения типа. 4) присваивание пустого значения: int*N=NULL; int *R=0; 6.2. Операции с указателями С указателями можно выполнять следующие операции: 1) разыменование (*); 2) присваивание; 3) арифметические операции (сложение с константой, вычитание, инкремент ++, декремент --); 4) сравнение; 5) приведение типов.
Операция разыменования предназначена для получения значения переменной или константы, адрес которой хранится в указателе. Если указатель указывает на переменную, то это значение можно изменять, также используя операцию разыменования. Примеры: int a; //переменная типа int int*pa=&a; //указатель pa инициализирован адресом a *pa=10; //присвоили значение 10 переменной с адресом pa, и a стала тоже =10 Присваивать значение указателям-константам запрещено, как и заносить значения по указателям на константы. Присваивание и приведение типов. Допускается присваивание указателей на один и тот же тип, в противном случае используют операцию явного приведения к типу, например, double a=1234.5; char*ptr=(char*)&a; for (int i=0;i<8;++i) printf(“%x”,ptr[i]); автоматически осуществляются преобразования любого указателя к void* и указателя на void* в любой. На одну и ту же область памяти могут ссылаться указатели разного типа. Если применить к ним операцию разыменования, то получатся разные результаты. int a=123; int*pi=&a; char*pc=(char*)&a; float *pf=(float*)&a; printf("\n%x\t%i",pi,*pi); printf("\n%x\t%c",pc,*pc); printf("\n%x\t%f",pf,*pf); При выполнении этой программы получатся следующие результаты: 66fd9c 123 66fd9c { 66fd9c 0.000000 Т. е. адрес у трех указателей один и тот же, но при разыменовании получаются разные значения в зависимости от типа указателя. В примере при инициализации указателя была использована операция приведения типов. При использовании в выражении указателей разных типов, явное преобразование требуется для всех типов, кроме void*. Указатель может неявно преобразовываться в значения типа bool, при этом ненулевой указатель преобразуется в true, а нулевой в false. 3) Арифметические операции применимы только к указателям одного типа. - Инкремент увеличивает значение указателя на величину sizeof(тип). Например: char *pc; int *pi; float *pf; ..... pc++; // значение увеличится на 1 pi++; // значение увеличится на 4 pf++; // значение увеличится на 4 - Декремент уменьшает значение указателя на величину sizeof(тип). - Разность двух указателей – это разность их значений, деленная на размер типа в байтах (т.е. это количество ячеек данного типа, расположенных между указателями). Например: int a=123,b=456,c=789; int*pi1=&a; int *pi2=&b; int*pi3=&c; printf("\n%x",pi1-pi2); printf("\n%x",pi1-pi3); Результат
Суммирование двух указателей не допускается. Можно суммировать указатель и константу, операция масштабируется размером типа, на который указывает указатель: pi3=pi3+2; pi2=pi2+1; printf("\n%x\t%d",pi1,*pi1); printf("\n%x\t%d",pi2,*pi2); printf("\n%x\t%d",pi3,*pi3); Результат выполнения программы: 66fd9c 123 66fd9c 123 66fd9c 123 При записи выражений с указателями требуется обращать внимание на приоритеты операций.
Ссылки 7.1. Понятие ссылки Ссылка – это синоним имени объекта, указанного при инициализации ссылки. Это и указатель, и значение одновременно. Это такой объект, который инициализируется адресом, а использоваться будет значение по адресу. Ссылки в основном служат для обеспечения удобства кода функций, в которые параметры передаются по адресам. Формат объявления ссылки тип & имя =имя_объекта; Примеры: int x=2; // определение переменной int& sx=x; // определение ссылки на переменную х sx=6; //теперь и x равно 6 const char& CR=’\n’; //определение ссылки на константу
7.2. Правила работы со ссылками 1) Переменная ссылка должна явно инициализироваться при ее описании, если она не является параметром функции, не описана как extern или не ссылается на поле класса. 2) После инициализации ссылке не может быть присвоено другое значение. 3) Не существует указателей на ссылки, массивов ссылок и ссылок на ссылки. 4) Операция над ссылкой приводит к изменению величины на которую она ссылается Ссылка не занимает дополнительного пространства в памяти, она является просто другим именем объекта. Пример: #include <stdio.h> int main() { int i=123; int &si=i; printf(“\ni=%i, si=%i\n”,i, si); i=456; printf(“\ni=%i, si=%i\n”,i, si); si=789; printf(“\ni=%i, si=%i\n”,i, si); return 0; } Выведется i=123 si=123 i=456 si=456 i=789 si=789
Массивы В языке Си/Си++ из базовых типов можно строить производные типы. Стандарт языка определяет три способа получения производных типов: - массив элементов заданного типа; - указатель на объект заданного типа; - функция, возвращающая значение заданного типа и имеющая аргументы заданных типов. Массив – это упорядоченная последовательность переменных одного типа. Каждому элементу массива отводится одна ячейка памяти. Размер ячейки (в байтах) зависит от типа элементов. Элементы одного массива занимают последовательно расположенные ячейки памяти. Все элементы имеют одно имя – имя массива. Элементы различают по индексам – порядковым номерам в массиве. Количество элементов в массиве называется его размером. Чтобы отвести в памяти нужное количество ячеек для размещения массива, надо заранее знать его размер. Резервирование памяти для массива выполняется на этапе компиляции программы.
8.1. Определение массива в С/С++ Синтаксис описания массива имеет вид тип имя[количество элементов]. Например, int a[100];// массив из 100 элементов целого типа. Операция sizeof(a) даст результат 400, т. е.100 элементов по 4 байта. Элементы массива всегда нумеруются с 0. Т.о. в вышеописанном массиве а состоит из 100 элементов, это a[0],a[1],a[2],..,a[99]. Чтобы обратиться к элементу массива, надо указать имя массива и номер элемента в массиве (индекс): a[0] – индекс задается как константа, a[55] – индекс задается как константа, a[i] – индекс задается как переменная, a[2*i] – индекс задается как выражение. Имя массива является адресом (указателем) его первого элемента, т.о. &a[0]=a, *(a+2)=a[2]. В общем случае a+i=&a[i], *(a+i)=a[i]. Элементы массива можно задавать при его определении: int a[10]={1,2,3,4,5,6,7,8,9,10}; Операция sizeof(a) даст результат 40, т. е.10 элементов по 4 байта. Можно инициализировать не все элементы массива: int a[10]={1,2,3,4,5}; Операция sizeof(a) даст и здесь результат 40, т. е.10 элементов по 4 байта. Если количество инициализирующих значений меньше, чем объявленная длина массива, то значения получат только первые элементы массива. Можно инициализировать массив и так: int a[]={1,2,3,4,5}; Здесь размер массива подсчитает компилятор по количеству значений, перечисленных при инициализации. Операция sizeof(a) теперь даст результат 20, т. е.5 элементов по 4 байта.
8.2. Обработка одномерных массивов При работе с массивами очень часто требуется одинаково обработать все элементы или часть элементов массива. Для этого организуется перебор элементов массива. Перебор элементов массива характеризуется: - направлением перебора; - количеством одновременно обрабатываемых элементов; - характером изменения индексов. По направлению перебора массивы обрабатывают: - слева направо (от начала массива к его концу); - справа налево (от конца массива к началу); - от обоих концов к середине. Индексы могут меняться: - линейно (с постоянным шагом); - нелинейно (с переменным шагом).
Date: 2016-11-17; view: 407; Нарушение авторских прав |