БлогNot. Не пригодившиеся задачи-2024, первое полугодие

Не пригодившиеся задачи-2024, первое полугодие

Сейчас в статье: 21 задача Как и в прошлый раз, будем добавлять задачи постепенно, по мере написания между делом и зря.

Основной язык C++, если не оговорено иного. Все программы выполнялись в консоли актуальных сборок Visual Studio 2019 или 2022 из пустого проекта с единственным добавленным файлом Source.cpp (для С++) или из проекта вида "Консольное приложение .NET Framework" (для C#).

1. Реализовать шаблонную функцию для создания таблицы значений функции двух переменных, изменяющихся в заданных пределах с заданным шагом. Таблица формируется в строке std::string, которую возвращает шаблонная функция.

Продемонстрировать работу шаблона для функций вида double f1(double x, double y) и int f2(int x, int y).

Для передачи в шаблон конкретной функции использовать шаблон указателя на функцию.

Реализовать возможность задания ширины столбца таблицы и количества знаков в дробной части числа.

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <cmath>

template <typename T> 
std::string table (T x1, T dx, T x2, T y1, T dy, T y2, T (*f) (T, T),
 size_t width = 8, size_t prec = 2) {
 std::string t;
 for (T x = x1; x <= x2 + dx / 10.; x += dx) {
  for (T y = y1; y <= y2 + dy / 10.; y += dy) {
   T fxy = f (x, y);
   std::stringstream ss;
   ss << std::fixed << std::setprecision (prec) << 
    std::setw (width) << x <<
    std::setw (width) << y << 
    std::setw (width) << fxy << std::endl;
   t += ss.str ();
  }
 }
 return t;
}

double f1 (double x, double y) {
 return pow (sin (x), 2) + pow (cos (y), 2);
}

int f2 (int x, int y) {
 return x % y;
}

int main () {
 std::cout << table <double> (0, 0.5, 4, 0, 0.5, 4, f1, 10, 3);
 std::cout << table <int> (1, 1, 4, 1, 1, 4, f2, 3, 0);
 return 0;
}

Мы обошлись бы без внешних функций, используя лямбды (теперь внешние определения для f1 и f2 не нужны):

int main () {
 std::cout << table <double> (0, 0.5, 4, 0, 0.5, 4, 
  [](double x, double y) {return pow (sin (x), 2) + pow (cos (y), 2); }, 
  10, 3);
 std::cout << table <int> (1, 1, 4, 1, 1, 4, 
  [](int x, int y) {return x % y; }, 3, 0);
 return 0;
}

2. Подсчитать числа рождения для всех возможных дат ДД.ММ.ГГГГ, 0 < ГГГГ < 10000 и построить частотную таблицу для чисел рождения 1,2,...,9.

Теоретически ясно, что чисел окажется примерно поровну, поскольку искомые суммы будут меняться "по кругу" - 1,2,...,9,1,2,...,9 и т.д.

#include <iostream>
#include <iomanip>
using namespace std;

size_t sumOfDigits (size_t n) {
 size_t s = 0;
 do {
  s += n % 10;
  n /= 10;
 } while (n);
 return s;
}

int main () { 
 size_t stat[10] = {0,0,0,0,0,0,0,0,0,0};
 size_t md[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
 for (size_t y = 1; y < 10000; y++) {
  md[2] = y % 4 == 0 && y % 100 != 0 || y % 400 == 0 ? 29 : 28;
  for (size_t m = 1; m < 13; m++) {
   for (size_t d = 1; d <= md[m]; d++) {
    size_t sum = sumOfDigits (d) + sumOfDigits (m) + sumOfDigits (y);
    while (sum > 9) sum = sumOfDigits (sum);
    stat[sum]++;
    /*
    cout << setw (2) << setfill ('0') << d << "." <<
     setw (2) << setfill ('0') << m << "." <<
     setw (4) << setfill ('0') << y << ": " << sum << endl;
    */
   }
  }
 }
 for (size_t i = 1; i < 10; i++) {
  cout << setw (1) << i << ":  " << setw (8) << stat[i] << endl;
 }
 return 0; 
}
//Вывод этой программы:
1:    405785
2:    405785
3:    405785
4:    405783
5:    405783
6:    405785
7:    405785
8:    405785
9:    405783

3. Имеется n номиналов монет, i-ый номинал стоит a[i] рублей, имеется по 2 монеты каждого номинала. Нужно набрать ровно k рублей. Программа определяет, можно ли выдать запрошенную сумму, если да, показывает, какими монетами она набрана.

Код выглядит страшновато, но, возможно, пройдёт тесты, если собрать в Release. Пытается применять meet-in-the-middle.

//Проект - Свойства - Свойства конфигурации - Общие - 
//Стандарт ISO C++17 (/std:c++17)
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <utility>

std::vector<int> vCoins, vCurComb;
std::vector<std::vector<int>> vCombinations;
int sum, iCur;

// генерирует все сочетания из vCoins.size() по num элементов в vCombinations
void generateAllCombinations (int num) {
 if (!num) {
  vCombinations.push_back (vCurComb);
  int yy = 0;
 }
 else {
  for (int i = iCur; i < vCoins.size (); ++i) {
   vCurComb.push_back (vCoins[i]);
   iCur = i + 1;
   generateAllCombinations (num - 1);
   vCurComb.pop_back ();
  }
 }
}

int main () {
 vCoins.assign ({ 1,2,3,5 }); // монеты
 sum = 13; // сумма

 for (int i = 0; i <= vCoins.size (); ++i) {
  iCur = 0;
  generateAllCombinations (i);
 }
 std::vector<std::pair<std::vector<int>, int>> vRes;
 vRes.reserve (vCombinations.size ());
 for (auto& v : vCombinations) {
  int sumv = std::reduce (v.begin (), v.end ());
  vRes.emplace_back (std::move (v), sumv);
 }

 auto vResSorted = vRes;
 std::sort (vResSorted.begin (), vResSorted.end (), 
  [](auto& pa, auto& pb) {return pa.second < pb.second; });
 auto ib = vRes.begin ();
 auto ib2 = vResSorted.begin ();
 for (; ib != vRes.end (); ++ib) {
  int need = sum - ib->second;
  if (ib2 = std::lower_bound (vResSorted.begin (), vResSorted.end (), need, 
   [](auto& pr, auto nd) { return pr.second < nd; }); ib2 != vResSorted.end ()) {
   if (ib2->second == need) break;
  }
 }
 if (ib != vRes.end ()) {
  std::cout << "Yes\n";
  std::cout << ib->first.size () + ib2->first.size () << "\n";
  for (int i = 0; i < ib->first.size (); ++i) {
   std::cout << ib->first[i] << " ";
  }
  for (int i = 0; i < ib2->first.size (); ++i) {
   std::cout << ib2->first[i] << " ";
  }
 }
 else {
  std::cout << "No\n";
 }
 return 0;
}

4. Вычислить x в 21 степени, применяя не более 6 операций умножения.

#include <iostream>
#include <cmath>

int main () {
 double x = -0.57;
 double y = x * x * x, z = y * y * y, res = z * z * y;
 std::cout << res << std::endl;
 std::cout << pow (x, 21); //для контроля
 return 0;
}

5. Найти в последовательности целых чисел максимальную длину цепочки последовательно расположенных элементов, обладающих заданным свойством, например, чётностью. Проверка свойства для одного элемента выполняется с помощью указателя на функцию, переданного в основной метод.

#include <iostream>
#include <vector>

bool even (int item) { return item%2==0; }

size_t func (std::vector <int>& a, bool (*test) (int)) {
 size_t cnt = 0, max = 0;
 for (size_t i = 0; i < a.size (); i++) {
  bool b = test (a[i]);
  if (b) cnt++;
  else {
   if (cnt > max) max = cnt;
   cnt = 0;
  }
 }
 if (cnt > max) max = cnt;
 return max;
}

int main () {
 std::vector <int> a {1,3,2,4,6,-3,8,12,22,4};
 std::cout << func (a,even);
 return 0;
}

6. Треугольник с высотой h строк выведен в консоль следующим образом (пример для h==4):

1111
222
33
4

Каждый ряд состоит из одинаковых цифр, при этом цифра в ряде с номером i определяется как остаток от деления i на 10. Количество цифр равно номеру ряда, считая с конца. Ряды нумеруются с единицы. Можно выводить больше десяти рядов. Для заданной высоты изобразить в консоли описанный перевёрнутый треугольник.

#include <iostream>

int main () {
 int h = 12;
 for (int i = 1; i <= h + 1; i++) {
  for (int j = 1; j <= h - i + 1; j++)
   std::cout << i % 10;
  std::cout << std::endl;
 }
}

7. Найти НОД двух натуральных чисел, применяя только операцию вычитания.

#include <iostream>

int main() {
 int a = 48, b = 72;
 while (a != b) {
  if (a > b) a -= b;
  else b -= a;
 }
 std::cout << a;
 return 0;
}

8. Заданы натуральные значения N, L < N и целое K = 0. В произвольном цикле по i = 1,2,...,N организовать изменение переменной K по закону 0, 1, ..., L, 0, 1, ..., L, 0, 1, ... При вычислении значения K условные операторы использовать нельзя.

#include <iostream>

int main() {
 int n = 100, l = 6, k = 0;
 for (int i = 1; i <= n; i++) {
  std::cout << k << ' ';
  k = (k + 1) % (l + 1);
 }
 return 0;
}

9. Перенести все нулевые значения из целочисленного вектора input в его конец за время O(n). Дополнительную память использовать нельзя.

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

std::vector<int> move_zeroes(std::vector<int>& input) {
 size_t j = 0, i = 0;
 for (i = 0; i < input.size(); i++) {
  if (input[i] != 0) input[j++] = input[i];
 }
 while (j < input.size()) input[j++] = 0;
 return input;
}

int main() {
 const int n = 100;
 std::vector<int> input;
 input.reserve(n);
 for (int i = 0; i < n; i++) input.push_back (i%5);
 std::copy(input.begin(), input.end(), 
  std::ostream_iterator <int>(std::cout, " "));
 input = move_zeroes (input);
 std::cout << "\n\n";
 std::copy(input.begin(), input.end(),
  std::ostream_iterator <int>(std::cout, " "));
 return 0;
}

10. Даны целые неотрицательные числа a, b, c, d, при этом 0≤c<d. Вывести в порядке возрастания все числа от a до b, которые дают остаток c при делении на d.

В этой задаче нельзя использовать любые условные операторы, а также массивы или другие контейнеры. Решение выполняется в одном цикле.

#include <iostream>

int main() {
 int a, b, c, d;
 std::cin >> a >> b >> c >> d;
 int start = (a - c + d - 1) / d * d + c;
 for (int i = start; i < b + 1; i += d) {
  std::cout << i << ' ';
 }
 return 0;
}

11. Реализовать структуру данных "очередь" со следующими методами:

  • push n - добавить в очередь число n (значение n вводится);
  • pop - удалить из очереди первый элемент;
  • front - вывести значение первого элемента, не удаляя его из очереди;
  • size - вывести количество элементов в очереди;
  • clear - очистить очередь;
  • exit - завершить работу.

Размер очереди должен быть ограничен только размером доступной оперативной памяти.

#include <iostream>

//Узел двусвязного списка
struct Node {
 Node() : next{ this }, prev{ this } {}
 Node(Node* before) : next{ before }, prev{ before->prev } {
  next->prev = prev->next = this;
 }
 virtual ~Node() {
  prev->next = next;
  next->prev = prev;
 }
 Node* next;
 Node* prev;
};

//Структура для одного элемента списка
template<typename T>
struct ValueNode : public Node {
 T value;
 ValueNode(Node* before, const T& value) : Node{ before }, value{ value } {}
};

//Структура начала двусвязного списка
struct HeaderNode : public Node {
 size_t size;
 HeaderNode() : Node(), size(0) {}
};

//Основной класс
template<typename T> class Queue {
public:
 Queue() : base() {}
 Queue(const Queue<T>&) = delete;
 Queue(Queue<T>&&) noexcept = delete;
 Queue<T>& operator=(const Queue<T>&) = delete;
 Queue<T>& operator=(Queue<T>&&) noexcept = delete;
 ~Queue() { clear(); }
 void push(const T& value) {
  new ValueNode<T>(&base, value);
  ++base.size;
 }
 void pop() {
  delete base.next;
  --base.size;
 }
 size_t getSize() const {
  return base.size;
 }
 const T& getFront() const {
  return dynamic_cast<ValueNode<T>*>(base.next)->value;
 }
 bool isEmpty() const {
  return base.next == &base;
 }
 void clear() {
  while (!isEmpty()) pop();
 }
private:
 HeaderNode base;
};

int main() {
 Queue<int> queue;
 std::string command;
 std::cout << "Enter the command (push, pop, front, size, clear or exit): ";
 while (std::cin >> command && command != "exit") {
  if (command == "push") {
   int value;
   std::cout << "Enter integer value: ";
   std::cin >> value;
   queue.push(value);
  }
  else if (command == "pop") {
   if (queue.isEmpty()) {
    std::cout << "Error, queue is empty\n";
   }
   else {
    std::cout << queue.getFront() << "\n";
    queue.pop();
   }
  }
  else if (command == "front") {
   if (queue.isEmpty()) {
    std::cout << "Error, queue is empty\n";
   }
   else {
    std::cout << queue.getFront() << "\n";
   }
  }
  else if (command == "size") {
   std::cout << queue.getSize() << "\n";
  }
  else if (command == "clear") {
   queue.clear();
  }
  std::cout << "Enter the command (push, pop, front, size, clear or exit): ";
 }
 return 0;
}

12. Реализовать деление "столбиком" двух длинных натуральных чисел.

#include <iostream>
#include <string>

std::string longDivision(std::string number, int divisor) {
 std::string ans; //результат
 int idx = 0; //индекс, который указывает на текущую цифру числа
 int temp = number[idx] - '0'; //часть числа, которую нужно поделить
 while (temp < divisor) { //пока temp меньше divisor
  temp = temp * 10 + (number[++idx] - '0');
 }
 while (number.size() > idx) { //повторяем до конца числа
  ans += (temp / divisor) + '0'; //добавляем результат в ответ
  temp = (temp % divisor) * 10 + number[++idx] - '0'; //берём следующую цифру числа
 }
 if (ans.length() == 0) //если делимое было больше или равно делителю
  return "0";
 return ans;
}

int main() {
 std::string number = "121931812224";
 int divisor = 123456;
 std::cout << longDivision(number, divisor);
 //https://www.google.com/search?q=123456*987654%3D
 return 0;
}

13. Даны два неупорядоченных набора целых чисел x и y, элементы в наборе могут повторяться и попадают в диапазон значений 0..max. Выдать без повторений в порядке возрастания числа, которые встречаются в обоих наборах. Задачу решить за время линейное время O(n+m).

Это классическая задача о пересечении множеств, но решать её поиском каждого элемента первого массива во втором очень неэффективно (время O(n2)).

Вместо этого опишем вспомогательный массив a размерностью max+1, в i-м значении которого будем хранить 0, если число i не содержится ни в одном из двух наборов чисел. Если число i имеется в первом наборе, запишем туда 1, а если в обоих наборах, запишем туда 2. После чего пробегая по массиву нужно достаточно вывести все i, у которых a[i]==2.

При создании массив a заполняется нулями, затем при чтении элемента x первого набора можно выполнять присваивание a[x]=1. При просмотре второго набора для каждого элемента y выполняем a[y]=2 только в случае, когда a[y]==1.

#include <iostream>

int main() {
 const int n = 11, m = 6, max = 10000;
 int x[n] = { 2, 4, 6, 8, 10, 12, 10, 8, 6, 4, 2 };
 int y[m] = { 3, 6, 9, 12, 15, 18 };
 int a[max+1] = {0};
 for (int i = 0; i < n; i++) a[x[i]] = 1;
 for (int i = 0; i < m; i++) if (a[y[i]] == 1) a[y[i]] = 2;
 for (int i = 0; i <= max; i++) 
  if (a[i] == 2) std::cout << i << ' ';
 return 0;
}

14. Найти последнюю цифру значения X в степени Y, X>0 и Y>9 - натуральные числа произвольной длины.

Прямое вычисление XY невозможно для сколько-нибудь больших чисел.

Последняя цифра результата зависит только от последней цифры числа X, остальные старшие разряды можно исключить.

Последняя цифра значения X4 совпадает с последней цифрой исходного числа X (если взять число, оканчивающееся на 2 и умножить его на 2, получится число, оканчивающееся на 4, при повторном умножении получим число, оканчивающееся на 8, при третьем умножении последней цифрой будет 6, а при четвертом снова получим 2). Для всех цифр можно записать аналогичную последовательность преобразований:

  0 - 0 - 0 - 0 - 0              5 - 5 - 5 - 5 - 5
  1 - 1 - 1 - 1 - 1              6 - 6 - 6 - 6 - 6
  2 - 4 - 8 - 6 - 2              7 - 9 - 3 - 1 - 7
  3 - 9 - 7 - 1 - 3              8 - 4 - 2 - 6 - 8
  4 - 6 - 4 - 6 - 4              9 - 1 - 9 - 1 - 9

При уменьшении большого значения Y на 4 последняя цифра результата не изменится, мы можем выполнить такое вычитание многократно и получить в переменой Y значение от 0 до 3, соответствующее значению Y % 4.

Далее задачу можно упростить, если искать вместо Y % 4 значение Y % 100. Действительно, если каждые 4 операции умножения не меняют последнюю цифру числа, то 100 операций также её не изменят, потому что 100 делится на 4. А чтобы найти остаток от деления длинного числа на 100 достаточно взять последние 2 цифры числа Y.

#include <iostream>
#include <string>

int main() {
 std::string sx = "12", sy = "13"; //106993205379072
 int x = sx.back()-'0',
  y = std::stoi(sy.substr(sy.length() - 2)) + 100,
  p = 1;
 for (int i = 1; i <= y; i++) p = p * x % 10;
 std::cout << p;
 return 0;
}

15. На шахматной доске располагаются 2 фигуры. Проверить, стоят ли они на одной горизонтали, вертикали или диагонали.

Позицию фигуры будем кодировать двузначным числом, десятки которого обозначают номер горизонтали сверху вниз, а единицы - номер вертикали слева направо. Проверим корректность данных и после решения задачи выведем в консоль символическое изображение доски и фигур.

#include <iostream>
#include <cmath>
using namespace std;

int main() {
 int f1, f2;
 do { //вводим, пока не получим 2 допустимых числа
  cout << "\nPiece 1 position: "; cin >> f1;
  cout << "Piece 2 position: "; cin >> f2;
  if (!cin.good()) {
   cin.clear();
   cin.ignore(100, '\n');
   continue;
  }
  if (f1 < 11 || f1 > 88 || f1 % 10 == 0 || f1 % 10 == 9) continue;
  if (f2 < 11 || f2 > 88 || f2 % 10 == 0 || f2 % 10 == 9) continue;
  break;
 } while (1);
 int r1 = f1 / 10, r2 = f2 / 10, c1 = f1 % 10, c2 = f2 % 10;
 if (c1 == c2) cout << "Vertical\n";
 else if (r1 == r2) cout << "Horizontal\n";
 else if (abs(r1 - r2) == abs(c1 - c2)) cout << "Diagonal\n";
 else cout << "No line\n";
 for (int i = 1; i < 9; i++) {
  cout << "\n";
  int k = i % 2;
  for (int j = 1; j < 9; j++) {
   int pos = i * 10 + j;
   if (pos == f1 || pos == f2) cout << "][";
   else cout << (k % 2 ? "__" : "##");
   k ^= 1;
  }
 }
 return 0;
}

Пример вывода программы:

Piece 1 position: 16
Piece 2 position: 61
Diagonal

__##__##__][__##
##__##__##__##__
__##__##__##__##
##__##__##__##__
__##__##__##__##
][__##__##__##__
__##__##__##__##
##__##__##__##__

16. Разложить в ряд Тейлора функцию гиперболического синуса по формуле sum ( x^(2n+1)/(2n+1)! ), |x|≤1. Сравнить результат разложения в ряд со значением, вычисленным стандартной функцией.

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
 double x = 0.5, //значение x
  f = sinh(x),  //точное значение функции
  s = 0,         //сумма ряда
  eps = 1e-9,    //допустимая погрешность
  xn = x;        //x в степени (2n+1)
 long int n = 1, //счетчик шагов
  nf = 1;        //(2n+1)!
 while (abs(f - s) >= eps) { //так как известно точное значение
  s += xn / nf;
  n += 2;
  xn *= x * x;       //каждый раз вычислять степень и факториал
  nf *= n * (n - 1); //заново - сильно терять в точности
  if (n > 1000) {
   cout << "Max steps = " << n << endl;
   break;
  }
 }
 cout.precision(12);
 cout << "x=            " << fixed << x << endl;
 cout << "sinh(x)=      " << f << endl;
 cout << "sum=          " << s << endl;
 cout << "|sinh(x)-sum|=" << abs(f - s) << endl;
 return 0;
}

17. Используя стандартные функции C++, определить день недели по введённой дате ДД.ММ.ГГГГ, год больше 1900, проверка корректности вводимых данных не обязательна.

#include <iostream>
#include <ctime>
#include <clocale>

int main() {
 // https://cplusplus.com/reference/clocale/setlocale/
 std::setlocale(LC_ALL, "");
 // https://cplusplus.com/reference/ctime/tm/
 std::tm srcTime{};

 std::cout << "Введите день: ";
 std::cin >> srcTime.tm_mday;
 std::cout << "Введите месяц: 1-12: ";
 std::cin >> srcTime.tm_mon;
 std::cout << "Введите год: ";
 std::cin >> srcTime.tm_year;

 // -1 означает, что mktime() должен (используя информацию 
 // о часовом поясе и системные базы данных) попытаться 
 // определить, действует ли летнее время в указанное время.
 srcTime.tm_isdst = -1;
 // tm_year должен содержать кол-во лет прошедших с 1900 года 
 srcTime.tm_year -= 1900;
 // месяцы в std::tm начинаются с 0
 srcTime.tm_mon -= 1;

 // https://cplusplus.com/reference/ctime/mktime/
 std::mktime(&srcTime);  // нормализуем srcTime

 char respBuf[64]; // сюда strftime сохранит результат
 // https://cplusplus.com/reference/ctime/strftime/
 std::strftime(respBuf, sizeof(respBuf), "%A", &srcTime);
 std::cout << respBuf << std::endl;

 return 0;
}

18. Найти с помощью решета Эратосфена простые числа до верхней границы поиска 100000000 и сохранить их в текстовый файл.

#include <iostream>
#include <fstream>
#include <numeric>

int main () {
 unsigned long int n = 100000000; // 0x7ffffffful; // - память выделится, но нереально долго
 unsigned long int* a = new unsigned long int[n + 1];
 std::iota (a,a+n+1,0ul);
 if (!a) {
  std::cout << "No memory";
  return -1;
 }
 
 unsigned long int i = 2ul, j;
 a[1] = 0ul;
 while (i <= n) {
  if (a[i] != 0ul) {
   j = i + i;
   while (j <= n) {
    a[j] = 0ul;
    j += i;
   }
  }
  i++;
 }
 std::ofstream f ("numbers.txt");
 if (!f) {
  std::cout << "Can't open numbers.txt to write results";
  return -2;
 }
 unsigned long int k = 0;
 for (i = 2; i < n; i++) {
  if (a[i] != 0ul) f << a[i] << std::endl;
  k++;
  if (k % 100000 == 0) std::cout << '.';
 }
 f.close ();
 std::cout << std::endl << "See results in numbers.txt";
 return 0;
}

19. Заполнить квадратную матрицу целыми числами 1, 2, 3, ... по диагоналям, начиная с правого нижнего угла:

 25 23 20 16 11
 24 21 17 12  7
 22 18 13  8  4
 19 14  9  5  2
 15 10  6  3  1

#include <iostream>
#include <iomanip>
#include <algorithm>

int main() {
 const int N = 5;
 int a[N][N] = { 0 };
 for (int i = 0, k = N*N; i < 2 * N; i++) {
  for (int j = std::max(0, i - N + 1); j < std::min(i + 1, N); j++)
   a[i - j][j] = k--;
 }
 for (int i = 0; i < N; i++) {
  for (int j = 0; j < N; j++)
   std::cout << std::setw(3) << a[i][j];
  std::cout << std::endl;
 }
 return 0;
}

20. Создать папку в файловой системе, возможно, с пробелами и кириллицей в имени.

Для этой программы должен быть включён стандарт C++17 и выбрана кодировка UTF-8 для исходного файла (см. ответы #3, #21 здесь).

#include <iostream>
#include <string>
#include <clocale>
#include <filesystem>

namespace fs = std::filesystem;

int main() {
 setlocale(LC_ALL,".1251");
 std::string folder("d:/temp/Новая папка");
  //папка, которую нужно создать
 // https://en.cppreference.com/w/cpp/filesystem/exists
 if (fs::exists(folder)) {
  std::cout << "Папка \""<< folder <<"\" уже существует" << std::endl;
 }
 else {
  std::cout << "Пробуем создать папку \""<< folder << "\"" << std::endl;
  // https://en.cppreference.com/w/cpp/filesystem/create_directory
  if (!fs::create_directory(folder)) {
   std::cout << "Ошибка создания папки " << folder << "\"" << std::endl;
  }
  else {
   std::cout << "Папка \"" << folder << "\" создана успешно" << std::endl;
  }
 }
 return 0;
}

21. Упаковать 3 однобайтовых символа в 32-битное число и распаковать обратно.

#include <iostream>

int pack3Chars(unsigned char a, unsigned char b, unsigned char c) {
 int ai = (int)a, bi = (int)b, ci = (int)c;
 return (ai << 16) & 0x00ff0000 |
        (bi << 8) & 0x0000ff00 |
        ci & 0x000000ff;
}

void unPack3Chars(int n, unsigned char &a, unsigned char &b, unsigned char& c) {
 a = (n & 0x00ff0000) >> 16;
 b = (n & 0x0000ff00) >> 8;
 c = (n & 0x000000ff);
}

int main() {
 unsigned char a = 'a', b = 'b', c = 'c';
 if (sizeof(int) != 4) {
  std::cout << "Need 32-bit integer for this purpose";
  return 1;
 }
 int n = pack3Chars (a,b,c);
 std::cout << std::hex << std::showbase << n << std::endl;
 unPack3Chars(n, a, b, c);
 std::cout << a << ' ' << b << ' ' << c << std::endl;
 return 0;
}

20.01.2024, 20:40 [94 просмотра]


теги: числа программирование учебное c++

К этой статье пока нет комментариев, Ваш будет первым