Функция push
недопустима.
Это условие в операторе if
if (s->sz+1 <= s->cap)
может быть причиной неопределенного поведения. Предположим для простоты, что s->cap
равно 1
. Таким образом, вы можете использовать sh только один элемент без изменения размера динамически выделяемого массива. Таким образом, после нажатия новое значение s->sz
будет равно 0
. И вы не можете сделать sh еще одно новое значение без изменения размера массива. Однако условие в операторе if оценивается как истинное, и вы будете записывать в память за пределами выделенного массива.
Также этот фрагмент кода
nv = (int*) realloc(s->v, sizeof(int)*s->cap);
free(s->v);
недействителен. В случае успешного вызова reallo c память, на которую указывает s-> v, была освобождена (или повторно использована). Таким образом, вызов free снова вызовет неопределенное поведение. То есть будет ли попытка освободить уже перераспределенную память или будет освобождена новая выделенная память.
Функция pu sh может быть определена, например, следующим образом
int push( stack *s, int e )
{
int success = 0;
if ( ( success = s->sz+1 < s->cap ) )
{
s->v[++s->sz] = e;
}
else
{
int *nv = realloc( s->v, sizeof( int ) * ( s->cap + 1 ) );
success = nv != NULL;
if ( success )
{
s->v = nv;
++s->cap;
s->v[++s->sz] = e;
}
}
return success;
}
Но в любом случае было бы лучше установить начальное значение для члена данных sz
на 0. В этом случае элемент данных будет отражать текущий размер стека.
Возвращаемое значение функции pop
неоднозначно. Возвращаемое значение 0 может быть допустимым значением, хранящимся в стеке. Также функция не должна выдавать никаких сообщений. Именно вызывающий объект функции решает, выдавать ли сообщение, если оно есть.
Также нет необходимости динамически выделять сам объект типа stack
. Он может иметь автоматическую c продолжительность хранения и быть локальной переменной.
И гораздо лучше, когда функция, инициализирующая стек, также имеет второй параметр, позволяющий вместо этого указать емкость созданного стека. использования magi c число 4
.
Ниже приведена демонстрационная программа, которая показывает, как можно определить стек и его функции.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *v; /* contents of the stack */
size_t cap; /* capacity of v, i.e. how many elements can fit in v */
size_t sz; /* number of elements currently stored in v */
} stack;
int init( stack * s, size_t capacity )
{
s->sz = 0;
s->cap = 0;
s->v = calloc( capacity, sizeof( int ) );
int success = s->v != NULL;
if ( success )
{
s->cap = capacity;;
}
return success;
}
int is_empty( const stack *s )
{
return s->sz == 0;
}
int push( stack *s, int e )
{
int success = 0;
if ( ( success = s->sz < s->cap ) )
{
s->v[s->sz++] = e;
}
else
{
int *nv = realloc( s->v, sizeof( int ) * ( s->cap + 1 ) );
success = nv != NULL;
if ( success )
{
s->v = nv;
++s->cap;
s->v[s->sz++] = e;
}
}
return success;
}
int pop( stack *s, int *value )
{
int success = !is_empty( s );
if ( success )
{
*value = s->v[--s->sz];
}
return success;
}
void destroy( stack *s )
{
free( s->v );
s->v = NULL;
s->cap = 0;
s->sz = 0;
}
int main( void )
{
stack pilha;
init( &pilha, 4 );
if ( is_empty( &pilha ) )
{
printf( "The stack is empty\n" );
}
const int N = 5;
for ( int i = 0; i < 5; i++ )
{
push( &pilha, i );
}
push( &pilha, N );
while ( ! is_empty( &pilha ) )
{
int value;
pop( &pilha, &value );
printf( "the current top value is %d\n", value );
}
destroy( &pilha );
if ( is_empty( &pilha ) )
{
printf("The stack isn't empty\n");
}
return 0;
}
Результат программы:
The stack is empty
the current top value is 5
the current top value is 4
the current top value is 3
the current top value is 2
the current top value is 1
the current top value is 0
The stack isn't empty