This question has become long after many updates. Click here to go down.
I have implemented stack using arrays in C. Please give me suggestions on how to improve it. The purpose of writing it is practice-only.
I'll be implementing it by using pointers soon so please leave the part about using pointers instead of arrays for implementing stack.
I'll keep adding updated code so please review the latest one.
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 100
#define MIN 1
#define MAX 3
void intro();
void push(int *arr, int *length, int data);
int pop(int* arr, int *length);
int main()
{
int arr[MAX_SIZE];
int length = 0;
int choice = MAX + 1;
int data;
while (1)
{
while (MAX < choice || choice < MIN)
{
system("cls");
intro();
printf("Enter your choice -> ");
scanf("%d", &choice);
}
system("cls");
switch (choice)
{
case 1:
printf("\nEnter data to be pushed -> ");
scanf("%d", &data);
push(arr, &length, data);
printf("\nData pushed");
break;
case 2:
printf("\nPopped Data is %d", pop(arr, &length));
break;
case 3:
return 0;
}
printf("\nLength is %d", length);
getchar();
getchar();
choice = MAX + 1;
}
}
void intro()
{
printf("1 Push data\n");
printf("2 Pop Data\n");
printf("3 Exit this program\n\n");
}
void push(int *arr, int *length, int data)
{
if (*length == MAX_SIZE){
printf("Stack Overflow\n");
exit(1);
}
arr[(*length)++] = data;
}
int pop(int *arr, int *length)
{
if (*length == 0){
printf("Stack Underflow\n");
exit(2);
}
return arr[--(*length)];
}
Update 1 after Lstor gave suggestions
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
static const int MAX_SIZE = 100;
static const int MIN = 1;
static const int MAX = 4;
void intro();
void push(int *, int *, int);
int pop(int *, int *);
int top(int *, int *);
int main()
{
int arr[MAX_SIZE];
int length = 0;
for (;;)
{
int choice = MAX + 1;
while (MAX < choice || choice < MIN)
{
system("cls");
intro();
printf("Enter your choice -> ");
scanf("%d", &choice);
}
system("cls");
int data;
errno = 0;
switch (choice)
{
case 1:
printf("\nEnter data to be pushed -> ");
scanf("%d", &data);
push(arr, &length, data);
if (errno == 1){
printf("\nStack overflow");
}
break;
case 2:
data = pop(arr, &length);
if (errno == 2){
printf("\nStack underflow");
}
else{
printf("\nThe data is %d", data);
}
break;
case 3:
data = top(arr, &length);
if (errno == 1){
printf("\nStack overflow");
}
else if (errno == 2){
printf("\nStack underflow");
}
else{
printf("\nThe data at top is %d", data);
}
break;
case 4:
return 0;
}
printf("\nLength is %d", length);
getchar();
getchar();
}
}
void intro()
{
printf("1 Push data\n");
printf("2 Pop Data\n");
printf("3 See the top of the stack\n");
printf("4 Exit this program\n\n");
}
void push(int *arr, int *length, int data)
{
if (*length == MAX_SIZE){
errno = 1;
return;
}
arr[(*length)++] = data;
}
int pop(int *arr, int *length)
{
if (*length == 0){
errno = 2;
return -1;
}
return arr[--(*length)];
}
int top(int *arr, int *length)
{
if (*length == 0){
errno = 2;
return -1;
}
else if (*length == MAX_SIZE){
errno = 1;
return -1;
}
return arr[*length - 1];
}
Update 2 - Includes the suggestions by Lstor given in comments and William Morris's suggestions. I changed a few things and didn't implement William Morris's suggestion about user experience.
#include<assert.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
static const int MAX_SIZE = 100;
enum action {PUSH = 1, POP, TOP, QUIT};
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = 0;
do
{
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, QUIT);
scanf("%d", &choice);
} while (choice != PUSH && choice != POP && choice != TOP && choice != QUIT);
return (enum action) choice;
}
void push(int *arr, int *length, int data)
{
if (*length == MAX_SIZE){
errno = PUSH;
return;
}
arr[(*length)++] = data;
}
int pop(int *arr, int *length)
{
if (*length == 0){
errno = POP;
return -1;
}
return arr[--(*length)];
}
int top(int *arr, int *length)
{
if (*length == 0){
errno = POP;
return -1;
}
else if (*length == MAX_SIZE){
errno = PUSH;
return -1;
}
return arr[*length - 1];
}
int main(void)
{
int arr[MAX_SIZE];
int length = 0;
enum action choice;
while ((choice = get_user_action()) != QUIT)
{
clear_screen();
int data;
errno = 0;
switch (choice)
{
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
push(arr, &length, data);
if (errno == PUSH){
printf("Stack overflow\n");
}
break;
case POP:
data = pop(arr, &length);
if (errno == POP){
printf("Stack underflow\n");
}
else{
printf("The data is %d\n", data);
}
break;
case TOP:
data = top(arr, &length);
switch (errno)
{
case PUSH:
printf("Stack overflow\n");
break;
case POP:
printf("Stack underflow\n");
break;
default:
printf("The data at top is %d\n", data);
}
break;
default:
assert(!"You should not have reached this.");
}
printf("Length is %d\n", length);
getchar();
getchar();
}
}
Update 3 Includes William Morris's suggestions to Update 2
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
static const int MAX_SIZE = 100;
enum action {PUSH = 1, POP, TOP, QUIT};
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = PUSH - 1;
do
{
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, QUIT);
scanf("%d", &choice);
} while (choice != PUSH && choice != POP && choice != TOP && choice != QUIT);
return (enum action) choice;
}
void push(int *arr, int *length, int *status, int data)
{
*status = PUSH - 1;
if (*length == MAX_SIZE){
*status = PUSH;
return;
}
arr[(*length)++] = data;
}
int pop(int *arr, int *length, int *status)
{
*status = PUSH - 1;
if (*length == 0){
*status = POP;
return -1;
}
return arr[--(*length)];
}
int see_top(int *arr, int *length, int *status)
{
*status = PUSH - 1;
if (*length == 0){
*status = POP;
return -1;
}
return arr[*length - 1];
}
int main(void)
{
int arr[MAX_SIZE];
int length = 0;
enum action choice;
while ((choice = get_user_action()) != QUIT)
{
clear_screen();
int status;
int data;
switch (choice)
{
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
push(arr, &length, &status, data);
if (status == PUSH){
printf("Stack overflow\n");
}
else{
printf("%d pushed onto the stack\n", data);
}
break;
case POP:
data = pop(arr, &length, &status);
if (status == POP){
printf("Stack underflow\n");
}
else{
printf("The data is %d\n", data);
}
break;
case TOP:
data = see_top(arr, &length, &status);
switch (status)
{
case POP:
printf("Nothing in the stack\n");
break;
default:
printf("The data at top is %d\n", data);
}
break;
default:
assert(!"You should not have reached this.");
}
printf("Length is %d\n", length);
getchar();
getchar();
}
}
Update 4 After William Morris's comments on Update 3. I also made the whole thing use consistent bracing style suggested by Lstor in my question about stack implementation by pointers
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static const int MAX_SIZE = 100;
enum action {START, PUSH, POP, TOP, QUIT, END};
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = START;
do {
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, QUIT);
scanf("%d", &choice);
} while (!(START < choice && choice < END));
return (enum action) choice;
}
void push(int *arr, int *length, int *status, int data)
{
*status = START;
if (*length == MAX_SIZE) {
*status = PUSH;
return;
}
arr[(*length)++] = data;
}
int pop(int *arr, int *length, int *status)
{
*status = 0;
if (*length == 0) {
*status = 1;
return -1;
}
return arr[--(*length)];
}
int peek(int *arr, int *length, int *status)
{
*status = 0;
if (*length == 0) {
*status = 1;
return -1;
}
return arr[*length - 1];
}
int main(void)
{
int arr[MAX_SIZE];
int length = 0;
enum action choice;
while ((choice = get_user_action()) != QUIT) {
clear_screen();
int status;
int data;
switch (choice) {
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
push(arr, &length, &status, data);
if (status == 1) {
printf("Stack overflow\n");
} else {
printf("%d pushed onto the stack\n", data);
}
break;
case POP:
data = pop(arr, &length, &status);
if (status == 1) {
printf("Stack underflow\n");
} else {
printf("The data is %d\n", data);
}
break;
case TOP:
data = peek(arr, &length, &status);
if (status == 1) {
printf("Nothing in the stack\n");
} else {
printf("The data at top is %d\n", data);
}
break;
default:
assert(!"You should not have reached this.");
}
printf("Length is %d\n", length);
getchar();
getchar();
}
}
Update 5 After discussing things in chat William Morris suggested other things. I have included Lstor's suggestion about using enum for status and suggestion in the chat.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static const int MAX_SIZE = 100;
enum action {START, PUSH, POP, TOP, QUIT, END};
enum status {SUCCESS, FAILURE};
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = START;
do {
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, QUIT);
scanf("%d", &choice);
} while (!(START < choice && choice < END));
return (enum action) choice;
}
enum status push(int *arr, int *length, int data)
{
if (*length == MAX_SIZE) {
return FAILURE;
}
arr[(*length)++] = data;
return SUCCESS;
}
enum status pop(int *arr, int *length, int *data)
{
if (*length == 0) {
return FAILURE;
}
*data = arr[--(*length)];
return SUCCESS;
}
enum status peek(int *arr, int *length, int *data)
{
if (*length == 0) {
return FAILURE;
}
*data = arr[*length - 1];
return SUCCESS;
}
int main(void)
{
int arr[MAX_SIZE];
int length = 0;
enum action choice;
while ((choice = get_user_action()) != QUIT) {
clear_screen();
int data;
switch (choice) {
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
if (push(arr, &length, data) == SUCCESS) {
printf("%d pushed onto the stack\n", data);
} else {
printf("Stack overflow\n");
}
break;
case POP:
if (pop(arr, &length, &data) == SUCCESS) {
printf("The data is %d\n", data);
} else {
printf("Stack underflow\n");
}
break;
case TOP:
if (peek(arr, &length, &data) == SUCCESS) {
printf("The data at top is %d\n", data);
} else {
printf("Nothing in the stack\n");
}
break;
default:
assert(!"You should not have reached this.");
}
printf("Length is %d\n", length);
getchar();
getchar();
}
}