Реализация стека в структуре данных на основе статического массива C++
Увидел на форме, как одну задачку решили стеком структуре данных через статический массив. Но я не понял, как работает этот стек и его функции. Ну вот к примеру для чего нам нужна переменная int arrayElementsCount = 0 и как она используется в функциях? Можете пожалуйста объяснить этот код.
#include <iostream>
#include <string.h>
#define N 5
using namespace std;
struct WebPage {
string url;
int size;
bool isConnectionSafe;
};
struct Stack {
WebPage array[N];
int arrayElementsCount = 0;
void push(WebPage webPage) {
if (size() >= N) {
cout << "Stack is full" << endl;
}
else {
array[arrayElementsCount] = webPage;
arrayElementsCount++;
}
}
void pop() {
if (isEmpty()) {
cout << "Stack is empty" << endl;
}
else {
array[arrayElementsCount - 1] = {};
arrayElementsCount--;
}
}
bool isEmpty() {
if (arrayElementsCount == 0) return true;
else return false;
}
int size() {
return arrayElementsCount;
}
void clear() {
for (int i = size() - 1; i >= 0; i--) {
array[i] = {};
}
arrayElementsCount = 0;
}
WebPage top() {
if (!isEmpty()) {
return array[arrayElementsCount - 1];
}
else {
cout << "Stack is empty." << endl;
return { "Null element", 0, false };
}
}
};
void print(Stack stack) {
Stack stackCopy = stack;
WebPage page;
for (int i = 0; i < stack.size(); i++) {
page = stackCopy.top();
if (page.isConnectionSafe) {
cout << "Webpage with safe connection: url = " << page.url << " , size is " << page.size << "kb" << endl;
}
else
cout << "Webpage with unsafe connection: url = " << page.url << " , size is " << page.size << "kb" << endl;
stackCopy.pop();
}
}
int main() {
Stack stack;
WebPage page;
stack.push({ "google.com", 139, true });
stack.push({ "youtube.com", 483, true });
stack.push({ "yabumaga.pl", 9, false });
stack.push({ "yaraketa.io", 174, false });
print(stack);
cout << endl;
page = stack.top();
stack.pop();
page.isConnectionSafe = true;
stack.push(page);
print(stack);
cout << endl;
stack.push({ "lol.com", 93, false });
stack.push({ "linkedin.com", 452, true });
stack.push({ "indianelephant.in", 872, false });
print(stack);
cout << endl;
stack.pop();
print(stack);
cout << endl;
for (int i = 0; i < 5; i++) {
stack.pop();
}
print(stack);
}
Ответы (2 шт):
Переменная arrayElementsCount - это счётчик добавленных элементов в стек.
Проверка есть ли какие-то элементы в стеки
bool isEmpty() {
if (arrayElementsCount == 0) return true;
else return false;
}
Сколько элементов Вы добавили (текущий размер)
int size() {return arrayElementsCount;}
Функция удаляет последний элемент и уменьшает счётчик arrayElementsCount на 1, если стек содержит элементы
void pop() {
if (isEmpty()) { cout << "Stack is empty" << endl; }
else {
array[arrayElementsCount - 1] = {};
arrayElementsCount--;
}
}
Во первых вы должны иметь определенное состояние экземпляров( то есть сохранить инвариант), чтобы код, использующий его, был предсказуем. Во вторых не нужно в функциях!членах выполнять выводы в консоль, потому что по ходу программы это вам может быть не нужным. Оставьте все выводы на вызывающую функцию.
Самое главное тут в том, что ваш счетчик находится в опасной зоне, и его может изменить любая функция, и от этого ваша программа станет не предсказуем(придется полагаться на то, что клиент не ошибется). Всегда лучше такие члены скрыть в закрытой части класса, тогда и не придется дать им длинные имена, потому что они только для разработчика. И вы также должны обеспечивать безопасные лишние вызовы вставки и удаления.
И вы не обеспечиваете вызовы необходимых функций для константных объектов. Чем лучше решите вопросы, быстрей и понятней будет код, и не будет лишней писанины. И, если убрать лишнее (например ваша функция вывода уже получает копию стека, но копирует его еще раз) и исходя из вышесказанного, можно написать что то подобное
struct WebPage {
string url{ "?" };
int size{};
bool isConnectionSafe{};
};
struct Stack {
bool isEmpty() const { return Count == 0; }
void push(const WebPage& webPage) {
if (Count < N)
array[Count++] = webPage;
}
void pop() {
if (Count > 0)
array[--Count] = WebPage();
}
int size() const { return Count ; }
void clear() {
while(Count)
array[--Count] = WebPage();
}
WebPage top() const {
if (Count)
return array[Count - 1];
return array[0];
}
private:
WebPage array[N];
int Count = 0;
};
void print(Stack stack) {
WebPage page = stack.top();
while (!stack.isEmpty()) {
cout << "Webpage with"
<< (!page.isConnectionSafe ? " un" : " ")
<< "safe connection: url = "
<< page.url << " , size is " << page.size << "kb" << endl;
}
stack.pop();
}
int main() {
Stack stack;
stack.push({ "google.com", 139, true });
stack.push({ "youtube.com", 483, true });
stack.push({ "yabumaga.pl", 9, false });
stack.push({ "yaraketa.io", 174, false });
//и если хотите вывод информации
// if(if(stack.top().url == "?") стек не полон или
if (stack.size() >= N )
cout << "Stack is full\n";
print(stack);
stack.clear();
stack.push({ "lol.com", 93, false });
stack.push({ "linkedin.com", 452, true });
stack.push({ "indianelephant.in", 872, false });
//...
return 0;
}
Далеко не идеально в таком состоянии, но направит вас делать лучше.