How to search a specific word in lex given a input file? - lex

I am very new to lex. I am trying to develop a parser to search a count of specific word in an given input file...
My code is
%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int lnum = 1, fresult = 0, cc=0, wc=0, lc=0, bc=0, sc=0, nc=0, tc=0, result;
char temp[20], str[20], fname[20];
FILE *fp;
#undef yywrap
%}
digit[0-9]+
word [a-zA-Z]+
eol [\n]
blank [ ]
tab [\t]
result [word]
%%
{result} {
if((strstr(temp, str)) != 0)
{
printf(" A match found on line: %d\n", lnum);
fresult++;
wc++;
cc+=yyleng;
}
lnum++;
if(fresult == 0)
{
printf(" Match not found\n");
}
}
{digit} {nc++;}
{word} {wc++; cc+=yyleng;}
{tab} {tc++;}
{blank} {bc++;}
{eol} {lc++;}
. sc++;
%%
int main(int argc, char *argv[])
{
strcpy(fname,argv[1]);
strcpy(str,argv[2]);
fp=fopen(fname,"r+");
yyin=fp;
yylex();
printf(" Total count of the word is :%d\n", fresult);
printf(" Character Count = %d\n", cc);
printf(" Number Count = %d\n", nc);
printf(" Word Count = %d\n", wc);
printf(" Line Count = %d\n", lc);
printf(" Special Character Count = %d\n", sc);
printf(" Blank Count = %d\n", bc);
printf(" Tab Count = %d\n", tc);
return(0);
}
int yywrap()
{
return -1;
}
The word count and others are working perfectly.... But the word search is taking the input but not given the specific count...... How can I improve the code?
Should I need to add anything?
Thanks in Advance...... :)

I have made some changes to your code to help you in the right direction. First, I created a variable to keep track of whether a match is found or not.
Secondly, I am not using strstr() anymore and instead I am using strcmp() because you want to match a word to a word not a word within a sentence and we do not need a pointer returned. strcmp() is nice because we just get an integer.
I see what you were trying to do with result [word] however, as you found out, this will not work. This section of the Flex file is known as the rules section. Here you use the regular expressions that you defined in the above section (definitions) to tell Flex what to do when a rule is matched.
As you can see, I have deleted all occurrences of result[word] - as this will not work. In the rules section, I also deleted the result definition because we no longer have a rule to match it. However, I keep the code for the result definitions and simply apply it to the word definition.
The last major change is adding the <<EOF>> rule which is a special rule that tells Flex what to do when it has encountered the end of the file. In our case, if the match variable is not 1, then we have not found a match and we would like to print this to the screen. We also need to call yyterminate() (definition at the bottom of the page) to stop the lexical analyzer.
Below is the updated code. I hope that helps!
%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int lnum = 1, fresult = 0, cc=0, wc=0, lc=0, bc=0, sc=0, nc=0, tc=0, result;
char temp[20], str[20], fname[20];
FILE *fp;
int match = 0;//For keeping track of matches
#undef yywrap
%}
/*Rules*/
digit [0-9]+
word [a-zA-Z]+
eol [\n]
blank [ ]
tab [\t]
/*Definitions*/
%%
{digit} {
nc++;
}
{tab} {
tc++;
}
{blank} {
bc++;
}
{eol} {
lc++;
}
{word} {
if((strcmp(yytext, str)) == 0)//We found a match
{
printf("\n A match found on line: %d\n", lnum);
fresult++;
wc++;
cc+=yyleng;
match = 1;//We have a match
}
else //We found a word, but it was not a match
{
wc++;
}
}
. {
sc++;
}
<<EOF>> {
if(!match)
{
printf(" Match not found\n");
}
yyterminate();
}
%%
int main(int argc, char *argv[])
{
strcpy(fname,argv[1]);
strcpy(str,argv[2]);
fp = fopen(fname,"r+");
yyin = fp;
yylex();
printf("\n\n Total count of the word is :%d\n", fresult);
printf(" Character Count = %d\n", cc);
printf(" Number Count = %d\n", nc);
printf(" Word Count = %d\n", wc);
printf(" Line Count = %d\n", lc);
printf(" Special Character Count = %d\n", sc);
printf(" Blank Count = %d\n", bc);
printf(" Tab Count = %d\n", tc);
fclose(fp);
return(0);
}
int yywrap()
{
return 1;
}

