Why does this BNF checker fail when checking specific grammar? - c

I am trying different scenarios to check the syntax of BNF grammar but when I have input 0 1 0 ; 0 I am getting an output of yes instead of no. The BNF grammar is A ::= 0 B and B ::= 1 A | 2 B | ; Would another else if statement fix this issue? Below is the code I have written so far. Any help resolving this or understanding how to resolve it is much appreciated.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void A(), B();
// input token
char tok[10];
// return the next token from standard input as a string,
// or return NULL if there is no more input
char *lexan() {
int n;
n = scanf("%s", tok);
if (n == EOF) {
return NULL;
}
return tok;
}
// print an error message and exit
void error(char* msg) {
printf("%s\n", msg);
exit(1);
}
// return if the standard input follows the syntax for A,
// else print an error message and exit
void A() {
char *lookahead;
lookahead = lexan();
if (lookahead == NULL) {
error("no");
}
else if (strcmp(lookahead, "0") == 0) {
B();
}
else error("no");
}
// return if the standard input follows the syntax for B,
// else print an error message and exit
void B() {
char *lookahead;
lookahead = lexan();
if (lookahead == NULL) {
error("no\n");
}
else if (strcmp(lookahead, "1") == 0) {
A();
}
else if (strcmp(lookahead, "2") == 0) {
B();
}
else if (strcmp(lookahead, ";") == 0) {
printf("yes\n");
}
else error("no\n");
exit (1);
}
int main() {
A();
// the input should be one A only
if (lexan() != NULL) {
error("no");
}
printf("yes\n");
}

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.

Comparison between pointers and integers in 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 '{'.

C: Strings, segmentation error

