Практикум ргппу 2017 3 Аннотация
Скачать 3.14 Mb.
|
8. Дан двумерный массив целых чисел из 4 столбцов и 4 строк. Все элементы главной диагонали заменить на сумму элементов в данном массиве, имеющих четное значение. 9. Дан двумерный массив вещественных чисел из 4 столбцов и 3 строк. Поменять местами первый столбец и столбец и столбец, где находится максимальный элемент массива. Вывести массив по строкам до и после перестановки. 10. Дан двумерный массив целых чисел из 4 столбцов и 4 строк. Найти минимальный элемент в первой половине массива (просмотр вести по строкам) и во второй половине массива. Поменять местами эти минимальные элементы массива. 11. Дан двумерный массив целых чисел из 4 столбцов и 3 строк. Найти сумму элементов в этом массиве стоящих после первого нуля.. 12. Дан двумерный массив целых чисел из 4 столбцов и 3 строк. Найти максимальный элемент среди отрицательных элементов этого массива. Вывести массив по строкам. Лабораторная работа № 7 Строки в C++ Теория Строковые значения (string values) нам уже встречались. Таким значением является, например, строка "Привет! ", которая входит в следующую cout- инструкцию: cout << "Привет!"; Строковые значения в C++ можно хранить в переменных и обрабатывать их подобно тому, как обрабатываются данные других типов. В C++ существуют 2 вида строк: С-строки, унаследованные от своего предшественника — языка С Класс string. Рассмотрим каждый из этих видов строк более подробно. С-строки Строковая переменная (cstring variable) — это то же самое, что и массив символов. Естественно представлять ее себе именно в таком виде. Строка суть множество символов, и для его хранения нам нужно не что иное, как массив символов. Таким образом, следующее объявление массива предоставляет 134 возможность хранить строковую переменную, состоящую не более чем из 9 символов: char s [10] ; Ошибки здесь нет; как было отмечено, строковая переменная s может хранить не более 9 символов. Хранить 10 символов она не может, потому что используется несколько иначе, чем обычный массив символов. На самом деле строковая переменная является частично заполненным массивом символов. Подобно любому другому частично заполненному массиву, она использует элементы массива, начиная с нулевого и заканчивая тем, в который записывается последний символ. Однако для того, чтобы запомнить количество используемых элементов частично заполненного массива, в строковой переменной применяется свой специфический метод. Здесь для записи количества используемых элементов нам не нужна дополнительная переменная типа int. Вместо этого в массиве, в котором хранится строковая переменная, сразу после последнего символа строки ставится специальный символ '\0'. Таким образом, если значением переменной s является строка "Привет! ", то элементы массива заполнены следующим образом: s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7] s[8] s[9] П р и в е т ! \0 ? ? Символ '\0' служит сигнальной меткой, обозначающей конец строки. Читая ее символы — s[0], s[l], s[2] и т.д., мы знаем, что, как только встретимся с символом '\0', это будет означать достижение конца строки. Поскольку символ '\0' всегда занимает один элемент массива, максимальная длина строки, которая может храниться в массиве, на единицу меньше его размера. Символом ' \0' помечается окончание строки, хранящейся в массиве символов. При таком использовании массив носит название строковой переменной. Хотя '\0' записывается впрограмме с помощью двух символов, на самом деле это один символ, который можно разместить в одной переменной типа char или в одном элементе массива символов. Объявление строковых переменных Строковая переменная — это в точности то же, что и массив символов, хотя и несколько иначе используемый. Строковая переменная объявляется как обычный массив символов. Синтаксис: char Имя_массива[Максиммальный_размер_строки + 1]; Пример: char my_cstring[11]; Добавление единицы (+1) позволяет зарезервировать место для нуль-символа ' \0', который завершает каждую строку, хранящуюся в массиве. Например, в объявленной выше строковой переменной my_string можно хранить строку длиной не более 10 символов. Символ ' \0' называется нуль-символом. Как и символ новой строки ' \n', он яв- ляется специальным символом. На этом аналогия не кончается. Символ '\0', как и ' \n', в программе записывается в виде двух символов, хотя на самом деле это всего одно символьное значение. Подобно любому другому символу, ' \0' можно хранить в 135 одной переменной типа char или в одном элементе массива символов. Отличие ' \0' от других символов позволяет использовать его как сигнальную метку, обозначающую окончание строки обычных символов. Единственное, что отличает строковую переменную от обычного массива, — это то, что в конце строковой переменной обязательно должен быть символ '\0'. Впрочем, это отличие скорее относится к использованию массивов, нежели к тому, чем эти массивы являются. Строковая переменная является массивом символов, хотя и используется несколько иначе. Особенности ввода-вывода строк. Выводить строки в поток можно с помощью оператора вывода <<. Например: string s1; cout<<”Результат”< Приведем пример программы работы с C-строками. Задание: Выделить из заданного слова s подстроку s1 из k символов начиная с позиции n. 136 Ввод s i=0 s[i]!= ‟\0' i++ m=i Ввод k,n s[i]!= ‟\0' s1[i]=s[n+i] i++ s1[i]= ‟\0' Вывод s1 n+k>=m Выход за пределы строки Да Нет Да Нет Да Нет #include #include # include using namespace std; void main() {SetConsoleCP(1251); SetConsoleOutputCP(1251); char s[50],s1[50]; int n,k,m; cout<< "Строка=" ; cin>>s; cout< int i=0; while (s[i]!= '\0' ) i++; m=i; cout<< "n=" ; cin>>n; cout<< "k=" ; cin>>k; //Проверка на выход за пределы строки if (n+k>m) {cout<< "Выход за пределы строки" ; return ;} /*Получение новой подстроки из k символов с позиции n*/ i=0; while (s[i]!= '\0' && i i++;} /* Добавление в новую строку символа окончания строки*/ s1[i]= '\0' ; cout< } Ввод кириллицы Обратите внимание на подключение библиотеки windows.h . Ранее использовалась библиотека locale и метод setlocale(0, ―‖) для отображения русских букв, набранных в редакторе кода. Но в данной задаче может возникнуть ситуация ввода русских букв в консольном экране. В этой ситуации метод setlocale не поможет. Для ввода и вывода русских букв в консольном приложении надо: 137 1. Подключить библиотеку windows.h : # include 2. Вызвать методы: SetConsoleCP(1251); SetConsoleOutputCP(1251); 3. В свойствах консоли ( в окошке которое появляется при запуске программы) выбрать язык Lucide Console: Результат работы программы: 138 Для С-строк не определены операции присваивания и конкатенации, для С-строк нет операций сравнения, в отличии от других языков программирования. Для этих операций созданы специальные функции в библиотеке cstring. strlen(строка) – возвращает целое число, равное длине строки без учета нуль- символа; strcpy(строка1,строка2) – копирует значение строка2 в переменную строка1; strcat(строка1, строка2) – присоединяет строковое значение строка2 к окончанию значения строковой переменной строка1; strcmp(строка1, строка2) – если строка1 и строка2 совпадают, возвращает 0, если строка1 меньше, чем строка2, возвращает отрицательное число, если строка1 больше строка2, возвращает положительное число. Для C-строк существуют функции преобразования строк в числа, которые находятся в библиотеке cstdlib: atoi(строка_цифр) – возвращает значение типа int; atol(строка_цифр) – возвращает значение типа long; atof(строка_цифр_с_разделителем_точка) – возвращает значение типа double. Если строковый аргумент не допускает такого преобразования, функция возвращает нулевое значение. Работа с С-строками достаточно сложная, кроме того, для этих строк работа с существующими функциями не всегда корректна, а обнаружить эту опасность достаточно сложно. Поэтому мы будем работать с другим видом строк – с классом string, который похож на строки в других языках программирования. Класс string Для работы с классом string требуется подключать библиотеку string. Для класса string определена операция присваивания (=) копирование одной строки в другую и операция конкатенации (+) – сцепления строк: s3=s1+s2 s=‖Пример‖+‖ ―+‖текста‖ Описание строковых переменных: string s; string s1(―Программирование‖); string s2=‖Пример ввода‖ При объявлении переменной s она инициализируется пустой строкой, при объявлении переменной s1 она инициализируется значением заданного аргумента: ―Программирование‖, а s2 - инициализируется значением ‖Пример ввода‖. Ввод –вывод строк С их помощью операторов << и >> ввод и вывод объектов типа string выполняется в том же виде, что и ввод-вывод С-строк. Заметим, что оператор >> 139 точно так же игнорирует пробелы, как и обычный оператор >> при использовании со стандартными типами, например с типом int. Если в строке встречаются пробелы, то перегруженный оператор >> считывает не всю строку, а только ту ее часть, которая идет до пробела (игнорируя сам пробел). Таким образом, если ввод осуществляется с помощью оператора >>, то программа считывает не строки, а слова. Под словом в данном случае подразумевается любая строка, в которую не входят пробельные символы. Чтобы прочитать всю С-строку используется функция- член класса istream под названием getline. Соответствующая функция, предназначенная для использования с объектами класса string, тоже называется getline, но она не является ни членом класса iostream, ни членом класса string. Это отдельная функция; ее первый аргумент — объект типа istream, второй — объект типа string, а третий (если он есть) — символ, появление которого во входном потоке приводит к прекращению вывода. По умолчанию таким признаком завершения является символ ' \n'. Пример использования функции getline приведен далее. #include #include // . . . string strl; // объявление пустой строки getline (cin, strl); // Вносит в strl все, что вводится в строке, // вплоть до символа '\n'. Символ '\n' // удаляется из ввода и отбрасывается. У функции getline, использующейся с объектами класса string, есть два прототипа: strings getline(istream& ins, string& strVar, char delimiter); и strings getline(istream& ins, string& srVar); При работе первой версии этой функции выполняется чтение символов из объектов класса istream, заданных в качестве первого аргумента функции, и вставка этих символов в строковую переменную. Это происходит до тех пор, пока в потоке не встретится символ-ограничитель (delimiter). Он удаляется из ввода и отбрасывается. Во второй версии функции роль ограничителя играет символ ' \n'; в остальном она работает точно так же, как и первая. Функция-член ignore В конструкциях вида cin>> intvar (гдеintvar— переменная типа int) все, введенное после числа, продолжает оставаться в потоке и быть доступным следующей операции ввода (включая символ '\n'). (Данное утверждение справедливо для переменных любого типа, которые извлекаются из входного потока.) Это может привести к нежелательному поведению функции getline. Одно из возможных решений этой проблемы является использование следующей функции-члена класса cin: istream& ignore(int count, char delimiter); 140 Функция либо считает count символов, либо будет считывать их до тех пор, пока ей не встретится символ-ограничитель delimiter (в зависимости от того, какое событие наступит раньше), а затем просто проигнорирует считанное. Потеря ввода при смешивании cin>> variable и getline Используя функцию getline, старайтесь свести к минимуму ввод с помощью инструкций вида cin >> variable, так как могут возникнуть проблемы. При использовании конструкции cin >> variable опускаются все пробелы, стоящие перед вводом, а символ '\n' остается в потоке. Функция же getline считывает все подряд, включая символ '\n', и останавливается. Если вызвать функцию getline после cin >> x, то она тут же встречает несчитанный символ '\n' и полагает, что имеет дело с пустой строкой. Если вы видите, что ваша программа пропускает некоторые вводимые данные, проверьте, не смешаны ли в ней два вида ввода. В такой ситуации можно использовать функцию-член класса istream с именем ignore. Например, вызов cin.ignore(10000, '\n'); приведет к считыванию 10000 символов, которые будут успешно проигнорированы (конечно же, если раньше встретится символ ' \n', то функция прекратит работу, как только считает его). Для объектов класса string используются как и в массивах квадратные скобки. Благодаря этому выражение с индексом s[i] ведет себя точно так же, как и для С- строк: оно вычленяет из строкового значения, хранящегося в объекте типа string с именем s, один символ. Таким образом, выражение s[i] можно использовать для извлечения символов точно так же, как и символы из обычного символьного массива. Важно помнить о том, что в перегрузку квадратных скобок для объектов класса string не входит проверка выхода значений индексов за дозволенные пределы. Это означает, что правильность использования значений индексов не проверяется. Проверку такого типа выполняет функция-член под названием at, которая в основном работает точно так же, как и квадратные скобки, но все же имеет два отличия. Для нее используются обозначения, принятые для функций, поэтому вместо s[i] нужно использовать s.at (i). Второе отличие состоит в том, что функция-член at проверяет, является ли значение аргумента i правильным индексом. В двух приведенных ниже примерах фрагментов кода предпринимается попытка выйти за пределы строки. В первом из них сообщение об ошибке не выведется, несмотря на то что в нем происходит обращение к переменной с несуществующим индексом: string str("Mary"); cout << str[6] << endl; Однако во втором фрагменте произойдет аварийный останов программы, из чего можно сделать вывод, что в программе имеется ошибка. string str("Mary"); cout << str.at (6) << endl; Отдельно взятый символ строки можно изменить, присвоив переменной с индексом name[i] новое значение. То же можно сделать и с помощью функции- члена at(pos). Например, чтобы заменить третий символ строки s символом 'X', можно использовать следующий фрагмент кода: 141 s.at(2) = 'X'; или s[2] = 'X'; Как и в обычном массиве, индексация позиций символов в объектах типа string начинается с 0, поэтому индекс третьего символа строки равен 2. Часто используемые функции-члены класса string Функции Пояснение s[i] Обращение для чтения и записи к символу с индексом i s.substr(pos, len) Возвращает подстроку вызывающего объекта, начинающуюся с позиции pos и имеющую длину len (доступ только для чтения) s.с_str() Предоставляет доступ только для чтения к С-строке, представленной объектом str s.at(i) Обращается для чтения и записи к символу строки s, который имеет индекс i sl=s2; Выделяет для строки sl объем памяти, равный длине строки s2, и инициализирует строку sl значением строки s2 s+=s2; Символы строки s2 добавляются в конец строки sl, для которой выделяется необходимый объем памяти s.empty() Если строка s является пустой, возвращает true, если s не пус- тая— false s.clear() Удаляет все символы в s s.insert(pos, s2) Помещает строку s2 в строку s, начиная с позиции роs stoi(s) Возвращает значение типа int (s – строка цифр) stod(s) Возвращает значение типа double (s – строка цифр и разделитель точка) to_string Преобразовывает значение в значение string. sl==s2 sl!=s2 Проверяет, равны строки или нет; возвращает соответствующее логическое значение sl Лексикографическое сравнение строк s.find(sl) Возвращает индекс начала подстроки sl, входящей в строку s s.find(sl,pos) Возвращает индекс начала подстроки sl, входящей в строку s; поиск начинается с позиции pos s.length() s.size() Возвращает текущее количество символов в строке s Примеры Пример 1. Дан текст. Разделить текст на слова и записать их в массив. Исходные данные: text – строкового типа. Результат: массив слов slovo. Просматриваются все символы текста и, если встречаются символы разделители слов - достигнут конец слова, это слово записывается массив и готовится для записи новый элемент массива. 142 Тестовый пример: при text=‖Сумма трех целых чисел‖ получаем массив: slovo[0]=‖Сумма‖, slovo[1]=‖трех‖, slovo[2]=‖целых‖, slovo[3]=‖чисел‖. Ввод text k=0; m=0 punct= ‟.,!:?;” „ l=text.length() i=0, .., l-1 n=(int)punct.find(text[i]) n>=0 k>0 и s!= ”-“ text=text+ ” “ s= ”” s=s+text[i] k=k+1 slovo[m]=s k=0 s= ”” Переменная содержащая все разделители слов, кроме тире (дефиса) k - количество букв в слове m – Индекс первого элемента массива Очистка переменной, в которой будут накапливаться буквы слова Добавление в конец текста разделителя слов (пробела) Определение количества символов в text Цикл для перебора символов в тексте Определение, является ли текущий символ разделителем слов Если i-й символ - разделитель Да Нет Если это первый из разделителей, которые отделяют одно слово от другова или это не тире Переписываем символы, накопленные в s - в slovo[m] Очищаем переменную, в которой накапливается слово Присоединяем символ к слову Увеличиваем количество символов в слове Да Нет Ввод текста Переход к следующему индексу массива slovo m=m+1 i=0, …, m-1 slovo[i] Вывод элементов массива slovo Код программы # include # include #include # include 143 using namespace std; void main() {SetConsoleCP(1251); SetConsoleOutputCP(1251); string text, s; string punct= "., !?:;" ; int k=0,n,l,m=0; string slovo[20]; cout<< "Введите текст " ; getline(cin, text); cout< ; text=text+ " " ; l=text.length(); for ( int i=0; i int )punct.find(text[i]); if (n>=0) { if (k>0 && s!= "-" ) {slovo[m]=s; m++; k=0; } s= "" ; } else {s+=text[i]; k++; } } for ( int i=0;i } |