{result} {
if((strstr(temp, str)) != 0)
result [word]
Result is a regex for the characters 'w', 'o', 'r', 'd', which is not what you want. You probably want to match on {word}. In addition, temp will always be null - I think you want to use yytext instead.

Related

How can I solve "lex program for the pattern that starts with vowel, ends with consonant and might have digits too"

I have tried to solve this question "Write a lex program for the pattern that starts with vowel, ends with consonant and might have digits too."
Here is my code:
%{
#include<stdio.h>
#include<string.h>
int cno=0, wno=0, lno=o;
%}
character [a-zA-z]
digit [0-9]
word({character}|{digit})+
line\n
%%
{line}{cno++;lno++;}
{line}{wno++; cno+=strlen(yytext);}{cno++;}
%%
int main(void)
{
yylex();
print("Count alphanumeric pattern: %d;", cno);
print("Length of string: %d;", wno);
print("Line numbers: %d\n", lno);
return 0;
}
Here is the output:
line 23: unrecognized rule
line 23: fatal parse error
I think the following code will solve your problem.
%{
int valid_patterns = 0, invalid_patterns =0;
%}
PATTERN ([aeiouAEIOU][A-Za-z0-9]*[b-df-hj-np-tv-zB-DF-HJ-NP-TV-Z])*
%%
{PATTERN} {printf("\n\t Pattern Matched: %s", yytext); valid_patterns++;}
[A-Za-z0-9]+ {invalid_patterns++;}
"\n" {
printf("\n\n\t Total Matched Patterns : %d", valid_patterns);
printf("\n\t Total Unmatched Patterns: %d\n", invalid_patterns);
valid_patterns = 0; invalid_patterns = 0;
}
%%
/*** User code section***/
int yywrap(){}
int main(int argc, char **argv[])
{
printf("\n Enter your inputs: \n\n");
yylex();
return 0;
}
Explanation of the first rule for PATTERN as per your questions requirements:
[aeiouAEIOU] make sure a pattern starts with a vowel.
[A-Za-z0-9]* indicates that any alphanumeric character can occur in middle.
[b-df-hj-np-tv-zB-DF-HJ-NP-TV-Z] make sure a pattern ends with a consonant.
(...)* indicates there might be 0 or more occurrence of desire pattern.
The second rule [A-Za-z0-9]+ catches any other input that doesn't match the requirements. And the final rule "\n"takes action when you input a new line, it prints information about your inputs.
An I/O example---
Input: Hello amazing people around the world
Output:
Pattern Matched: amazing
Pattern Matched: around
Total Matched Patterns : 2
Total Unmatched Patterns: 4

Trying to count the number of 'a' that are entered

Whenever I try to run the following code to count my characters I constantly get zero instead of the number of characters I have inserted.
#include <stdio.h>
void main() {
int c;
int count = 0;
while ( (c = getchar() != EOF) && c == 'a' ) {
count = count +1;
}
printf("Number of chara: %d", count);
}
I have altered the code to instead only count whenever 'a' comes up, but still only get zero when I enter my characters and hit the return key.
The condition of your while loop evaluates to false when the program reads a character that isn't an 'a', which ends the while loop. Since your program reads characters in the while loop, no more characters get read.
Try checking if the character is an 'a' inside the loop body before updating the counter instead of in the loop condition.
The loop will stop because you set the c=='a'. Try to remove that in your code.
Try this one:
int c;
int count = 0;
while (c = getchar() != EOF ) {
count = count +1;
}
printf("Number of chara: %d", count);
}`

Fread/fwrite unexpected behavior

I have created a file 'meta.dat' in my current directory and want the code below to give me this output
The character B
Number of items read 1
int main() {
FILE* fp = fopen("meta.dat", "wb");
char j = 'B';
fwrite(&j, sizeof(j), 1, fp);
fclose(fp);
FILE* fp1 = fopen("meta.dat", "rb");
char i = '\0';
int n = fread(&i, sizeof(i), 1, fp1);
printf("The character %c\n", &i);
printf("Number of items read %d\n", &n);
}
However what I get is this output in my console (I use Windows):
The character &
Number of items read 6422304
What's wrong with the code? And what's happening behind the scenes, why am I seeing this strange output?

strncpy functions produces wrong file names

I am new in C and writing a code to help my data analysis. Part of it opens predetermined files.
This piece of code is giving me problems and I cannot understand why.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLOGGERS 26
// Declare the input files
char inputfile[];
char inputfile_hum[MAXLOGGERS][8];
// Declare the output files
char newfile[];
char newfile_hum[MAXLOGGERS][8];
int main()
{
int n = 2;
while (n > MAXLOGGERS)
{
printf("n error, n must be < %d: ", MAXLOGGERS);
scanf("%d", &n);
}
// Initialize the input and output file names
strncpy(inputfile_hum[1], "Ahum.csv", 8);
strncpy(inputfile_hum[2], "Bhum.csv", 8);
strncpy(newfile_hum[1], "Ahum.txt", 8);
strncpy(newfile_hum[2], "Bhum.txt", 8);
for (int i = 1; i < n + 1; i++)
{
strncpy(inputfile, inputfile_hum[i], 8);
FILE* file1 = fopen(inputfile, "r");
// Safety check
while (file1 == NULL)
{
printf("\nError: %s == NULL\n", inputfile);
printf("\nPress enter to exit:");
getchar();
return 0;
}
strncpy(newfile, newfile_hum[i], 8);
FILE* file2 = fopen(newfile, "w");
// Safety check
if (file2 == NULL)
{
printf("Error: file2 == NULL\n");
getchar();
return 0;
}
for (int c = fgetc(file1); c != EOF; c = fgetc(file1))
{
fprintf(file2, "%c", c);
}
fclose(file1);
fclose(file2);
}
// system("Ahum.txt");
// system("Bhum.txt");
}
This code produces two files but instead of the names:
Ahum.txt
Bhum.txt
the files are named:
Ahum.txtv
Bhum.txtv
The reason I am using strncpy in the for loop is because n will actually be inputted by the user later.
I see at least three problems here.
The first problem is that your character array is too small for your strings.
"ahum.txt", etc. will need to take nine characters. Eight for the actual text plus one more for the null terminating character.
The second problem is that you have declared the character arrays "newfile" and "inputfile" as empty arrays. These also need to be a number able to contain the strings (at least 9).
You're lucky to have not had a crash from overwriting memory out the program space.
The third and final problem is your use of strcpy().
strncpy(dest, src, n) will copy n characters from src to dest, but it won't copy final null terminator character if n is equal or less than size of the src string.
From strncpy() manpage: https://linux.die.net/man/3/strncpy
The strncpy() function ... at most n bytes of src are copied.
Warning: If there is no null byte among the first n bytes of src,
the string placed in dest will not be null-terminated.
Normally what you would want to do is have "n" be the size of the destination buffer minus 1 to allow for the null character.
For example:
strncpy(dest, src, sizeof(dest) - 1); // assuming dest is char array
There are a couple of problems with your code.
inputfile_hum, newfile_hum, need to be to be one char bigger for the trailing '\0' on strings.
char inputfile_hum[MAXLOGGERS][9];
...
char newfile_hum[MAXLOGGERS][9];
strncpy expects the first argument to be a char * region big enough to hold the expected results, so inputfile[] and outputfile[] need to be declared:
char inputfile[9];
char outputfile[9];

How to let fscanf stop reading after a new line

#include <stdio.h>
#define MAX 1000
int line_counter (FILE *file, char buf[]);
int main(int argc, char *argv[]) {
FILE *ptr_file;
char buf[MAX];
ptr_file = fopen("alice-eg.txt", "r");
if (!ptr_file) {
return 1;
}
int count = 0;
while (fscanf(ptr_file, "%s", buf) == 1) {
printf("%s", buf);
if (buf == '\n') {
return count;
}
else {
count += 1;
}
}
printf("The number of words in this line is: %d", count);
return 0;
}
I want to do something along the lines of this but I have no idea how to make it work as the buf is just a pointer to an array of letters (correct me if I'm wrong I just started with C and my understanding of pointers is still quite bad).
fscanf write the line from the file (separated by ENTER) to the buff array and so if it will read an empty line buff[0] = '\n' so that should be your condition.
Secondly:
while (fscanf(ptr_file, "%s", buf) == 1)
Is wrong since fscanf returns the number of read character and so for the line "abcd" form the file it will return 4 and your loop will stop right away instead of reading the entire file and so your condition should be:
while (fscanf(ptr_file, "%s", buf) != EOF)
since fscanf will return EOF when it will reach the end of the file