The following piece of code is scanning for command line arguments for valid sentences that contains the words 'Int' or 'Float'.
I have debugged it for hours trying to locate where the error is occurring to no avail.
Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
bool process_input(int, char *[]);
bool first_word_correct(char *);
void print_string(char *);
int main(int argc, char *argv[]) {
if (!process_input(argc, argv))
printf("Incorrect input.\n");
else
printf("CORRECT input.\n");
return EXIT_SUCCESS;
}
bool process_input(int argc, char *argv[]) {
char *word;
int i, j;
bool is_new_sentence = true;
i = 0;
j = 0;
while (++i < argc) {
// check the first word - must be "A" or "An"
if (is_new_sentence) {
if (!first_word_correct(argv[i])) {
return false;
}
is_new_sentence = false;
}
// we're checking subsequent words of the same sentence
else if (!is_new_sentence) {
// is this the last word?
strcpy(word, argv[i]);
if (word[strlen(word) - 1] == '.') {
is_new_sentence = true;
}
switch(is_variable_name(word)) {
case 1:
printf("int found!\n");
break;
case 2:
printf("float found!\n");
break;
}
}
}
return true;
}
bool first_word_correct(char *word) {
if (strcmp(word, "A") == 0 || strcmp(word, "An") == 0) {
return true;
}
else {
return false;
}
}
/*
*int 1
*float 2
*/
int is_variable_name(char *word) {
if ((strcmp(word, "int") == 0) || (strcmp(word, "int.") == 0))
return 1;
if ((strcmp(word, "float") == 0) || (strcmp(word, "float.") == 0))
return 2;
return -1;
}
You are not allocated memory for word before using it. Try like
else if (!is_new_sentence) {
// is this the last word?
word=malloc(100);// size is based on your argv[i]
strcpy(word, argv[i]);
if (word[strlen(word) - 1] == '.') {
is_new_sentence = true;
}

What's the best choice of data structure to solve Timus Nr#1027?

Could anybody tell me what's the best choice of data structure to solve the problem # http://acm.timus.ru/problem.aspx?space=1&num=1027.
Copied here for reference.
Problem
A text of a correct D++ program contains a symbol part, arithmetic
expressions and comments. Comments may appear everywhere and may
contain any symbols. A comment is always opened by a pair of symbols
(* and is closed by a pair of symbols * ) Each comment must be
closed. An arithmetic expression in D++ is always opened by "(", is
closed by ")" and may contain only symbols "=+-/0123456789)(" and
"end of line" symbols. An arithmetic expression can't start with a
pair of symbols "(". You may run across embedded brackets in an
arithmetic expression. In this case these brackets are to be balanced.
It means that "((1)))" as well as "(23))((+)" are not correct
arithmetic expressions. An arithmetic expression is correct if and
only if brackets placed correctly. At last, all the rest of the
program text (the result of rejection of all comments and arithmetic
expressions from the initial text of the program) may contain every
symbol excluding "(" and ")". We would like to especially notice that
the spaces are possible anywhere in a text of a program except when
appearing in arithmetic expressions.
Would hashing be useful ?
My approach is as below(there are still some bugs,concentrate on the DS part)
#include <stdio.h>
/* enable to get debug print statements */
#define DEBUG_ENABLE 0
#define INSUFFICIENT_BUFFER -1
#define BUFSIZE 20
char buf[BUFSIZE];/*buffer for ungetch*/
int bufp=0;/*next free position in buf*/
/*get a(possibly pushed-back)character*/
int mygetch(FILE *infile)
{
return(bufp>0)? (buf[--bufp]): (getc(infile));
}
/*push a character back on input*/
int ungetch(char c)
{
if(bufp >= BUFSIZE)
{
printf("ungetch:too many characters - increase the stack buffer size\n");
return INSUFFICIENT_BUFFER;
}
else
{
buf[bufp++]=c;
return 0;
}
}
enum CharType
{
isAlphabet=0,
isNumber,
isSpace,
isNewline,
isOperator,
isOpeningBrace,
isClosingBrace,
isStar,
isOther
};
enum
{
False=0,
True
};
/* return different codes for different types of input characters*/
int getCharType(char ch)
{
if((ch>='A'&&ch<='Z') || (ch>='a'&&ch<='z'))
{
return isAlphabet;
}
else if(ch=='+'||ch=='-'||ch=='/'||ch=='=')
{
return isOperator;
}
else if(ch>='0'&& ch<='9')
{
return isNumber;
}
else if(ch=='*')
{
return isStar;
}
else if(ch=='(')
{
return isOpeningBrace;
}
else if(ch==')')
{
return isClosingBrace;
}
else if(ch==' ')
{
return isSpace;
}
else
{
return isOther;
}
}
int parseInputFile(FILE *infile)
{
int ArthExpScanning = 0;
int CmmntScanning = False;
int ch,chtmp;
while((ch=mygetch(infile))!=EOF)
{
#if DEBUG_ENABLE
printf("%c",ch);
#endif /*DEBUG_ENABLE*/
switch(getCharType(ch))
{
/*Arithmetic Expression or possibly comment starts here*/
case isOpeningBrace :
if((chtmp=mygetch(infile))!=EOF)
{
if(getCharType(chtmp)== isStar)
{
CmmntScanning = True;
#if DEBUG_ENABLE
printf("\nCmmnt Scanning = True\n");
#endif /*DEBUG_ENABLE*/
}
else if (CmmntScanning == False)
{
ArthExpScanning += 1;
#if DEBUG_ENABLE
printf("\nArthExpScanning = %d\n",ArthExpScanning);
#endif /*DEBUG_ENABLE*/
if(ungetch(chtmp) == INSUFFICIENT_BUFFER)
{
return (0);
}
}
}
break;
/*Arithmetic Expression possibly closes here */
case isClosingBrace :
if(CmmntScanning == False)
{
ArthExpScanning -= 1;
#if DEBUG_ENABLE
printf("\nArthExpScanning = %d\n",ArthExpScanning);
#endif /*DEBUG_ENABLE*/
}
#if DEBUG_ENABLE
if(ArthExpScanning < 0)
{
printf("\nerror here!!\n");
}
#endif /*DEBUG_ENABLE*/
break;
case isStar :
if((chtmp=mygetch(infile))!=EOF)
{
if((getCharType(chtmp)== isClosingBrace) && (CmmntScanning == True))
{
CmmntScanning = False;
#if DEBUG_ENABLE
printf("\nCmmnt Scanning = False\n");
#endif /*DEBUG_ENABLE*/
}
else
{
if(ungetch(chtmp) == INSUFFICIENT_BUFFER)
{
return (0);
}
}
}
break;
case isSpace :
if((CmmntScanning == False) && (ArthExpScanning != 0))
{
/* Space not allowed while scanning arith exp */
#if DEBUG_ENABLE
printf("NO \n");
#endif /*DEBUG_ENABLE*/
return 0;
}
break;
case isAlphabet :
case isOperator :
case isNumber :
case isNewline :
default:
break;
}
}
if((ArthExpScanning == 0) && (CmmntScanning == False))
{
/* if there are no open braces and comments left after parsing the entire
file return success*/
return 1;
}
else
{
return 0;
}
}
int main(int argc,char *argv[])
{
FILE *infile;
if(argc != 2)
{
printf("Correct usage is : D++ExpParser inputfilename\n");
return (-1);
}
if((infile = fopen(argv[1],"r")) == NULL )
{
printf("Not able to open file : %f\n",argv[1]);
return (-2);
}
if(parseInputFile(infile))
{
printf("YES\n");
}
else
{
printf("NO\n");
}
fclose(infile);
}
Hashing? No. Hint for your web search: this is a context-free grammar.

Resources