2.3. Контрольные вопросы и задания.
Какие операторы вводят информацию в память компьютера?
Каким образом можно ввести информацию при помощи форматирования?
Какие существуют виды условного оператора и чем они отличаются?
Чем условный оператор принципиально отличается от условной операции?
Назовите три вида оператора цикла. Чем они принципиально отличаются между собой?
Какое значение возвращает функция floor (x)?
Для чего нужен сложный оператор {…} в условном операторе?
Для чего используют блок {…} в командах цикла? Может ли тело цикла for не выполняться ни разу? При каком условии?
лекция 3
программирование задач с использованием массивов. указатели.
При работе с массивами необходимо обратить внимание на их сохранение, ввод и вывод элементов. При программировании обязательно нужно использовать указатели. Указатель – особый тип данных, предназначенный для сохранения адреса в памяти. Если к указателю массива mas, например, прибавить значение 3, это приведет к получению нового указателя на четвертый (!) по порядку элемент массива. При этом переход выполняется в соответствии к типу массива.
Тесную связь с указателями имеет определенный в языке С++ тип данных – массив, ала вектор. Массив – это структурированный тип данных, который представляет собой пронумерованные элементы одинакового типа. Обозначением массива при описании является наличие парных скобок - [ ]. Элементы массива нумеруются, начиная с 0.
Например:
int mas1[21]; char mas2[67];
где объявлены вектор mas1, который содержит 21 элемент типа int и вектор mas2, которй содержит 67 элементов типа char.
В С++ есть два способа доступа к элементам вектора (массива): с использование механизма указателя и классический – с помощью индекса.
Использование механизма указателя основано на использовании факту, что имя вектора (массива) является указателем – константой, которая равна адресу начала вектора (массива) – первого байта первого элемента вектора (массива) (mas1==&mas1[0]). В результате этого используя операцию разименования «*» можно обеспечить доступ к любому элементу вектора (массива). Так эквивалентными будут обращения к i-му элементу вектора (массива) с использованием индекса - mas1[i] и выражения *(mas1+i), так как (mas1+i)==& mas1[i].
Многомерные массивы в С++ представляются в виде векторов указателей на векторы – многомерные вектора.
Багатовимірні масиви в С++ представляються у виді векторів покажчиків на вектори - багатовимірні вектора.
Использование механизма указателей для доступа к некоторому і,j,k-му элементу трехмерного вектора (массива) может быть таким:
b[і][j][k]= = *(b[і][j]+k)= =*(*(b[і]+j)+k)= =*(*(*(b+і)+j)+k) .
В этих обращения используется тот факт, что имя многомерного вектора (массива) является указателем-константой на вектор (массив) указателя – констант вектора (массива) строки, первый элемент которого является также указателем – константа строки. Элементы многомерных векторов (массивов) последовательно (в виде цепочки) сохраняются в памяти в порядке возрастания самого правого индекса – «по строкам», т.е. последний индекс изменяется быстрее.
В современном программировании часто используют динамические массивы, которые хранятся в динамической памяти, которая используется по мере необходимости. Например, одномерный динамический массив создается и удаляется операторами
int n=10;
float *md;
md=new float[n]; // создание
…// обработка
delete [] md; // удаление
Массивы указателей применяют при использовании функция, а также в ситуациях, когда необходимо выполнить какие-либо действия, не изменяя входных данных. Элементами таких массивов являются адреса данных.
Фрагмент программы сортирования массива через массив указателей на его элементы имеет вид
int ma[n], *mp[n]; // описание массива данных и массива указателей
for(i=0; i<n; i++)
mp[i]=&ma[i]; //присвоение адресов
for(i=0; i<n-1; i++) // сортировка указателей
for(j=0; j<n-i-1; j++)
if(*mp[j]>*mp[j+1])
{int *p= mp[j]; mp[j]= mp[j+1]; mp[j+1]=p;}
Пример 3.1.
Отсортировать массив mas действительных чисел размером 10 элементов по убыванию.
#include <iostream.h>
#include <сonio.h>
void main()
{ const n=10;
int i, j;
float mas [n], rab;
cout<<"Vvеdі 10 elem \n";
for ( i=0; i<n; i++)
cin>>mas[i]; // вариант cin>>*(mas+i);
cout<< " Isxodnik\n";
for( i=0; i<n; i++)
cout<<mas[i]; // cout<<*(mas+i)<<" ";
cout<<"\n"; // cout<<endl;
// Сортировка по убыванию
for (i=1; i<n; i++)
for (j=0;j<n-i-1;j++)
if(mas[j]<mas[j+1]) // if(*(mas+j) <*(mas+j+1))
{ rab= mas[j]; // { rab=*(mas+j);
mas[j] =mas[j+1]; // *(mas+j)=*(mas+j+1);
mas[j+1]=rab;} // *(mas+j+1)=rab; }
// Вывод результата
cout<< " Otsort massiv\n"<<"\n";
for (i=0; i<n; i++)
cout<< mas[i]<<” ”; // cout<<*(mas+i)<<" ";
getch(); //задержка экрана
}
Пример 3.2.
В многомерном массиве matr размером 5*6 найти сумму элементов каждой строки. Полученный массив отсортировать по возрастанию.
#include <iostream.h>
#include <conio.h>
void main()
{int i,j,sum,stk;
int matr[5][6], mas[5];
cout<<"Input matr\n";
// Ввод массива
for(i=0; i<5; i++)
for(j=0; j<6; j++) cin>> *(*(matr+i)+j);
// Найти сумму элементов каждой строки
for(i=0; i<5; i++)
{sum=0;
for(j=0; j<6; j++)
sum+=*(*(matr+i)+j); *(mas+i)=sum;}
cout<< "Result mas\n";
for(i=0; i<5; i++)
cout<< *(mas+i)<<" "; cout<<endl;
// Сортировка вестора (массива) mas по возрастанию
for( i=1; i < 5; i++)
for( j=0; j < 4-i; j ++)
if (*(mas+j)> *(mas+j+1))
{stk=*(mas+j); *(mas+j)= *(mas+j+1); *(mas+j+1)=stk;}
// Вывод отсортированного массива
cout<< "Result otsortirov mas\n";
for( i=0; i<5; i++)
cout<< *(mas+i)<<" "; cout<<endl;
getch(); }
Пример 3.3.
Создать динамический масив из n строк и m столбцов (значения n и m ввести с клавиатуры). Найти сумму парных элементов массива.
#include <iostream.h>
void main()
{ int n,m,i;
int **mas;
cout<<"Vveditе kolsch strok (n) i stolbcov (m)"<<endl;
cin>>n>>m;
//создаем динамический массив
mas=new int*[n]; //создаем массив указателей
for(i=0;i<n;i++)
mas[i]=new int[m];
cout<<"Vvedit elementi masiva"<<endl;
for(i=0;i<n;i++)
for(int j=0;j<m;j++) cin>>mas[i][j];
for(i=0;i<n;i++,cout<<endl)
for(int j=0;j<m;j++)
cout<<mas[i][j]<<"\t";
int sum(0);
for(i=0;i<n;i++)
for(int j=0;j<m;j++)
if(mas[i][j]%2==0) sum+=mas[i][j];
cout<<" sum== "<<sum<<endl;
// освобождаем память
for(i=0;i<n;i++)
delete[]mas[i];//освобождаем строки
delete []mas; //освобождаем массив указателей
cin>>i;
}
3.3. Контрольные вопросы и задания.
1. Как понимать выражение *( c+i ), где с – имя указателя?
2. Какие преимущества имеет использование указателей в программах?
3. Как в языке С++ представляют многомерные массивы?
4. Объясните выражение *(*(matr+i)+j).
5. Что такое разименование в языке С++?
6. Какие действия можно выполнять с указателями?
7. Напишите программу сортирования массива по правилу возрастания с использованием указателей.
8. Как задать изменяющийся размер массиву?
9. Что такое динамические массивы?
10. Объясните использование массивов указателей.
ЛЕКЦИЯ 4
СТРОКИ. ОБРАБОТКА ДАННЫХ СИМВОЛЬНОГО ТИПА
4.1. Работа с данными символьного типа.
В языке С++ существует несколько возможностей работы с символьными данными. Классическая работа сводится к использованию массивов символов. При этом существует возможность обработки каждого символа и разработки эффективных алгоритмов.
Другое направление обработки сводится к манипулированию строками – массивом символов, который заканчивается специальным символом конца строки. При этом за счет использования библиотечных функций значительно упрощается программирование и соответственно расширяется класс задач.
Для того, чтобы воспользоваться стандартними функциями С++ для работы со строками, нужно в программу включить директиву #include <string.h>. Основные функции этой библиотеки приведены ниже. В заголовках функции приведены типы параметров и порядок вызова.
char *strcat (char*_dest, const char*_src); — функция реализует соединение строки dest со строкой src. Функция возвращает указатель на начало полученной строки (dest). Промежуточный символ ‘\0’ строки dest гасится.
— char *strncat (char*_dest, const char*_src, size_t_maxlen); — функция присоединяет maxlen символов из строки, на которую указывает src, до строки, на которую указывает dest. Строка dest должна содержать не меньше maxlen свободных байтов. Если maxlen больше строки src, выполняется простая конкатенация.
— char*strchr (const char*_, int_c); — функция возвращает указатель на позицию первого вхождения символа “c” в строку, на которую указывает s. В строку включается и символ ‘\0’.
— int strcmp (const char*_s1, const char*_s2); — функция выполняет сравнение двух строк, на начало которых указывают s1 и s2. Функция принимает значение меньше нуля, если s1<s2; равное нулю, если s1==s2; больше нуля, если s1>s2.
— int strnсmp (const char*_s1, const char*_s2, size_t_maxlen); — функция аналогична функции strcmp () и отличается тем, что выполняется сравнение первых maxlen байтов.
int stricmp (const char *_s1, const char *_s2); — функция выполняет сравнение двух строк, на что указывают s1 и s2. Перед сравнением символы превращаются в маленькие. Функция принимает значение больше нуля, если s1>s2; равное нулю, если s1==s2; меньше нуля, если s1<s2.
— int strlen (const char*_s); — функция возвращает длину строки в байтах, на которую указывает s. Нуль-терминатор не учитывается.
— char*stpcpy (char *_dest, const char *_src); — функция копирует строку, на которую указывает src, в другое место памяти, на которое указывает dest. Функция возвращает указатель на начало строки, которая копировалась в dest.
char*strncpy (char*_dest, const char*_src, size_t_maxlen); — функция копирует maxlen байт из строки, на которую указывает src, в другое место в памяти, на которое указывает dest. Нуль-терминатор тоже копируется. Если maxlen меньше длины строки src, к строке src не присоединяется символ “\0”. А если больше, то строка src переносится полностью, а символы, которые остались, заполняются символом “\0”. Функция возвращает указатель dest.
char *strlwr (char *_s); — функция превращает все символы строки, на начало которой указывает s, в маленькие буквы. Функция возвращает указатель на начало этой строки.
char *strups (char *_s); — функция превращает все символы строки, на начало которой указывает s, в большие буквы. Функция возвращает указатель на полученную строку.
char *strset (char *_s, int_ch); — функция заполняет строку, на начало которой указывает s, символом ch. Функция возвращает указатель на полученную строку.
Пример 4.1
Подсчитать количество слов в строке, учитывая то, что пропусков между словами может быть сколько угодно.
#include <iostream.h>
#include <conio.h>
void main()
{ char *s=”Repetitio est mater studiorum ”;
int i=1, col=0;
while (s[i]!=’\0’)
{if (s[i]==’ ’) { col++;
while (s[i]==’ ’)
i++;
}
else i++;
}
cout<<”\n Kolichestvo slov=”<<col<<’\n’;
}
Пример 4.2
В предложении найти слово с максимальным количеством букв.
#include <iostream.h>
#include <string.h>
#include <stdio.h>
void main()
{char tex1[]=" s1 s2max, slovo kolichchch, bukv!"; // предложение
char *p1,*pmax;
char del[]=" ,!."; // строка символов-разделитель между словами
int dl,dlmax;
cout<<" NACHALO ! ETO VASHA STROKA: "<<tex1<<endl;
p1=strtok(tex1,del); // выделение начального слова
pmax=p1;
dlmax=strlen(p1);
while (p1!=NULL)
{ dl=strlen(p1);
if (dl>dlmax)
{dlmax=dl; pmax=p1;}
p1=strtok(NULL,del); // перемещение указателя к следующему слову,
// начиная с указателя NULL
}
cout <<" max_dlina = "<<dlmax<<" mslovo= "<<pmax<<endl;
}
4.4 Контрольные вопросы и задания.
1. Что такое строка символов в языке С++?
2. Какие преимущества имеет работа с массивами символов?
3. Какие преимущества имеет работа со строками символов? Как она реализуется?
4. Разобраться с техникой ввода-вывода строки в С++.
5. Когда можно не описывать длину строки?
6. Какие функции работы со строками в С++ используются для вставки и удаления подмножеств слов?
7. Для чего используется функция strtok?
8. Что делает оператор p1=strtok(NULL,del); ?
