17 не пригодившихся задач за май 2021
Почти все задачи проверялись в консоли актуальной сборки Visual Studio 2019, для поиска на странице нужных слов нажимайте комбинацию клавиш Ctrl+F в браузере. Предыдущая заметка серии была здесь.
Среди постановок есть как совсем простые, так и чуть поинтереснее.
1. Из каждого элемента вектора вычесть среднее арифметическое его элементов.
#include <iostream> #include <vector> #include <algorithm> #include <iterator> #include <numeric> using namespace std; int main() { vector <double> v {1, 2, 3, 4}; cout << "Source= "; copy(v.begin(), v.end(), ostream_iterator<double>(cout, " ")); double avg = accumulate(v.begin(), v.end(), 0.0) / v.size(); cout << endl << "Avg= " << avg << endl; transform(v.begin(), v.end(), v.begin(), [&](double x) { return x - avg; }); //или for_each (v.begin(), v.end(), [&](double x) { x -= avg; }); cout << "Destination= "; copy (v.begin(), v.end(), ostream_iterator<double>(cout, " ")); return 0; }
2. Сделать копию стека St без отрицательных элементов. Результат – новый стек St1.
#include <QStack> #include <QtAlgorithms> #include <QDebug> int main() { QStack <int> St, St1; St << 1 << -2 << 3 << -3 << 2; qDebug() << St; std::copy_if (St.begin(), St.end(), std::back_inserter(St1), [](int i){ return i>=0; } ); qDebug() << St1; return 0; }
Сделано в Qt, там удобнее запись элементов в стек оператором << и вывод с помощью qDebug.
3. Записать в бинарный файл N = 10 целых чисел с консоли. Найти сумму максимального и минимального чисел, найденным значением заменить первую и предпоследнюю компоненты файла. Сумму, исходный файл и файл после замены вывести в консоль.
#include <cstdlib> #include <iostream> #include <fstream> #include <vector> #include <algorithm> #include <iterator> using namespace std; template <typename T> vector <T> read(const char* fname) { vector <T> v; ifstream f(fname, ios::binary); if (!f) { cout << "Can't open " << fname << " to read data"; exit(2); } T val; while (!f.read((char*)&val, sizeof(T)).eof()) { v.push_back (val); } f.close(); return v; } int main() { const int n = 10; vector <int> v; int val; cout << endl; for (size_t i = 0; i < n; i++) { do { cout << "Type item " << (i+1) << ": "; cin >> val; if (cin.good()) break; cin.clear(); cin.ignore(INT_MAX, '\n'); } while (1); v.push_back (val); } ofstream f("1.dat", ios::binary); if (!f) { cout << "Can't open 1.dat to write"; exit(1); } f.write((char*)&v[0], v.size() * sizeof(int)); f.close(); v.clear(); v = read <int> ("1.dat"); cout << endl << "Read source file: "; copy(v.begin(), v.end(), ostream_iterator <int>(cout, " ")); int sum = *min_element(v.begin(), v.end()) + *max_element(v.begin(), v.end()); cout << endl << "Sum= " << sum; fstream f2("1.dat", ios::binary | ios::in | ios::out); f2.seekp(0, ios_base::beg); f2.write((char*)&sum, sizeof(int)); f2.seekp((v.size()-2)* sizeof(int), ios_base::beg); f2.write((char*)&sum, sizeof(int)); f2.close(); v.clear(); v = read <int>("1.dat"); cout << endl << "Read changed file: "; copy(v.begin(), v.end(), ostream_iterator <int>(cout, " ")); return 0; }
Тестовый прогон:
Type item 1: 1 Type item 2: 2 Type item 3: 3 Type item 4: 4 Type item 5: 5 Type item 6: 6 Type item 7: 7 Type item 8: 8 Type item 9: 9 Type item 10: вводим что попало вместо числа, такое не пройдёт Type item 10: 10 Read source file: 1 2 3 4 5 6 7 8 9 10 Sum= 11 Read changed file: 11 2 3 4 5 6 7 8 11 10
4. В конце заданной строки дописать символы подчёркивания "_", доведя длину строки до 25 символов.
#include <iostream> #include <string> using namespace std; int main() { const size_t len = 25; string s("I'm a string"); size_t my_len = s.length(); if (my_len < len) s.insert(s.end(), len - my_len, '_'); cout << s; return 0; }
5. Сформировать контейнер q, включив в него по одному разу элементы, которые входят в одну и только одну из очередей q1 и q2 (Qt).
#include <QDebug> #include <QQueue> #include <QList> #include <QSet> int main() { QQueue <int> q1, q2; q1 << 1 << 3 << 2 << 4 << -5; q2 << 1 << 1 << 8 << 4 << -5 << 7 << 7; QSet <int> q0 = q1.toSet().intersect(q2.toSet()); //почистили от дублей очереди и пересекли их QList <int> q = q1.toSet().subtract(q0).toList() + q2.toSet().subtract(q0).toList(); //вычли пересечение из каждого из множеств и //сложили их qDebug() << q; }
6. Реализовать вычисление арифметического среднего, произведения, минимума, максимума из элементов вещественного массива с размерностью, не превышающей заданной. Использовать шаблонную функцию для ввода через cin значения числового типа с проверкой корректности ввода.
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <climits> #include <windows.h> using namespace std; template <typename T> T getVal (const char *msg, T min, T max) { T val; do { cout << endl << msg; cout.precision (2); cin >> val; if (!cin.good()) { cin.clear(); cin.ignore (INT_MAX, '\n'); continue; } if (val < min || val > max) { cout << "Введите значение от " << fixed << min << " до " << fixed << max; continue; } return val; } while (1); } int main() { SetConsoleCP(1251); SetConsoleOutputCP(1251); //windows.h const int nmax = 100; //максимальная размерность double a[nmax] = {0}; int n; //реальная размерность n = getVal ("N=", 2, nmax); double summa = 0., max = -DBL_MAX, min = DBL_MAX, pr = 0.; char buf[80]; for (int i = 0; i < n; i++) { sprintf(buf, "A[%d]=", i+1); a[i] = getVal(buf, -1e3, 1e3); summa += a[i]; if (a[i] > max) max = a[i]; if (a[i] < min) min = a[i]; if (a[i] != 0.) pr = (pr == 0 ? a[i] : pr * a[i]); } cout << endl << "AVG=" << (summa / n) << " MAX=" << max << " MIN=" << min << " PRD=" << pr; cin.get(); return 0; }
7. Обойти матрицу размерности N x N по спирали против часовой стрелки начиная с правого верхнего угла и заполнить её числами 1, 2, ..., N2
#include <iostream> #include <iomanip> using namespace std; int main() { const int n = 5; int spiral[n][n]; int value = 1; int minCol = 0; int maxCol = n - 1; int minRow = 0; int maxRow = n - 1; while (value <= n * n) { for (int i = maxCol ; i >= minCol; i--) spiral[minRow][i] = value++; //влево for (int i = minRow + 1; i <= maxRow; i++) spiral[i][minCol] = value++; //вниз for (int i = minCol + 1; i <= maxCol; i++) spiral[maxRow][i] = value++; //вправо for (int i = maxRow - 1; i > minRow; i--) spiral[i][maxCol] = value++; //вверх minCol++; minRow++; maxCol--; maxRow--; } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) cout << setw(4) << spiral[i][j]; cout << endl; } return 0; }
8. Создать класс Vector для работы с векторами на плоскости, содержащий следующие члены класса: поля double x, у; функции или операторы, позволяющие вывести на экран вектор, вычислить длину вектора, сравнить два вектора на равенство.
#include <iostream> #include <iomanip> #include <cmath> using namespace std; class Vector { double x,y; public: Vector (double _x=0., double _y = 0.) : x(_x), y(_y) {} Vector (const Vector &right) { x=right.x; y=right.y; } Vector& operator = (const Vector& right) { if (this != &right) { x = right.x; y = right.y; } return *this; } friend ostream& operator << (ostream& os, Vector& _data) { os.precision(3); os << endl << "(" << setw(8) << fixed << _data.x << "," << setw(8) << fixed << _data.y << ")"; return os; } double length() { return sqrt(pow(x,2)+pow(y,2)); } bool operator == (const Vector& right) { return x==right.x && y==right.y; } }; int main() { Vector x(1,1); cout << x; Vector y = x; cout << y; cout << endl << (x==y); cout << endl << x.length(); Vector z; z = x = y; cout << z; return 0; }
9. Объявить целочисленную квадратную матрицу порядка N. Заполнить матрицу выше главной диагонали единицами, на главной диагонали - нулями, а ниже неё – двойками. Вывести матрицу на экран.
#include <iostream> #include <iomanip> using namespace std; int main() { const int n = 5; int a[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i < j) a[i][j] = 1; else if (i > j) a[i][j] = 2; else a[i][j] = 0; cout << setw(4) << a[i][j]; } cout << endl; } return 0; }
10. По дате, заданной натуральными значениями "день", "месяц" и "год" (предполагается, что данные заданы корректно), определить и вывести дату предыдущего дня.
#include <iostream> using namespace std; int main() { int d = 27, m = 5, y = 2021; //день, месяц, год int md[] = {31,28,31,30,31,30,31,31,30,31,30,31}; //продолжительность месяцев if (y%400==0 || y%4==0 && y%100!=0) md[1]++; //29 февраля для високосных //контроля правильности данных нет if (d > 1) d--; else { if (m > 1) { m--; d = md[m-1]; } else { d = 31; m = 12; y--; //с новым годом, итить } } cout << d << "." << m << "." << y; return 0; }
11. Дано 100 первых натуральных чисел. Напечатать их по 12 в строке.
#include <iostream> #include <iomanip> int main() { for (int i = 0, cnt = 1; i < 100; i++, cnt++) { std::cout << std::setw(4) << (i + 1); if (cnt % 12 == 0) { cnt = 0; std::cout << std::endl; } } return 0; }
12. Найти количество элементов матрицы, расположенных между первым минимальным и последним максимальным элементами (при последовательном построчном обходе элементов матрицы).
#include <iostream> #include <iomanip> using namespace std; int main() { const int n = 3, m = 4; int b[n][m] = { {1,2,0,3}, {4,5,6,9}, {7,9,8,1} }; int imin1 = 0, jmin1 = 0, imaxn = 0, jmaxn = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (b[i][j] < b[imin1][jmin1]) { imin1 = i; jmin1 = j; } if (b[i][j] >= b[imaxn][jmaxn]) { imaxn = i; jmaxn = j; } } } int nmin = imin1 * m + jmin1, nmax = imaxn * m + jmaxn; if (nmin > nmax) cout << (nmin - nmax - 1); else cout << (nmax - nmin - 1); return 0; }
Но вообще в такой задаче я бы сразу матрицу делал как
const int n = 3, m = 3; int a[n * m] = { 1,2,3, 4,5,6, 7,8,9 };
и обошелся одним циклом.
13. Извлечь из строки std::string все лексемы, являющиеся допустимой записью вещественных чисел и найти сумму этих чисел.
#include <iostream> #include <sstream> using namespace std; int main() { string s("Hello, 123 , I'm a 1e3 test 1.5 "), next; // 123 1000 1.5 istringstream iss(s); double sum = 0; size_t pos = 0; while (iss >> next) { try { double f = stof(next, &pos); if (pos == next.size()) { sum += f; } } catch (invalid_argument const&) { continue; } } cout << "Sum=" << fixed << sum; return 0; }
14. Написать простейший класс Rectangle, содержащий следующие члены класса: поля double а, b; функции, позволяющие вывести на экран информацию о прямоугольнике, рассчитать периметр прямоугольника, рассчитать площадь прямоугольника, установить длины сторон прямоугольника, установить, является ли данный прямоугольник квадратом.
#include <iostream> using namespace std; class Rectangle { double a,b; public: Rectangle (double _a = 0., double _b = 0.) : a(_a), b(_b) {} void show() { cout << endl << a << ", " << b; } double perimeter() { return 2 * a + 2 * b; } double square() { return a * b; } void set (double _a = 0., double _b = 0.) { a = _a; b = _b; } bool is_square () { return a==b; } //вообще-то, вещественные числа так некорректно сравнивать, //но пугать вариантами сравнения "с точностью до..." не будем }; int main() { Rectangle r(4,3); r.show(); cout << endl << "p=" << r.perimeter() << ", s=" << r.square(); r.set(5,5); r.show(); cout << endl << "Is square now? " << r.is_square(); return 0; }
15. Написать консольную программу для решения квадратных уравнений со следующими возможностями:
- возможность последовательно решить любое количество уравнений, проверка корректности вводимых данных;
- учёт всех особых случаев, таких как тождество, несовместное уравнение, линейное уравнение, единственный вещественный корень, комплексные корни и т.п.
- корректный вывод результатов, исключающий, например, "-0" и другие проблемы, связанные с обработкой вещественных чисел.
#include <iostream> #include <cmath> #include <climits> using namespace std; //сравнение двух значений double с допустимой погрешностью eps bool equal(double a, double b, double eps) { return abs(a-b) < eps; } //замена нулём значений меньше eps, чтобы не печаталось "-0" double fmt (double a, double eps) { return (abs(a) < eps ? 0. : a); } int main() { const double eps = 1e-12; //погрешность double a,b,c,d,x1,x2; cout << "Hello, I can solve Quadratic equation a * x ^ 2 + b * x + c = 0" << endl; do { do { cout << "Type real or integer a, b, c (space delimited): "; cin >> a >> b >> c; if (cin.good()) break; cin.clear(); cin.ignore(INT_MAX, '\n'); } while (1); cout.precision(3); //сколько знаков в дробной части выводим if (equal(a,0.,eps)) { if (equal(b, 0., eps)) { if (equal(c, 0., eps)) cout << "Identity 0 = 0"; else cout << "An equation like C = 0 is inconsistent"; } else cout << "X=" << fmt(-c / b, eps) << ", linear equation"; } else { d = pow(b, 2) - 4 * a * c; if (d < 0) { x1 = -b / (2 * a); x2 = sqrt(abs(d)) / (2 * a); cout << "X1=" << fmt(x1, eps) << "+" << fmt(x2, eps) << "i, " << "X2=" << fmt(x1, eps) << "-" << fmt(x2, eps) << "i, " << " complex roots"; } else if (equal(d, 0., eps)) { cout << "X=" << fmt(-b / (2 * a), eps) << ", single root"; } else { x1 = (-b + sqrt(d)) / (2 * a); x2 = (-b - sqrt(d)) / (2 * a); cout << "X1=" << fmt(x1, eps) << ", X2=" << fmt(x2, eps); } } char action = '0'; do { cout << endl << endl << "Press 1 and Enter to solve other equation, 0 and Enter to exit: "; cin >> action; if (cin.good()) break; cin.clear(); cin.ignore(INT_MAX, '\n'); } while (1); if (action == '0') break; } while (1); return 0; }
16. Переписать в std::vector построчно элементы статического и динамического двумерного массива.
Для статического можно, например, так:
const int n = 3, m = 4; int b[n][m] = { {1,2,0,3}, {4,5,6,9}, {7,9,8,1} }; int* start = &b[0][0]; vector <int> v(start, start + (n * m));С динамическим придётся ещё пробежаться по строкам. Для простоты контроль выделения памяти не делается.
const int n = 3, m = 4; int **b = new int * [n]; for (size_t i = 0; i < n; i++) { b[i] = new int [m]; for (size_t j = 0; j < m; j++) b[i][j] = i + j; } vector <int> v; for (size_t i = 0; i < n; i++) { int* start = &b[i][0]; v.insert(v.end(), start, start + m); }
17. На вход прораммы подаётся n целых чисел. Сформировать контейнер с различной длиной строк по следующему правилу: в первой строке расположить числа, оканчивающиеся на 0, во второй – на 1, в третьей на 2, и т.д. Одинаковые значения в контейнер не добавлять.
#include <iostream> #include <vector> #include <set> using namespace std; int main() { const size_t n = 100; vector <set<int>> a(10); cout << "Our data: "; int val; for (size_t i = 0; i < n; i++) { val = rand() % 100; a.at(val % 10).insert(val); cout << val << ' '; } set<int>::iterator it; for (size_t i = 0; i < 10; i++) { cout << endl << "String " << i << ": "; for (it = a.at(i).begin(); it != a.at(i).end(); ++it) cout << *it << ' '; } return 0; }
30.05.2021, 18:54 [1295 просмотров]