Comparison between pointers and integers in C - c

What I'd like to program is having a user input a series of parentheses/braces and evaluate them whether they are nested properly or not.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define STACK_SIZE 100
char contents[STACK_SIZE];
int top = 0;
void make_empty(void)
{
top = 0;
}
bool is_empty(void)
{
return top == 0;
}
bool is_full(void)
{
return top == STACK_SIZE;
}
void push(char i)
{
if(is_full())
stack_overflow();
else
contents[top++] = i;
}
char pop(void)
{
if(is_empty())
stack_underflow();
else
return contents[--top];
}
void stack_overflow(void)
{
printf("Stack overflow\n");
exit(EXIT_FAILURE);
}
void stack_underflow(void)
{
printf("Stack underflow\n");
exit(EXIT_FAILURE);
}
int main(void)
{
char ch;
printf("Enter parentheses and/or braces: ");
while((ch = getchar()) != '\n')
{
if(ch == '(' || ch == '{')
push(ch);
else if(ch == ')')
{
if(pop != '(') /// compiler says it is a comparison between pointer and integer.
{
printf("not nested properly!");
exit(EXIT_FAILURE);
}
}
else if(ch == '}'){
if(pop != '{') /// compiler says it is a comparison between pointer and integer.
{
printf("not nested properly!");
exit(EXIT_FAILURE);
}
}
}
if(is_empty())
printf("Parentheses/braces are nested properly");
else
printf("not nested properly!!");
/* if the stack is empty, it is nested properly, otherwise not.*/
return 0;
}
the compiler says that the comparison between pop and '(' or '{' is comparison between pointer and integer, although I set the return type of the function 'pop' as int. Because of this when the program processed with right parenthesis or brace it always prints "not nested properly." How can I improve this?

This is just "mentioning" the function, not calling it.
The compiler sees a function pointer instead of the return value and its type.
pop != '{'
Use
pop() != '{'
in order to call the function and do the comparison of return value of type char and '{'.

Related

Works when executed as main, but not when called by main

I was attempting to read a CSV file with the readCsv() function defined below. I happened to observe that when the readCsv() function is called within the main() function,
I end up experiencing a runtime error and the function readCsv() fails to work properly. By contrast, when I instead rename the readCsv() function to main() (of course having commented the main()
function first), the program works perfectly. But now I'm stuck because I need to be able
to call the readCsv() function within main().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int readCsv(void)
{
int n = 0;
while(n == 0)
{
do{
printf("Enter the index of the student you want to query:");
scanf("%i",&n);
while(getchar() != '\n')
{
continue;
}
}while((isdigit(n)) != 0);
}
n++;
FILE* fp;
fp = fopen("students.csv","r+");
if ((fp == NULL)) exit(1);
char buffer[1024];
int row,column = 0;
while(fgets(buffer,1024,fp))
{
column = 0;
row++;
if(row != n)
{
continue;
}
else if (row == n)
{
char* value = strtok(buffer,",");
while(value)
{
if (column == 0)
{
printf("\nIndex:");
}
if (column == 1)
{
printf("\tName:");
}
if (column == 2)
{
printf("\tAge:");
}
if (column == 3)
{
printf("\tphone:");
}
printf("%s",value);
value = strtok(NULL,",");
column++;
}
printf("\n");
break;
}
else
{
printf("None of the conditions are true");
break;
}
}
fclose(fp);
return 0;
}
void main(void)
{
readCsv();
}
It's easy to get lost when one function tries to do everything: file open/close, user input, read from file, search for target, output results, handle problems.
Here's a snippet of your function modified to demonstrate how these operations may be handled in a more obvious (imho) sequence.
bool found = false;
while( !found && fgets(buffer,1024,fp) )
{
if( atoi( buffer ) == n ) // 'Index' is first value of each row
found = true;
}
fclose(fp);
if( !found )
{
printf("None of the conditions are true");
return 0;
}
int column = 0;
char* value = strtok(buffer,",");
/*
output fields of this row that are in buffer[]
Or, pass buffer[] to a separate function that prints the fields.
*/
return 1;

Parentheses checker in c using stacks of arrays not producing correct output everytime

