Don't access argv[1] unless you are sure it exists.
Declare variables where you can initialize them (e.g., FILE *fp).
Why is your stack so incredibly small?
"External variables" is not the correct terminology. You mean "global variables", which are generally an indication of bad program organization (along with functions that take no parameters, which often means they are using globals). It is very strange that you made ch global since you are only using it in main. (And ch should be an int, not a char, since fgetc returns an int so that EOF can have a value that cannot possibly equal any char.) To facilitate passing the stack around properly, a struct is useful.
Don't open a file with mode "r+" if you are just reading from it. Use "r" instead.
You aren't testing that the popped chars actually match (are the closing forms) of the ones that you pushed.
And your algorithm is not entirely correct anyway, since if you run into a close paren that doesn't have a matching open it's possible that the stack will "underflow", which means that the parens aren't balanced.
Don't say is_empty() == true, just say is_empty(). And don't then test the opposite condition with another if; just use an else.
The following is typed up very quickly and is not perfect. Just to give you an idea.
Code:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define STACK_SIZE 100
typedef struct Stack {
char data[STACK_SIZE];
int top;
} Stack;
void make_empty(Stack *st);
bool is_empty(const Stack *st);
bool is_full(const Stack *st);
char pop(Stack *st);
void push(Stack *st, char ch);
int main(int argc, char *argv[]){
if (argc != 2) {
fprintf(stderr, "Usage: parens FILE\n");
exit(EXIT_FAILURE);
}
printf("Checking %s file: ", argv[1]);
FILE *fp = fopen(argv[1], "r");
Stack st;
make_empty(&st);
bool good = true;
for (int ch; good && (ch = fgetc(fp)) != EOF; ) {
switch (ch) {
case '(': case '{':
push(&st, ch);
break;
case ')':
if (pop(&st) != '(')
good = false;
break;
case '}':
if (pop(&st) != '{')
good = false;
break;
}
}
if (good && is_empty(&st))
printf("Parentheses/braces are nested properly.\n");
else
printf("Parentheses/braces are NOT nested properly.\n");
fclose(fp);
return EXIT_SUCCESS;
}
void make_empty(Stack *st) {
st->top = 0;
}
bool is_empty(const Stack *st) {
return st->top == 0;
}
bool is_full(const Stack *st) {
return st->top >= STACK_SIZE;
}
void push(Stack *st, char ch) {
if (is_full(st)) {
printf("Stack Overflow!\n");
exit(EXIT_FAILURE);
}
else
st->data[st->top++] = ch;
}
char pop(Stack *st) {
if (is_empty(st)) {
printf("Parentheses/braces are NOT nested properly.\n");
exit(EXIT_SUCCESS);
}
else
return st->data[--st->top];
}