Почему не желательно писать using namespace std:
https://ru.stackoverflow.com/questions/415847/%D0%9F%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D1%81%D1%82%D0%B2%D0%BE-%D0%B8%D0%BC%D0%B5%D0%BD-using-namespace-std
https://ru.stackoverflow.com/questions/415847/%D0%9F%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D1%81%D1%82%D0%B2%D0%BE-%D0%B8%D0%BC%D0%B5%D0%BD-using-namespace-std
Stack Overflow на русском
Пространство имен (using namespace std;)
Очень часто в интернете вижу как многие программисты усердно пишут везде программы используя в коде std::. Зачем они это делают? Почему нельзя просто использовать using namespace std; перед програм...
💯2
C++ Chanel
#include <iostream> class Artist { public: void Start() { Requesting(); } private: void Requesting() { std::string figure; bool run = 0; // run будет равна false std::cout << "Write what figure you want to draw:…
тут я мог и использовать стейтмент,как и в олимпиадных задачах,там где используются только стандартная библиотека.Но про реальные проекты написано в ссылке сверху
Интересная задача на leetcode
https://leetcode.com/problems/largest-substring-between-two-equal-characters/
Решение скину позже
https://leetcode.com/problems/largest-substring-between-two-equal-characters/
Решение скину позже
LeetCode
Largest Substring Between Two Equal Characters - LeetCode
Can you solve this real interview question? Largest Substring Between Two Equal Characters - Given a string s, return the length of the longest substring between two equal characters, excluding the two characters. If there is no such substring return -1.…
❤1
Решение:
class Solution {
public:
int maxLengthBetweenEqualCharacters(string s) {
int result {-1};
for(int i = 0;i<s.size();++i){
for(int j = i+1;j<s.size();++j){
if(s[i] == s[j])
result = max(j-i-1,result);
}
}
return result;
}
};
❤1
История о том как появились foo и baz
Если кто-то не знает foo bar и baz это очень распространенные метки среди программистов,они очень часто используются в примерах разных документаций или на форумах.Примеры на фото выше.
1.Взято со stack overflow:
Foo и bar произошли от армейского акронима времён Второй мировой, FUBAR — “Fucked Up Beyond All Recognition” (англ. “Разбито в хлам”). Во время кампаний в Северной Африке и Сицилии (1942–1943) возникло целое семейство таких сокращений, которые можно найти в книге Рика Эткинсона Day of Battle: The War in Sicily and Italy, 1943-1944. Например, сокращение JANFU означает “Joint Army Navy Fucked Up” (англ. “Союз армии и флота облажался”), и применялось, в частности, для описания инцидента 11 июля 1943 года, когда британский флот сбил 23 транспортных самолёта США с десантом.
В реальном деве переменная не должна быть бессмысленной!!!!
Например в циклах i,j,k и так далее (от итерации)
Если кто-то не знает foo bar и baz это очень распространенные метки среди программистов,они очень часто используются в примерах разных документаций или на форумах.Примеры на фото выше.
1.Взято со stack overflow:
Foo и bar произошли от армейского акронима времён Второй мировой, FUBAR — “Fucked Up Beyond All Recognition” (англ. “Разбито в хлам”). Во время кампаний в Северной Африке и Сицилии (1942–1943) возникло целое семейство таких сокращений, которые можно найти в книге Рика Эткинсона Day of Battle: The War in Sicily and Italy, 1943-1944. Например, сокращение JANFU означает “Joint Army Navy Fucked Up” (англ. “Союз армии и флота облажался”), и применялось, в частности, для описания инцидента 11 июля 1943 года, когда британский флот сбил 23 транспортных самолёта США с десантом.
В реальном деве переменная не должна быть бессмысленной!!!!
Например в циклах i,j,k и так далее (от итерации)
Немножечко про set,как найти последний элемент в сете ( самый большой ):
в С++ set это структура данных которая хранит набор уникальных элементов.Это значит, что каждый элемент в сете может присутствовать только один раз.Элементы в сете не имеют определенного порядка. Это означает, что вы не можете получить доступ к элементам сета по индексу, как в массиве или списке.В стандартной библиотеке C++ контейнер std::set обычно реализуется как красно-черное дерево. Красно-черное дерево является одной из наиболее эффективных реализаций сбалансированных деревьев поиска, которые обеспечивают операции вставки, удаления и поиска за логарифмическое время в среднем. Фото красно-черного дерева выше!!!
Set довольно часто использую в задачах как и map который также реализуется через красно-черное дерево.
в С++ set это структура данных которая хранит набор уникальных элементов.Это значит, что каждый элемент в сете может присутствовать только один раз.Элементы в сете не имеют определенного порядка. Это означает, что вы не можете получить доступ к элементам сета по индексу, как в массиве или списке.В стандартной библиотеке C++ контейнер std::set обычно реализуется как красно-черное дерево. Красно-черное дерево является одной из наиболее эффективных реализаций сбалансированных деревьев поиска, которые обеспечивают операции вставки, удаления и поиска за логарифмическое время в среднем. Фото красно-черного дерева выше!!!
Set довольно часто использую в задачах как и map который также реализуется через красно-черное дерево.
К примеру: https://codeforces.com/problemset/problem/469/A простенькая задача идея которой взять два массива и соединить их в сет( из двух массивов {2,3,3} и {1,4,66,5} мы получим один сет {1,2,3,4,5,66})
Также нам нужно проверить какой самый большой элемент из двух массивов.Но как же это сделать???Можно завести переменную,но можно сделать еще легче через указатель для доступа к элементам контейнера.Для того чтобы получить последний элемент мы сначала получаем итератор на последний элемент множества a с помощью a.end(), а затем сдвигаем его на один элемент назад с помощью операции декремента --. И, наконец, с помощью операции разыменования * мы получаем значение элемента, на который указывает этот итератор, то есть мы получили последний элемент множества a.
Также нам нужно проверить какой самый большой элемент из двух массивов.Но как же это сделать???Можно завести переменную,но можно сделать еще легче через указатель для доступа к элементам контейнера.Для того чтобы получить последний элемент мы сначала получаем итератор на последний элемент множества a с помощью a.end(), а затем сдвигаем его на один элемент назад с помощью операции декремента --. И, наконец, с помощью операции разыменования * мы получаем значение элемента, на который указывает этот итератор, то есть мы получили последний элемент множества a.
*—a.end()
Codeforces
Problem - 469A - Codeforces
Codeforces. Programming competitions and contests, programming community
❤🔥1
Решение задачи:
#include <iostream>
#include <set>
using namespace std;
int main()
{
int n;
cin >> n;
int p;
int q;
set<int> res;
cin >> p;
for (int i = 0; i < p; ++i) {
int temp;
cin >> temp;
res.insert(temp);
}
cin >> q;
for (int i = 0; i < q; ++i) {
int temp;
cin >> temp;
res.insert(temp);
}
if (res.size() == n && *--res.end() == n) {
cout << "I become the guy.";
}
else {
cout << "Oh, my keyboard!";
}
return 0;
}
🍓3
Супер интересная задача на знания контейнеров map и кодировочных наборов ( Следующий пост про них )
https://codeforces.com/problemset/problem/1927/B
Решение и объяснение будет в след посте
https://codeforces.com/problemset/problem/1927/B
Решение и объяснение будет в след посте
Codeforces
Problem - 1927B - Codeforces
Codeforces. Programming competitions and contests, programming community
Решение задачи:
#include <iostream>
#include <set>
#include <map>
#include <vector>
using namespace std;
int main() {
int t{};
cin>>t;
vector<string> res;
for(int g = 0;g<t;++g){
int n;
cin>>n;
string result;
vector<int> v(n,0);
for(int i = 0;i<n;++i){
cin>>v[i];
}
map<char,int> m;
for(int i = 0;i<n;++i){
int w = 97;
for(int j = 0;j<26;++j){
if(m[w] == v[i]){
result+=(char)(w);
++m[w];
break;
}else{
w++;
}
}
}
res.push_back(result);
}
for(string s : res){
cout<<s<<endl;
}
return 0;
}
Как решить эту задачу?
Перед тем как решать ее нужно узнать как использовать map.
Если кто-то не знает - map ассоциативный контейнер основанный на ключах и значениях.Каждый элемент в map представляет собой пару ключ-значение, где ключ уникален внутри контейнера.Если вы обратитесь к любому ключу, он автоматически создан.Например, у нас есть map<char,int>:
Таким образом у нас будет автоматически сохранено значение 0 в ключ 'a'.
Также как и set,использует красно-черное бинарное дерево для хранение элементов,Это обеспечивает быстрый и эффективный поиск элементов по ключу.На удаление и вставку за логарифмическое время , занимает (O(log n)),Логарифмическое время означает, что время выполнения алгоритма растет не пропорционально размеру входных данных, а логарифмически зависит от размера входных данных.
Перед тем как решать ее нужно узнать как использовать map.
Если кто-то не знает - map ассоциативный контейнер основанный на ключах и значениях.Каждый элемент в map представляет собой пару ключ-значение, где ключ уникален внутри контейнера.Если вы обратитесь к любому ключу, он автоматически создан.Например, у нас есть map<char,int>:
std::map<char,int> m;
if ( m['a'] == 0 ){
std::cout<<"zero";
}
Таким образом у нас будет автоматически сохранено значение 0 в ключ 'a'.
Также как и set,использует красно-черное бинарное дерево для хранение элементов,Это обеспечивает быстрый и эффективный поиск элементов по ключу.На удаление и вставку за логарифмическое время , занимает (O(log n)),Логарифмическое время означает, что время выполнения алгоритма растет не пропорционально размеру входных данных, а логарифмически зависит от размера входных данных.
Указатели на функцию???
Да,в С++ такое возможно в качестве переменной или аргумента.
Недавно перечитывал cplusplus.com и увидел что в параметры можно принимать не только обычные типы,а и void что меня удивило.
Если мы напишем вот так то строка
Или можно сделать указатель на функцию в параметры:
Да,в С++ такое возможно в качестве переменной или аргумента.
Недавно перечитывал cplusplus.com и увидел что в параметры можно принимать не только обычные типы,а и void что меня удивило.
int square(int x) {
return x * x;
}
int main() {
int (*myPointer)(int) = square;
std::cout << "Квадрат: " << myPointer(5) << std::endl;
}
Если мы напишем вот так то строка
int(*myPointer)(int) = square;
будет r_value.Или можно сделать указатель на функцию в параметры:
void foo(int (*function)(int), int value) {
int result = function(value);
std::cout << "Result: " << result << std::endl;
}
int square(int x) {
return x * x;
}
int main() {
int (*myPointer)(int) = square;
foo(myPointer, 3);
}
👍3
Вот еще один пример из самого cplusplus.com :
void increase (void* data, int psize)
{
if ( psize == sizeof(char) )
{ char* pchar; pchar=(char*)data; ++(*pchar); }
else if (psize == sizeof(int) )
{ int* pint; pint=(int*)data; ++(*pint); }
}
int main ()
{
char a = 'x';
int b = 1602;
increase (&a,sizeof(a));
increase (&b,sizeof(b));
cout << a << ", " << b << '\n';
return 0;
}
Что такое умные указатели в С++?
Я думаю,что все знают что такое указатель(raw pointer) или необработанный указатель.Но для обычных указателей нужно особое внимание,так как они с легкостью сломают ваше приложение.Ихнее управление зависит только от вас,если вы динамически выделяете память( new some_type ),то вы должны удалить его в ручную ( delete some_type ) в массивах за это отвечает другой оператор( один из таких: delete[] ).И во время написания кода,вам нужно помнить какой оператор нужно использовать.А если вы случайно ошиблись - может привести к неопределенному поведению / Undefined behavior .
Чтобы избегать проблем с утечкой памяти,придумали умные указатели.Они сами делают деаллокацию,например когда вы выходите из функции (и многое другое).На самом деле,умные указатели это просто класс который проводит все манипуляции под капотом.Насчет деалокации - просто срабатывает деструктор класса который освобождает выделенную память.
Начиная с С++11 появилось три основных типа умных указателей:
std::unique_ptr — умный указатель, владеющий динамически выделенным ресурсом.
std::shared_ptr — это умный указатель, который управляет разделяемым динамически выделенным ресурсом. Он поддерживает совместное владение ресурсом несколькими std::shared_ptr, и внутренний счетчик отслеживает количество указателей, владеющих ресурсом.
std::weak_ptr — подобен std::shared_ptr, но не увеличивает счетчик.
Я думаю,что все знают что такое указатель(raw pointer) или необработанный указатель.Но для обычных указателей нужно особое внимание,так как они с легкостью сломают ваше приложение.Ихнее управление зависит только от вас,если вы динамически выделяете память( new some_type ),то вы должны удалить его в ручную ( delete some_type ) в массивах за это отвечает другой оператор( один из таких: delete[] ).И во время написания кода,вам нужно помнить какой оператор нужно использовать.А если вы случайно ошиблись - может привести к неопределенному поведению / Undefined behavior .
Чтобы избегать проблем с утечкой памяти,придумали умные указатели.Они сами делают деаллокацию,например когда вы выходите из функции (и многое другое).На самом деле,умные указатели это просто класс который проводит все манипуляции под капотом.Насчет деалокации - просто срабатывает деструктор класса который освобождает выделенную память.
Начиная с С++11 появилось три основных типа умных указателей:
std::unique_ptr — умный указатель, владеющий динамически выделенным ресурсом.
std::shared_ptr — это умный указатель, который управляет разделяемым динамически выделенным ресурсом. Он поддерживает совместное владение ресурсом несколькими std::shared_ptr, и внутренний счетчик отслеживает количество указателей, владеющих ресурсом.
std::weak_ptr — подобен std::shared_ptr, но не увеличивает счетчик.
Wikipedia
Undefined behavior
behavior of erroneous computer programs that the language standard permits to be unpredictable
Что автоматически перегружаеться при создании объекта с++?
При создании любого объекта автоматически происходит перегрузка нескольких операций а именно:
-Конструктор
Он перегружаеться для создания и инициализации объекта.Если не определить собственный - то компилятор сделает это за вас.
-Деструктор
Деструктор вызывается при удаления объекта и освобождает ресурсы занятые объектом.Если не определить собственный - то компилятор сделает это за вас.
-Конструктор копирования
Этот конструктор копирует значения членов одного объекта в другой объект того же типа.Если не определить собственный - то компилятор сделает это за вас.
-Оператор присваивания
Если вы не определите собственный оператор присваивания (operator=), компилятор сгенерирует его для вас. Этот оператор копирует один объект в другой, что позволяет выполнить присваивание между объектами.
-Конструктор перемещения
Представляет альтернативу конструктору копирования в тех ситуациях, когда надо сделать копию объекта, но копирование данных нежелательно - вместо копирования данных они просто перемещаются из одной копии объекта в другую.
Давайте посмотрим на код и сами в этом убедимся:
Такой код не получиться запустить так как не существует конструктора по умолчанию.
Для того чтобы исправить этот код нужно либо сделать автоматические значения либо перегрузить конструктор без параметров.
Код:
При создании любого объекта автоматически происходит перегрузка нескольких операций а именно:
-Конструктор
Он перегружаеться для создания и инициализации объекта.Если не определить собственный - то компилятор сделает это за вас.
-Деструктор
Деструктор вызывается при удаления объекта и освобождает ресурсы занятые объектом.Если не определить собственный - то компилятор сделает это за вас.
-Конструктор копирования
Этот конструктор копирует значения членов одного объекта в другой объект того же типа.Если не определить собственный - то компилятор сделает это за вас.
-Оператор присваивания
Если вы не определите собственный оператор присваивания (operator=), компилятор сгенерирует его для вас. Этот оператор копирует один объект в другой, что позволяет выполнить присваивание между объектами.
-Конструктор перемещения
Представляет альтернативу конструктору копирования в тех ситуациях, когда надо сделать копию объекта, но копирование данных нежелательно - вместо копирования данных они просто перемещаются из одной копии объекта в другую.
"Если не определить собственный - то компилятор сделает это за вас."
Давайте посмотрим на код и сами в этом убедимся:
#include <iostream>
class Chiken {
private:
int m_age;
std::string m_name;
public:
Chiken(int age, std::string name) :m_age(age), m_name(name) {
std::cout << "Constructor called" << std::endl;
}
int GetAge() const { return m_age; }
std::string GetName() const { return m_name; }
};
int main() {
Chiken chik1;
std::cout<<chik1.GetName();
}
Такой код не получиться запустить так как не существует конструктора по умолчанию.
Для того чтобы исправить этот код нужно либо сделать автоматические значения либо перегрузить конструктор без параметров.
Код:
#include <iostream>
class Chiken {
private:
int m_age;
std::string m_name;
public:
Chiken(int age = 0, std::string name = "Unnamed") :m_age(age), m_name(name) {
std::cout << "Constructor called" << std::endl;
}
int GetAge() const { return m_age; }
std::string GetName() const { return m_name; }
};
int main() {
Chiken chik;//вызов конструктора
Chiken chik1(12,"Vasya");//вызов конструктора
std::cout<<chik.GetName()<<std::endl;
Chiken chik2 = chik1;//Оператор присваивания
Chiken chik3(chik2); //Копирования конструктора
std::cout << chik3.GetAge();
}// вызов деструктора
Абстрактные классы
Ключевое слово class в С++ используется для объявления пользовательского типа данных.Так же это очень мощный инструмент ООП который позволяет объединять данные и методы в один объект.
Если мы хотим создать иерархию классов животных: собак,лошадей,кошек,свиней.Что нам делать?Тут вступает абстрактный класс...
С microsoft документации по С++:
То есть для того чтобы класс считался абстрактным нужна хотя-бы одна чисто виртуальная функция (pure-virtual function) .
В нашем случае мы можем сделать наш Animal клас абстрактным и наследовать наши дочерние классы. Рассмотрим на примере:
Вывод:
1. Объект абстрактного класса не может быть создан,но можно выделять динамическую память на дочерние классы через указатель или ссылку.
2. Классы наследники должны переопределить все pure-virtual функции, иначе они остануться абстрактными.
3. В нашем примере класс Animal предоставляет общие функции но он не сможет ходить,бегать,прыгать так как это КАТЕГОРИЯ ОРГАНИЗМОВ - его можно записывать в абстрактные классы.
Ключевое слово class в С++ используется для объявления пользовательского типа данных.Так же это очень мощный инструмент ООП который позволяет объединять данные и методы в один объект.
Если мы хотим создать иерархию классов животных: собак,лошадей,кошек,свиней.Что нам делать?Тут вступает абстрактный класс...
С microsoft документации по С++:
Абстрактные классы используются в качестве обобщенных концепций, на основе которых можно создавать более конкретные производные классы. Невозможно создать объект абстрактного типа класса. Однако можно использовать указатели и ссылки на абстрактные типы классов.
Вы создаете абстрактный класс, объявляя по крайней мере одну чистую виртуальную функцию-член. Это виртуальная функция, объявленная с помощью синтаксиса чистого описателя (= 0). Классы, производные от абстрактного класса, должны реализовывать чисто виртуальную функцию; в противном случае они также будут абстрактными.
То есть для того чтобы класс считался абстрактным нужна хотя-бы одна чисто виртуальная функция (pure-virtual function) .
В нашем случае мы можем сделать наш Animal клас абстрактным и наследовать наши дочерние классы. Рассмотрим на примере:
#include <iostream>
class Animal {
public:
virtual void Speak() const = 0;
virtual ~Animal() {}
};//наш абстрактный класс
class Dog : public Animal{
public:
virtual void Speak() const override { std::cout << "Dog speak! \n"; }
virtual ~Dog() {}
};
class Cat : public Animal {
public:
virtual void Speak() const override { std::cout << "Cat speak! \n"; }
virtual ~Cat() {}
};
int main() {
//Animal* prt = new Animal(); - ошибка
Animal* ptr = new Dog();
ptr->Speak();
delete ptr;
ptr = new Cat();
ptr->Speak();
delete ptr;
}
Вывод:
1. Объект абстрактного класса не может быть создан,но можно выделять динамическую память на дочерние классы через указатель или ссылку.
2. Классы наследники должны переопределить все pure-virtual функции, иначе они остануться абстрактными.
3. В нашем примере класс Animal предоставляет общие функции но он не сможет ходить,бегать,прыгать так как это КАТЕГОРИЯ ОРГАНИЗМОВ - его можно записывать в абстрактные классы.
Что такое и зачем нужны uint32_t , int64_t , uint8_t и тд?
Когда все начинали изучать С++ работали с разными типами данных ( char , int , std::string , bool ).Но на разных архитектурах и разные компиляторы хотят от int разное количество памяти.
Давайте рассмотрим это подробнее:
Влияние архитектуры на размер int
16-битные архитектуры:
На старых 16-битных системах тип int обычно занимал 2 байта (16 бит).
32-битные архитектуры:
На большинстве современных 32-битных систем тип int занимает 4 байта (32 бита). Это связано с тем, что 32-битные процессоры оптимально работают с данными размером 4 байта.
64-битные архитектуры:
На большинстве современных 64-битных систем тип int также занимает 4 байта (32 бита), несмотря на то, что процессоры способны работать с данными большего размера. Это сделано для обеспечения обратной совместимости и эффективности.
Мы можем сделать вывод что на разных устройствах код будет работать по разному.Но что если мы хотим чтобы наша программа работала одинаково на разных компиляторах и архитектурах?
Кроссплатформенность - способность программного обеспечения работать с несколькими аппаратными платформами или операционными системами.
Для того чтобы решить вопрос кроссплатформенности в С++ добавили Целочисленные типы фиксированной ширины.Они имеют один размер не зависимо от архитектуры.
Основные 8:
int8_t - char ( 1 байт)
int16_t - short ( 2 байта )
int32_t - int ( 4 байта )
int64_t - long long ( 8 байт )
Если добавить символ u в начале то будут unsigned типы ( которые не могут быть меньше нуля но хранят в два раза больше положительных чисел).
Все эти типы будут выделять на этапе компиляции столько битов,сколько написано в названии.
Когда все начинали изучать С++ работали с разными типами данных ( char , int , std::string , bool ).Но на разных архитектурах и разные компиляторы хотят от int разное количество памяти.
Давайте рассмотрим это подробнее:
Влияние архитектуры на размер int
16-битные архитектуры:
На старых 16-битных системах тип int обычно занимал 2 байта (16 бит).
32-битные архитектуры:
На большинстве современных 32-битных систем тип int занимает 4 байта (32 бита). Это связано с тем, что 32-битные процессоры оптимально работают с данными размером 4 байта.
64-битные архитектуры:
На большинстве современных 64-битных систем тип int также занимает 4 байта (32 бита), несмотря на то, что процессоры способны работать с данными большего размера. Это сделано для обеспечения обратной совместимости и эффективности.
Мы можем сделать вывод что на разных устройствах код будет работать по разному.Но что если мы хотим чтобы наша программа работала одинаково на разных компиляторах и архитектурах?
Кроссплатформенность - способность программного обеспечения работать с несколькими аппаратными платформами или операционными системами.
Для того чтобы решить вопрос кроссплатформенности в С++ добавили Целочисленные типы фиксированной ширины.Они имеют один размер не зависимо от архитектуры.
Основные 8:
int8_t - char ( 1 байт)
int16_t - short ( 2 байта )
int32_t - int ( 4 байта )
int64_t - long long ( 8 байт )
Если добавить символ u в начале то будут unsigned типы ( которые не могут быть меньше нуля но хранят в два раза больше положительных чисел).
Все эти типы будут выделять на этапе компиляции столько битов,сколько написано в названии.
Docs
Стандартные типы
Дополнительные сведения: Стандартные типы
❤1👍1😱1