I tried to write a parentheses checker in c using stacks of arrays. The code does not give error messages but sometimes gives the right output and sometimes wrong output.
How can i improve the code or any other suggestions will be very much appreciated. I am a beginner C programmer.
I tried to take the input as a string but could not do it. Any suggestions?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 25
int top = -1;
char stack[MAX];
void push(char x)
{
if(top == MAX - 1){
printf("Stack Overflow\n");
return;
}
stack[++top] = x;
}
char pop()
{
char popped;
if(top == -1) {
printf("Stack Underflow\n");
return 0;
}
popped = stack[top];
--top;
return popped;
}
char Top()
{
return (stack[top]);
}
int arePair(char opening,char closing)
{
if(opening =='(' && closing == ')') return 1;
else if((opening =='{' && closing == '}')) return 1;
else if (opening =='[' && closing == ']') return 1;
return 0;
}
int paranthesesBalanced(char *exp,int size)
{
for (int i=0;i<size;i++)
{
if(exp[i] == '(' || exp[i] == '{' || exp[i] == '[')
push(exp[i]);
else if (exp[i] == ')' || exp[i] == '}'|| exp[i] == ']')
{
if(top == -1 || !arePair(Top(),exp[i]))
return 0;
else
pop();
}
}
return (top == -1 ? 1:0);
}
int main()
{
char exp[25];
int size=0;
printf("Enter the size of
expression\n");
scanf("%d",&size);
printf("Enter the expression(Less than
25 characters): \n");
//scanf("%[ˆ\n]%",exp);
for (int i=0;i<size;i++)
{
scanf("%c",&exp[i]);
}
if(paranthesesBalanced(exp,size))
printf("Balanced!\n");
else
printf("Not Balanced!\n");
}
I agree with comments above that you should spend some time to learn how to debug your programs.
The problem with your code lies in the way you read user input. %c matches all characters including new line character. Your code in current form reads newline between size of user data and data itself as first character of the input, so exp[0] == '\n'. There are multiple ways to resolve the issue, like flushing input or uncomment the line you commented (and get rid of superfluous percent sign or switch to some other way of reading your input like using %s instead of using %c in a loop.
Hope it helps.
Here is the minimal modified version which works correctly:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 25
int top = -1;
char stack[MAX];
void push(char x)
{
if(top > MAX - 1){ //CHANGED
printf("Stack Overflow\n");
return;
}
stack[++top] = x;
}
char pop()
{
char popped;
if(top == -1) {
printf("Stack Underflow\n");
return 0;
}
popped = stack[top];
--top;
return popped;
}
char Top()
{
return (stack[top]);
}
int arePair(char opening,char closing)
{
if(opening =='(' && closing == ')') return 1;
else if((opening =='{' && closing == '}')) return 1;
else if (opening =='[' && closing == ']') return 1;
return 0;
}
int paranthesesBalanced(char *exp,int size)
{
for (int i=0;i<size;i++)
{
if(exp[i] == '(' || exp[i] == '{' || exp[i] == '[')
push(exp[i]);
else if (exp[i] == ')' || exp[i] == '}'|| exp[i] == ']')
{
if(top == -1 || !arePair(Top(),exp[i]))
return 0;
else
pop();
}
}
return (top == -1 ? 1:0);
}
int main()
{
char exp[25];
int size=0;
printf("Enter the size of xpression\n");
scanf(" %d",&size);
printf("Enter the expression(Less than 25 characters): \n");
scanf("%s",exp); //DELETED FOR LOOP - BETTER USE GETCHAR() RATHER THAN SCANF
printf("%s\n",exp);
if(paranthesesBalanced(exp,size))
printf("Balanced!\n");
else
printf("Not Balanced!\n");
}
Instead of scanf you can go this way as scanf doesn't support space i.e. if you enter hello world it will only read hello. Alternative:
int i,count++;
while((i=getchar())!=EOF)
{
if((i!=\0')&&(count<MAX))
exp[count++]=i;
else
break;
}
In this way you can easily check for length of expression and its limits + it will allow you to enter space.

Infix to postfix function error: control may reach end of non-void function

/*
This is a code that changes infix notation to postfix notation.
I used FILE/IO to get infix notations and the infix.txt file looks like
3
2+4*2-1;
9+3^2^(3-1)*2;
2*((7-2)/3+4)^2%3;
My question is I get error saying "control may reach end of non-void function" on the last two functions, icp and isp. How can I fix this?
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX_SIZE 100
#define ENTER 0x000d
void infixtopostfix(char expression[]);
char get_token(char expression[], int *index);
void push(int *top, char token);
int pop(int *top);
int icp(char op);
int isp(char op);
char stack[MAX_SIZE];
int main(void) {
int i, num;
FILE *file;
char expression[MAX_SIZE];
if((file=fopen("infix.txt","r")) == NULL) {
printf("No file.\n");
}
fgets(expression, MAX_SIZE, file);
num = atoi(expression);
for(i=0; i < num; i++) {
fgets(expression, MAX_SIZE, file);
printf("%s", expression);
infixtopostfix(expression);
}
fclose(file);
}
void infixtopostfix(char expression[]) {
char token;
char element;
int top=0;
int index=0;
for(token=get_token(expression, &index); token!=';'; token=get_token(expression, &index)) {
if(isdigit(token)) printf("%c", token);
else if(token == ')') {
while (stack[top] != '(') {
element = pop(&top);
printf("%c", element);
}
pop(&top);
}
else {
while (isp(stack[top])>=icp(token)) {
element = pop(&top);
printf("%c", element);
}
push(&top, token);
}
}
while((token=pop(&top))!=0) printf("%c", token);
printf("\n");
}
char get_token(char expression[], int *index) {
char token=expression[(*index)++];
return token;
}
void push(int *top, char data) {
if(*top < (MAX_SIZE-1)) stack[++(*top)] = data;
}
int pop(int *top) {
if(*top > -1) return stack[(*top)--];
else return 0;
}
int icp(char op) {
switch (op){
case '(' : return 20; break;
case '+' : return 12; break;
case '-' : return 12; break;
case '*' : return 13; break;
case '%' : return 13; break;
case ';' : return 0;
}
}
int isp(char op) {
switch (op){
case '(' : return 0; break;
case '+' : return 12; break;
case '-' : return 12; break;
case '*' : return 13; break;
case '%' : return 13; break;
case ';' : return 0;
}
}
While you may believe that your methods will only ever get one of these 6 characters, the compiler has to assume that any character can be passed in. At the moment, these methods will not return anything if you pass in, for example, 'x'.
You need to specify a default action for all characters not otherwise covered by your switch. Whether this is returning a default value or throwing an exception, that is up to you. But it's nonetheless a possibility your code needs to handle.
like this:
}//end switch
fprintf(stderr, "\nunrecognized OP(%c) is specified.\n", op);// '/', '^'...
return -1;//or exit(-1);

Infix notation to postfix notation using stack

I am trying to convert infix notation to postfix notation using stack. I have written the following code but it is giving me error:
/Users/apple/Desktop/infix.c|49|error: expected expression
and I am unable to find the error. Please help me to correct this code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 100
char st[MAX];
int top = -1;
void push(char st[],char);
char pop(char st[]);
void InfixtoPostfix(char source[],char target[]);
int getPriority(char);
int main(){
char infix[100],postfix[100];
printf("enter any infix expression");
fflush(stdin);
gets(infix);
strcpy(postfix,"");
InfixtoPostfix(infix,postfix);
printf("\nthe corresponding postfix expression is:");
puts(postfix);
return 0;
}
void InfixtoPostfix(char source[],char target[]){
int i=0,j=0;
char temp;
strcpy(target,"");
while(source[i]!='\0')
{
if(source[i]=='(')
{
push(st,source[i]);
i++;
}
else if(source[i]==')')
{
while((top!=-1)&&(st[top]!='('))
{
target[j]=pop(st);
j++;
}
if(top==-1)
{
printf("\nincorrect syntax");
exit(1);
}
temp=pop(st);
i++;
else if((isdigit(source[i]))||(isalpha(source[i]))
{
target[j]=source[i];
j++;
i++;
}
else if(source[i]=='+'||source[i]=='- '||source[i]=='*'||source[i]='/'||source[i]=='%d')
{
while((top!=-1)&&(st[top]!='(')&&(getPriority(st[top])>getPriority(source[i])))
{
target[j]=target[i];
i++;
}
push(st,source[i]);
i++;
}
else{
printf("\nincorrect expression");
exit(1);
}
}
while((top!=-1)&&(st[top]!='('))
{
target[j]=pop(st);
j++;
}
target[j]='\0';
}
}
int getPriority(char op)
{
if(op=='/'||op=='*'||op=='%'||op=='%')
return 1;
else if(op=='+'||op=='-')
return 0;
}
void push(char st[],char val)
{
if(top==MAX-1)
printf("overflow");
else{
top++;
st[top]=val;
}
}
char pop(char st[])
{
char val=' ';
if(top==-1)
printf("underflow");
else{
val=st[top];
top--;
}
return val;
}
Many problems, the most important one being
else if((isdigit(source[i]))||(isalpha(source[i]))
lacks a closing parentheses, your coding style makes it difficult to notice
else if ((isdigit(source[i]) != 0) || (isalpha(source[i]) != 0))
And don't use gets() it's deprecated, in your case
fgets(infix, sizeof(infix), stdin);
would work, and will have the benefit of preventing a buffer overflow.
While there are so many issues in the code,
this one here is the most horror:
if(top==-1)
{
printf("\n incorrect syntex");
exit(1);
}
temp=pop(st);
i++;
else if((isdigit(source[i]))||(isalpha(source[i]))
{
target[j]=source[i];
j++;
i++;
}
No, you are not doing that right. FWIK, C doesn't allow this:
if()
{
//some code
}
//some code
else{
//some code
}
The other issue being:
else if((isdigit(source[i]) )||(isalpha(source[i])). I would prefer it to be,
else if( (0 != isdigit(source[i])) || (0 != isalpha(source[i])) )
Or as suggested by Jonathan Leffler in a comment below: even better if you use if (isalnum(source[i])) since it checks for all alphanumeric.
Is it only me who finds the code not so readable?
Instead of if(op=='/'||op=='*'||op=='%'||op=='%') I would prefer
if((op == '/')||(op == '*')||(op == '%')) in terms of readability.

*** glibc detected *** invalid pointer: 0x00000031bee21188

I've looked through similar questions on stackoverflow, but I'm still not sure how to fix it.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
extern char * pop();
extern void push(char *);
int i;
int j=0;
//Resize the array to 1.1 it's size
void reSize(char* tag){
char *temp = malloc(1.1*sizeof(tag));
for (i=0;i<(sizeof(tag)/sizeof(tag[0]));i++){
*(temp+i) = *(tag+i);
}
free(tag);
tag = temp;
}
int compare(char* tag, char* popVal){
i=0;
while (i<sizeof(tag)/sizeof(tag[0])){
if (*(tag+i) == *(popVal+i)){
i++;
}else{
return 0;
}
}
return 1;
}
void dothis(){
int ch;
int n=0;
char *tag = malloc(10* sizeof(char));
char *popVal;
while ((ch = getchar()) != '>'){
tag[n] = ch;
n++;
if (n > (sizeof(tag)/sizeof(tag[0]))-1 ){
reSize(tag);
}
}
if (*tag == '/'){
popVal = malloc(sizeof(tag));
popVal = pop();
j--;
if (!(compare(tag,popVal))){ // Compare will return 1 if the same
printf("Invalid");
exit(1);
}
}else{
push(tag);
j++;
}
free(tag);
free(popVal);
}
int main(int argc, char * argv[])
{
int ch;
while ((ch = getchar()) != EOF) {
if (!(isalpha(ch) || ch == '<'))
continue;
dothis();
}
if (j != 0){
printf("Invalid\n");
exit(1);
}
printf("Valid\n");
exit(0);
}
then the external methods:
#include <stdio.h>
#include <stdlib.h>
static int top = 0;
static char * stack[100];
int isEmpty()
{
return !(top);
}
char * pop()
{
if (isEmpty()){
fprintf(stderr, "Stack is empty");
exit(1);
}
top--;
return (char *) stack[top];
}
void push(char * thing2push)
{
if (top == 100){
fprintf(stderr, "Too many things in the stack");
exit(1);
}else{
stack[top] = thing2push;
top++;
}
}
In a previous question, the selected answer was "passing a pointer to memory you haven't allocated with malloc will definitely not do good things.", but I"m pretty sure I allocated everything
Here's a bug:
popVal = malloc(sizeof(tag));
popVal = pop();
You malloc an area and then immediately lose that value, replacing it with something from pop().
This is most definitely a bug:
while ((ch = getchar()) != '>'){
tag[n] = ch;
n++;
if (n > (sizeof(tag)/sizeof(tag[0]))-1 ){
You assign to tag[n] before checking the range of n. When you do check the range of n after the fact you use sizeof(tag). tag is a pointer. It's size is 4 (32 bit) or 8 (64 bit). Neither size has anything to do with how big n can be before tag[n] writes into invalid memory.
Another bug:
char * pop()
{
if (isEmpty()){
fprintf(stderr, "Stack is empty");
exit(1);
}
top--;
return (char *) stack[top];
}
If you're a beginning C programmer, never cast a pointer. Because I doubt that you have learned enough yet to know if this is a good or bad idea.
The type system exists for good reasons and if it complains about some types not matching, it is far more likely to be right than you are.

Resources