- •Институт математики, экономики и механики кафедра математического обеспечения компьютерных систем в. С. Макогон, и. Н. Лисицына
- •Оглавление
- •Введение
- •Основныетипы данных, операции и выражения
- •Описание переменных.
- •Операции , выражения и операторы.
- •3. Операторы управления программой. Базовые управляющие структуры.
- •Операторы ветвления Условный оператор if
- •Оператор - переключатель
- •Операторы повторения (цикла).
- •4. Программирование алгоритмов линейной структуры.
- •5. Программирование разветвляющихся алгоритмов (оператор if).
- •6. Программирование разветвляющихся алгоритмов (оператор switch)
- •Оператор for
- •Цикл с постусловием do -while
- •8. Итерационные циклы
- •Задачи для самостоятельного решения
- •9. Программирование алгоритмов с использованием функций
- •Основные понятия численного решения уравнений
- •10. Программирование алгоритмов с использованием массивов
- •11. Символьные переменные и строки. Обработка строк.
- •Другие средства ввода-вывода символов и строк
- •Массивы строк
- •12. Указатели
- •Массивы указателей
- •2. Описание метода трапеций
- •3. Программный комплекс
- •13. Структуры
- •Указатели на структуры
- •14. Файлы. Потоковый ввод-вывод
- •Функции для работы с файлами
- •Открытие файловых потоков
- •Закрытие файловых потоков
- •Удаление файлов
- •Переименование файлов
- •Реинициализация
- •Функции для ввода-вывода по символам
- •1 Вариант) содержит только буквы исходной строки
- •2 Вариант) перевернута по отношению к исходной
- •Двоичные (бинарные) файлы. Блочно-ориентированный ввод-вывод.
2. Описание метода трапеций
Этот метод основан на том, что площадь криволинейной фигуры, ограниченной кривой y=f(x) и прямымиx=xi,x=xi+1иy=0, то есть интеграл, заменяется площадью прямоугольной трапеции с основаниями,и высотой
то есть
Тогда квадратурную формулу трапеций приближенного вычисления определенного интеграла Iможно записать в виде
Для достижения требуемой точности при вычислении по квадратурной формуле используется метод последовательного удвоения числа шагов. Для вычисления значения интеграла с заданной степенью точности необходимо первоначально принять некоторое произвольное количество разбиений участка интегрирования, например, n = 10 и вести расчет интеграла сначала при этом количестве разбиений, а затем при удвоенном, т.е. n = 20, затем при n = 40 и т.д. до тех пор, пока погрешность не станет меньше или равной заданной точности.
3. Программный комплекс
// integral.cpp Приближенное вычисление определенного
// интеграла методом трапеций
// Для достижения требуемой точности при вычислении по
// квадратурной формуле используется метод последовательного
// удвоения числа шагов n участка интегрирования.
#include "stdafx.h"
#include <conio.h>
#include <stdio.h>
#include <iostream>
using namespace std;
// вычисление 1 подынтегральной функции
double Fsqrt(double x)
{
return sqrt(2*x+1); // a = 0, b = 1 Ответ: 1.398717
}
// вычисление 2 подынтегральной функции
double Fsin(double x)
{
return sin(x/4); //a = 0, b = 1 Ответ: 0.124344
}
// вычисление 3 подынтегральной функции
double Fsqr (double x)
{
return x*x; //a = 0, b = 1 Ответ: 0.3333
}
// вычисление 4 подынтегральной функции
double f (double x)
{
return log(x); //a = 1, b = 2 Ответ:
}
// Функция вычисления интеграла методом трапеций
// В заголовке функции TRAP используется формальный параметр-указатель
// на функцию (*uf). При вызове этой функции в качестве фактического
// параметра ей передается имя реальной функции: Fsqrt, Fsin, Fsqr
// через оператор switch (num_F)
double trap(double a, double b, int n,double (*uf)(double))
{
int i; double h,s;
h=(b-a)/n; s=((*uf)(a)+(*uf)(b))/2;
for( i=1; i<= n-1; i++)
s=s+(*uf)(a+i*h);
s=s*h;
return s;
}
// основная программа
int main()
{ system("cls"); system("chcp 1251");
double a, b; // интервал интегрирования
double eps; // точность вычисления интеграла
double s1,s2; // последовательные приближения к интегралу
int n ; // число интервалов интегрирования
int num_F; // номер функции: 1,2,3
eps=0.00001 ; n=10;
//*******************************************
m2: cout<<"ВВЕДИ номер вызываемой функции: 1,2,3";
cin>>num_F;
if (num_F < 1 || num_F > 3)
{cout<<"ERROR num_F "; goto m2;}
cout<<"ВВЕДИ A "; cin>>a;
cout<<"ВВЕДИ B "; cin>>b;
//**********ВЫЗОВ ФУНКЦИИ TRAP*************
switch (num_F)
{
case 1: s1=trap(a,b,n,Fsqrt ); //вызов функции-метода
printf("n = %5d интеграл =%10.6lf\n", n, s1);
do
{ n=n*2; s2=trap(a,b,n,Fsqrt ); //вызов функции-метода
printf("n = %5d интеграл =%10.6lf\n", n, s2);
if(fabs(s2-s1)<eps)
break;
s1=s2;
}
while(1);
break; // для функции F1
case 2: s1=trap(a,b,n,Fsin ); //вызов функции-метода
printf("n = %5d интеграл =%10.6lf\n", n, s1);
do
{ n=n*2; s2=trap(a,b,n,Fsin ); //вызов функции-метода
printf("n = %5d интеграл =%10.6lf\n", n, s2);
if(fabs(s2-s1)<eps)
break;
s1=s2;
}
while(1);
break; // для функции F2
case 3: s1=trap(a,b,n,Fsqr ); //вызов функции-метода
printf("n = %5d интеграл =%10.6lf\n", n, s1);
do
{ n=n*2; s2=trap(a,b,n,Fsqr ); //вызов функции-метода
printf("n = %5d интеграл =%10.6lf\n", n, s2);
if(fabs(s2-s1)<eps)
break;
s1=s2;
}
while(1);
break; // для функции F3
}
return 0;
}
Далее следуют примеры программ, использующих функции и указатели.
Задача 148. Создать функцию, подсчитывающую сумму чисел, предшествующих первому отрицательному элементу в массиве.
// Программа отлажена в Visual Studio 2008 (27.05.2008)
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
// Сумма чисел до первого отрицательного
// элемента в массиве
float my_func(float *a, int n)
{ int flag = 0;
float s=0; float *uk1=a+n-1;
while( a <= uk1)
{ if( *a >= 0)
s=s + *a;
else
{ flag = 1; break;}
a++;
}
if(flag == 0)
return -777;
else
return s;
}
const int n = 7;
int main()
{ //float a[n]={2,4,6,88,9,10,15};
float a[n]={2,1,1,-1,1,1,1};
float s=my_func(a , n);
if (s < 0)
cout << "NOT FOUND\n";
else
cout<<s<<endl;
return 0;
}
Задача 149.Создать функцию, подсчитывающую сумму чисел, расположенных после последнего отрицательного элемента в массиве.
// Программа отлажена в Visual Studio 2008
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
// Сумма чисел после последнего отрицательного
// элемента в массиве
float my_func(float *a, int n)
{ int flag = 0;
float s=0; float *uk1=a+n-1;
while( uk1 >= a)
{
if (*uk1 < 0)
{ flag = 1; break;}
uk1--;
}
if(flag == 0)
return -777;
else
{ uk1++;
while(uk1 < a + n)
{ s=s + *uk1; uk1++;}
return s;
}
}
const int n = 7;
int main()
{ //float a[n]={2,4,6,88,-9,10,15};
float a[n]={2,1,1,1,1,1,1};
float s=my_func(a , n);
if (s < 0)
cout << "NOT FOUND\n";
else
cout<<s<<endl;
return 0;
}
Задача 150.Создать функцию, осуществляющую бинарный поиск заданного элемента Q в заданном упорядоченном массиве целых чисел.
Функция dicho() рализует бинарный поиск, используя механизм указтелей и адресную арифметику для обработки массива. Ранее (см задачу 92) этот алгоритм был реализван в стиле традиционной обработки массивов с применением индексирования.
// Программа отлажена в Visual Studio 2008
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
//двоичный поиск 3.06.2008
int dicho(int *x, int n, int Q)
{
int low=0,high=n-1, mid, flag=0;
while(low <= high && !flag)
{
mid=(low+high)/2;
if(*(x+mid) == Q)
flag=1;
else
if(*(x+mid) < Q)
low=mid+1;
else
high=mid-1;
}
if(flag)
return mid;
else
return -777;
}
int main()
{
int i, Q,found;
int a[]={1,3,7,33,44,55,66,77,88};
int n=sizeof(a)/sizeof(int);
// Устанавливаем локализацию для выходного потока
wcout.imbue( locale( "rus_rus.866" ) );
// Выводим строку на русском !
wcout<< L"введи ключ поиска\n";
scanf("%d",&Q);
found = dicho(a, n, Q);
if(found>=0)
wcout<< Q<<L" на "<<found<<L" месте\n";
else
wcout<<Q<< L" не найден\n";
getch();
}
Вот результат работы этой программы:
введи ключ поиска
33
33 на 3 месте
Задача 151.Создать функцию, которая удаляет из заданной строки текст, заключенный в круглые скобки ( и ), формируя новую строку. Функция в случае успеха возвращает 0, и некоторое отрицательное число при неудаче (-1 при отсутствии “(“, -2 при отсутствии “)” ).
// Программа отлажена в Visual Studio 2005
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
// функция удаляет символы между ( и )
int del_skob(char *s1, char *s2)
{
while(*s1 != '\0' && *s1 != '(')
*s2++ = *s1++;
if(*s1=='\0')
return -1;
while(*s1 != '\0' && *s1 != ')')
s1++;
if(*s1=='\0')
return -2;
s1++;
while(*s1 != '\0' )
*s2++ = *s1++;
*s2=0;
return 0;
}
int main()
{
char s1[40]="12345(мама мыла раму)6789", s2[40];
int flag;
// Устанавливаем локализацию для выходного потока
wcout.imbue( locale( "rus_rus.866" ) );
// Выводим строку на русском !
wcout<< L"Введи строку "; gets(s1);
flag=del_skob(s1, s2);
if (flag==-1)
{wcout << L"Нет ("; getch();return 0;}
if (flag==-2)
{wcout << L"Нет )"; getch(); return 0;}
else
puts(s2);
getch();return 0;
}
Задача 152. Создать строку, содержащую цифры и другие символы. Определить функцию типа указатель, которая в динамической области памяти (“куче”) формирует новую строку на базе исходной, удалив предварительно из неё цифры и записав оставшиеся символы в обратном порядке. Функция должна возвращать указатель на вновь сформированную строку.
// Программа отлажена в Visual Studio 2008 (24.05.2008)
#include <iostream>
using namespace std;
char *delzifr(char *s);
int main ()
{
char *str="988776ASDFGH1233^%&^888";
// Устанавливаем локализацию для выходного потока
wcout.imbue( locale( "rus_rus.866" ) );
// Выводим строку на русском !
wcout<< L"Строка-результат: ";
cout<<delzifr(str)<<endl;
wcout<< L"Исходная строка: "<<str<<endl;
getch();return 0;
}
char *delzifr(char *s)
{
char *my_s= new char [strlen(s)];
// char *my_s=(char*)malloc(strlen(s));
char *uk1=s, *uk2=my_s;
while(*s)
s++; //End string
while(--s>=uk1)
{
if(*s<'0'|| *s>'9')
{
*my_s = *s;
my_s++;
}
}
*my_s ='\0';
return(uk2);
}
Задача 153. Определить строку в динамической области памяти. Подсчитать, сколько раз в заданную строку входит каждый её символ.
В приведенной ниже программе для подсчета числа вхождений каждого символа предусмотрена функция count(). Функция delchr() удаляет символ после подсчета количества его вхождений в строку.
// count2.cpp Программа отлажена в Visual Studio 2008
#include "stdafx.h"
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
void delchr(char *, char); // прототип функции
// Подсчет числа вхождений каждого символа
void count(char *s)
{
char *uk, ch; int k;
while((ch = *s)!='\0')
{
//указатель S не сдвигается!
k=1; uk=s+1;
while(*uk != '\0')
{
if(ch==*uk)
k++;
uk++;
}
//printf("%c - %d \n",ch,k);
wcout <<L"символ "<<ch<<L" встречается "<<k<<L" раз\n";
delchr(s,ch);
}
}
// удаление символа в строке
void delchr(char *s,char c)
{
char *uk=s;
while(*s!='\0')
{
if (*s!=c)
{
*uk=*s;
uk++;
}
s++;
}
*uk='\0';
}
int main()
{
char *s; int size;
wcout.imbue( locale( "rus_rus.866" ) );
wcout<< L"Укажи длину строки :";
cin>>size; fflush(stdin);
s=(char*)malloc(size);
wcout<< L"Введи строку "; gets(s);
count(s);
getch();return 0;
}
Задача 154. Создать функцию, которая находит в заданной строке последнее вхождение символа # и пересылает в другую строку символы, начиная с найденного символа и до конца строки. Если искомый символ не найден, функция возвращает -1, иначе – номер позиции найденного символа в исходной строке.
/ Программа отлажена в Visual Studio 2008
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
int move_str (char *s1, char *s2)
{
char *uks = s1;
while (*uks)
uks++;
uks--;
while (uks >=s1 && *uks != '#')
uks--;
char *k = uks;
if (uks < s1)
return -1;
else
while (*uks != '\0')
*s2++ = *uks++;
*s2 = 0;
return (k - s1); //позиция символа #
}
int main()
{ char s1[]="12345# 6789# END", s2[25];
int k = move_str(s1,s2);
if (k < 0)
puts("# NOT FOUND");
else
{puts(s2); cout << endl<<k;}
return 0;
}
Задача 155. Определить строку в динамической области памяти. Создать функцию delsub( str, k, L ) для удаления из заданной строки str подстроки длиной L символов, начиная из символа с номером k.
// Программа отлажена в Visual Studio 2008
#include <stdlib.h>
#include <malloc.h>
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
// функция удаления подстроки
void delsub(char *s, int k, int l)
{
char *uk;
if(k>strlen(s)) return;
if(k+l>=strlen(s))
{ *(s+k)='\0';
return;
}
s=s+k; uk=s+l;
while(*s++ = *uk++) // копирование
;
//или так: for(s=s+k,uk=s+l; (*s=*uk); s++,uk++) ;
}
int main()
{
int k,l;
int size;
// Устанавливаем локализацию для выходного потока
wcout.imbue( locale( "rus_rus.866" ) );
// Выводим строку на русском !
wcout<<L"Укажи длину строки :";
cin>>size; fflush(stdin);
//char *s =(char*)malloc(size);
char *s = new char [size];
wcout<<L"Введи строку "; gets(s);
wcout<<L"Введи k и l ";
cin>>k>>l;
delsub(s,k,l);
puts(s);
getch();return 0;
}
Задача 156. Проверить, можно ли из букв, входящих в заданное слово (А), составить другое заданное слово (В). Каждая буква исходного слова может быть использована в формируемом слове только один раз.
Приведенная ниже программа использует две функции: slova() и del(). Первая из них осуществяет собственно проверку, входит ли каждая буква слова А в слово В. Вторая функция удаляет протестированную букву из слова А. Обратите внимание на тонкий момент: функция slova() работает с переменной flag, которая учитывает удаление последнего символа слова А, на который функция del() пересылает нуль-символ ('\0').
// Программа отлажена вVisual Studio 2008
#define L 80
#include <stdio.h>
#include <conio.h>
#include <iostream>
using namespace std;
void del(char *s,char c)
{
char *uk=s;
while (*s)
{
if(*s != c)
*uk++=*s;
s++;
}
*uk='\0';
}
int slova(char *A,char *B)
{ char *uk=A;int flag;
while (*B)
{ A=uk;
putchar(*B);putchar('\n');
flag=0;
while (*A)
{
if(*A==*B)
{ del(A,*A); //*A='*';
flag=1;
puts(uk);
break;
}
A++;
}
if(*A=='\0' && flag==0)
return 0;
B++;
}
return 1;
}
int main()
{
char A[L]="интеграл", B[L]="гантели";
// Устанавливаем локализацию для выходного потока
wcout.imbue( locale( "rus_rus.866" ) );
// Выводим строку на русском !
wcout<< L"Введи слово А "; cin >> A;
wcout<< L"Введи слово B "; cin >> B;
if(slova(A,B))
wcout<< L"можно";
else
wcout<< L"нельзя";
getch();return 0;
}
Задача 157. В заданной строке символов содержатся буквы, цифры и, быть может, некоторые другие символы. Создать функцию, которая выделяет из заданной строки только цифры и образует из них натуральное число типа unsigned long, которое и является возвращаемым функцией значением. Считать, что в строке содержится не более 9 цифр. Для обработки текста использовать указатели.
// Программа отлажена в Visual Studio 2008
#include<stdio.h>
#include<conio.h>
#include <iostream>
using namespace std;
unsigned long str_to_numb(char *s)
{
unsigned long m=0; int kzifr=0;
while(*s)
{ if(*s>='0' && *s<='9')
{ m=m*10+(*s-'0');
kzifr++;
}
if(kzifr >= 10)
{
printf("VERY MANY FIGURES - ");
return kzifr;
}
s++;
}
return m;
}
int main()
{
unsigned long m=0;char s[32]="75ee109wfg639()E";
m=str_to_numb(s);
printf("%ld\n",m);
getch(); return 0;
}
Задача 158.Создать функцию, которая заданную строку S1[L], каждый символ которой - двоичная цифра ('0', '1'), преобразует в эквивалентное десятичное число типа unsigned long int, которое и является возвращаемым функцией значением. Длина строки не превышает 32.
// str_num.cpp Программа отлажена в Visual Studio 2008
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
unsigned long str_to_number(char *str)
{
unsigned int maska=1;
unsigned long m=0;
char *uk=str;
while(*uk) uk++;
while(--uk>=str)
{
m=m + (*uk-'0')*maska;
maska<<=1;
}
return m;
}
int main()
{
char str[33]="01111111111111111111111111111111";
unsigned long m = str_to_number(str);
printf("%ld",m);
getch(); return 0;
}
Задача 159. Составить программу, которая определяет массив строк poem[4][60] следующего содержания:
Едва увидел я сей свет,
Уже зубами смерть скрежещет,
Как молнией, косою блещет
И дни мои, как злак, сечет.
(Державин)
Определить две функции, которые позволяют:
а) найти и выдать на экран слова, в которые заданная буква "е" входит два и более раз;
б) перевернуть все слова, которые начинаются заданной буквой "с".
Использовать указатели при обработке текста.
// Программа отлажена в Visual Studio 2008
#include "stdafx.h"
#include<conio.h>
#include<stdio.h>
#include <iostream>
using namespace std;
// Буква "e" или "E" входит 2 и более раз?
void two_raz( char *s, char ch1, char ch2 )
{
int m; char *uk1,*uk2;
uk1 = s;
while(*uk1!='\0')
{
while(*uk1 == ' ')
uk1++;
uk2 = uk1; m = 0;
while (*uk1 != ' ' && *uk1 != '\0')
{
if(*uk1==ch1 || *uk1==ch2)
m++;
uk1++;
}
if(m>=2)
while(uk2<uk1)
{
putchar(*uk2);
uk2++;
}
putchar(' ');
}
}
//перевернуть слово на заданную букву
void revers(char *s, char ch)
{
char *uk1,*uk2, r;
while(*s)
{
// пропуск пробелов перед словом
while(*s==' ')
s++;
uk1=s; // указатель на начало слова
// пропуск слова
while(*s != ' ' && *s != '\0')
s++;
uk2=s-1; // указатель на конец слова
if(*uk1 == ch)
while(uk2 > uk1)
{
r=*uk2;
*uk2=*uk1;
*uk1=r;
uk1++;uk2--;
}
}
}
#define L 80
int main()
{
char poem[4][L]={
" Едва увидел я сей свет,",
" Уже зубами смерть скрежещет",
" Как моленией, косою блещет",
" И дни мои, как злак, сечет."
};
// а)
char bukwa_e = 'е', bukwa_E = 'Е';
for(int k=0; k<4; k++)
{
two_raz(poem[k], bukwa_e, bukwa_E );
putchar('\n');
}
// б)
char bukwa_c = 'с';
for(int k=0; k<4; k++)
{
revers(poem[k], bukwa_c );
puts(poem[k]);
}
getch();return 0;
}