I was working on a homework problem when I encounter this error, fflush inside main function in main.c is not working
I tried the code in ubuntu local system and in repl.it and the output does not contain "#include" line from sample.c , The only line "preprocessor " is printed in terminal..
Files used:
main.c
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
char token[1024];
int toksize = 0;
int breaker = 0;
int is_normal(char ch) {
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
|| ch == '_' || (ch >= '0' && ch <= '9'))
return 1;
return 0;
}
int Tokenizer(FILE * file_ptr) {
char ch;
toksize = 0;
ch = 'a';
while (is_normal(ch) == 1 && ch != EOF) {
ch = fgetc(file_ptr);
if (ch == EOF) break;
if (toksize > 0 && !is_normal(ch)) break;
token[toksize] = ch;
toksize++;
token[toksize] = '\0';
}
if (ch == EOF)
breaker = 1;
if (toksize > 1 || is_normal(token[0]))
fseek(file_ptr, -1L, SEEK_CUR);
// fflush(stdin);
// fflush(stdout);
return 1;
}
int main() {
fprintf(stderr, "ji");
int flag = 0;
FILE * fd = fopen("sample.c", "r");
breaker = 0;
if (fd == NULL) {
printf("file not found!!");
return 0;
}
while (breaker == 0 && Tokenizer(fd) > 0) {
int stage = 0;
if (token[0] == '#') { // handling preprocessor
while (token[0] != '\n') {
printf("%s", token);
if (Tokenizer(fd) == 0) {
breaker = 1;
break;
}
}
fflush(stdout);
printf(" -- preprocessor directive\n");
}
}
}
sample.c
#include<stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct stack {
int tos;
char arr[21];
} stack;
void push(stack*, char);
char pop(stack*);
void convert(char[], char[]);
int isoperand(char);
int precd(char, char);
int isempty(stack);
int main()
{
char infix[21];
char prefix[21];
printf("Enter the character in infix expression:\n");
scanf("%s", infix);
convert(infix, prefix);
printf("%s", prefix);
}
int isempty(stack s)
{
return s.tos == -1;
}
void push(stack *p, char ch)
{
if (p->tos == 19)
{
printf("Stack overflow");
}
p->arr[++(p->tos)] = ch;
}
char pop(stack *p)
{
if (p->tos == -1)
{
printf("Stack underflow");
return '\0';
}
return p->arr[(p->tos)--];
}
int isoperand(char ch)
{
return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'));
}
int precd(char op1, char op2) /*I think in this function something is wrong but I am unable to trace it.*/
{
if (op1 == op2)
return 1;
else if (op2 == '$')
return 0;
else if (op1 == '$')
return 1;
else if ((op2 == '*' || op2 == '%' || op2 == '/') &&(op1 != '*' || op1 != '%' || op1 != '/'))
return 0;
else if ((op1 == '*' || op1 == '%' || op1 == '/') &&(op2 != '*' || op2 != '%' || op2 != '/'))
return 1;
else if ((op2 == '-' || op2 == '+') && (op1 != '-' || op1 != '+'))
return 0;
else
return 1;
}
void convert(char infix[], char prefix[])
{
int i, j = 0;
stack s;
s.tos = -1;
int r;
for (i = (strlen(infix) - 1); i >= 0; i--)
{
if (isoperand(infix[i]) == 1)
{
prefix[j] = infix[i];
j++;
}
else
{
while (isempty(s) == 0)
{
r = precd(infix[i], s.arr[s.tos]);
if (r == 0)
{
prefix[j] = pop(&s);
j++;
}
else
break;
}
push(&s, infix[i]);
}
}
while (isempty(s) == 0)
{
prefix[j] = pop(&s);
j++;
}
prefix[j] = '\0';
strrev(prefix);
}
I think I have written something wrong in the precd(char, char) function if else if else condition which checks the precedence but I am unable to trace it. Also I think the problem is in the comparison of '-' operator with '+' operator you can also see other functions if they have any bug I have also added comment in the function to highlight it.
I am stuck here, please help.
I'm trying to read tokens from a file and want to show them in the terminal. I'm doing this multiple steps, I've created a c program that can detect tokens. But it's harder for me to read tokens from a text file and show it to the terminal that which is operator, integer, keywords, or identifier. Can anyone help me to do it please?
Here is the identifier.c file:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// Returns 'true' if the character is a DELIMITER.
bool isDelimiter(char ch)
{
if (ch == ' ' || ch == '+' || ch == '-' || ch == '*' ||
ch == '/' || ch == ',' || ch == ';' || ch == '>' ||
ch == '<' || ch == '=' || ch == '(' || ch == ')' ||
ch == '[' || ch == ']' || ch == '{' || ch == '}')
return (true);
return (false);
}
// Returns 'true' if the character is an OPERATOR.
bool isOperator(char ch)
{
if (ch == '+' || ch == '-' || ch == '*' ||
ch == '/' || ch == '>' || ch == '<' ||
ch == '=')
return (true);
return (false);
}
// Returns 'true' if the string is a VALID IDENTIFIER.
bool validIdentifier(char* str)
{
if (str[0] == '0' || str[0] == '1' || str[0] == '2' ||
str[0] == '3' || str[0] == '4' || str[0] == '5' ||
str[0] == '6' || str[0] == '7' || str[0] == '8' ||
str[0] == '9' || isDelimiter(str[0]) == true)
return (false);
return (true);
}
// Returns 'true' if the string is a KEYWORD.
bool isKeyword(char* str)
{
if (!strcmp(str, "if") || !strcmp(str, "else") ||
!strcmp(str, "while") || !strcmp(str, "do") ||
!strcmp(str, "break") ||
!strcmp(str, "continue") || !strcmp(str, "int")
|| !strcmp(str, "double") || !strcmp(str, "float")
|| !strcmp(str, "return") || !strcmp(str, "char")
|| !strcmp(str, "case") || !strcmp(str, "char")
|| !strcmp(str, "sizeof") || !strcmp(str, "long")
|| !strcmp(str, "short") || !strcmp(str, "typedef")
|| !strcmp(str, "switch") || !strcmp(str, "unsigned")
|| !strcmp(str, "void") || !strcmp(str, "static")
|| !strcmp(str, "struct") || !strcmp(str, "goto"))
return (true);
return (false);
}
// Returns 'true' if the string is an INTEGER.
bool isInteger(char* str)
{
int i, len = strlen(str);
if (len == 0)
return (false);
for (i = 0; i < len; i++) {
if (str[i] != '0' && str[i] != '1' && str[i] != '2'
&& str[i] != '3' && str[i] != '4' && str[i] != '5'
&& str[i] != '6' && str[i] != '7' && str[i] != '8'
&& str[i] != '9' || (str[i] == '-' && i > 0))
return (false);
}
return (true);
}
// Returns 'true' if the string is a REAL NUMBER.
bool isRealNumber(char* str)
{
int i, len = strlen(str);
bool hasDecimal = false;
if (len == 0)
return (false);
for (i = 0; i < len; i++) {
if (str[i] != '0' && str[i] != '1' && str[i] != '2'
&& str[i] != '3' && str[i] != '4' && str[i] != '5'
&& str[i] != '6' && str[i] != '7' && str[i] != '8'
&& str[i] != '9' && str[i] != '.' ||
(str[i] == '-' && i > 0))
return (false);
if (str[i] == '.')
hasDecimal = true;
}
return (hasDecimal);
}
// Extracts the SUBSTRING.
char* subString(char* str, int left, int right)
{
int i;
char* subStr = (char*)malloc(
sizeof(char) * (right - left + 2));
for (i = left; i <= right; i++)
subStr[i - left] = str[i];
subStr[right - left + 1] = '\0';
return (subStr);
}
// Parsing the input STRING.
void parse(char* str)
{
int left = 0, right = 0;
int len = strlen(str);
while (right <= len && left <= right) {
if (isDelimiter(str[right]) == false)
right++;
if (isDelimiter(str[right]) == true && left == right) {
if (isOperator(str[right]) == true)
printf("'%c' IS AN OPERATOR\n", str[right]);
right++;
left = right;
} else if (isDelimiter(str[right]) == true && left != right
|| (right == len && left != right)) {
char* subStr = subString(str, left, right - 1);
if (isKeyword(subStr) == true)
printf("'%s' IS A KEYWORD\n", subStr);
else if (isInteger(subStr) == true)
printf("'%s' IS AN INTEGER\n", subStr);
else if (isRealNumber(subStr) == true)
printf("'%s' IS A REAL NUMBER\n", subStr);
else if (validIdentifier(subStr) == true
&& isDelimiter(str[right - 1]) == false)
printf("'%s' IS A VALID IDENTIFIER\n", subStr);
else if (validIdentifier(subStr) == false
&& isDelimiter(str[right - 1]) == false)
printf("'%s' IS NOT A VALID IDENTIFIER\n", subStr);
left = right;
}
}
return;
}
// DRIVER FUNCTION
int main()
{
// maximum legth of string is 100 here
char str[100] = "int a = b + 1c; ";
parse(str); // calling the parse function
return (0);
}
Here is the token.txt file that I need to read from and show it to the terminal:
1) Keywords:
for, while, if
2) Identifier
total, sum, average, a, b, c
3) Operators:
'+', '++', '-' etc.
4) Separators:
', ' ';' etc
5) Integers:
1, 2, 3, 5, 6, 7, 8, 9
File IO in C can be done in two ways, buffered and unbuffered. Buffered IO wraps around the FILE type and the f... functions like fopen, fread, fscanf, fclose and so on.
Unbuffered IO is done via open, read, write and close functions.
Typically you'd rather rely on the buffered variant, so showing about that one:
FILE* in = fopen(path_to_file, "r");
// ^ open file for reading
if(!in)
{
// opening file was not successful
// TODO: appropriate error handling like printing an error message
}
else
{
char buffer[128];
size_t num;
while((num = fread(buffer, sizeof(buffer), sizeof(*buffer), in)) > 0)
{
// use buffer up to buffer[num]
}
// if you are interested if an error occurred or just the end of file
// has been read, you can now check e. g. via
if(!feof(in))
{
// error handling
}
fclose(in);
}
More complex file handling might include moving partially read tokens at the end of the buffer towards its front and filling the buffer from there on:
char buffer[128];
size_t offset = 0, num;
while((num = fread(buffer + offset, sizeof(buffer) - offset, sizeof(*buffer), in)) > 0)
{
// you discover e. g. n non-delimiter bytes at the end possibly not being
// a complete token at position pos
memmove(buffer, buffer + pos, n);
offset = n;
}
I need to calculate the size of a string in order to apply a function (the function applied is going to depend on the size of valor.)
However, as you can see in this example, I am having some trouble using strlen in the string (in the example you can see I inserted 2 'valor' and the given strlen was 6).
Here is the code, and next to it an image of the process returned.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char valor[5];
char naipe[5];
int c;
int i = 0;
do {
c = getchar();
if (((c > '0') && (c < '9')) || (c == 'K') || (c == 'Q') || (c == 'J') ||
(c == 'A') || (c == 'T')) {
valor[i] = c;
continue;
}
if ((c > 'A') && (c < 'Z')) {
naipe[i] = c;
i++;
}
} while (c != '\n');
printf("%ld", strlen(valor));
return 0;
}
you have two arrays and you should use two counters for them ,otherwise you would probably skip some elements of each arrays.
also you should terminate char valor[5] and char naipe[5] with '\0'.
int main() {
char valor[5];
char naipe[5];
int c;
int i = 0,j=0;
do {
c = getchar();
if (((c > '0') && (c < '9')) || (c == 'K') || (c == 'Q') || (c == 'J') ||
(c == 'A') || (c == 'T')) {
valor[j] = c;
j++;
continue;
}
if ((c > 'A') && (c < 'Z')) {
naipe[i] = c;
i++;
}
} while (c != '\n');
valor[j] = '\0';//terminate first then print.
printf("%ld", strlen(valor));
naipe[i] = '\0';
return 0;
}
In my main function I am using letter(ch). I am trying to get some letter characters to become a string or token. Before using the append function it would just print all the characters out.
//output
000: u
001: s
002: e
003: .
004: s
005: y
006: s
007: t
008: e
009: m
010: .
011: i
012: o
013: ;
I found an appending function that gets the letter characters into the array, but it prints out like a pyramid. How do I get the last result when it's done appending, and use the '\0' to split it? Shouldn't it have already split it by the initial '\0' in the append function? Am I approaching this in the right direction? Is there something I'm missing in order for the split after the null?
//output
000: u
001: us
002: use
003: .
004: uses
005: usesy
006: usesys
007: usesyst
008: usesyste
009: usesystem
010: .
011: usesystemi
012: usesystemio
013: ;
//main.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include "ch_type.h"
FILE *file;
char line[400];
int line_num;
char ch;
void append(char* line, char ch)
{
int length = strlen(line);
line[length] = ch;
line[length + 1] = '\0';
}
int main()
{
file = fopen("source.txt", "r");
while((ch = fgetc(file)) != EOF)
{
if(space(ch))
{
printf(" %03d: %c\n", line_num++, ch);
}
if(letter(ch))
{
append(line, ch);
printf(" %03d: %s\n", line_num++, line);
}
if(separator(ch))
{
printf(" %03d: %c\n", line_num++, ch);
}
}
return 0;
}
//ch_type.h
int space(int ch)
{
return ((ch == ' '));
}
int letter(int ch)
{
return (((ch >= 'a') && (ch <= 'z')) || (ch >= 'A') && (ch <= 'Z'));
}
int separator(int ch)
{
return ((ch == '#') || (ch == '(') || (ch == ')') || (ch == '{') || (ch == '}') || (ch == '[') || (ch == ']')
|| (ch == '<') || (ch == '>') || (ch == '.') || (ch == ',') || (ch == ':') || (ch == ';'));
}
Print line when you enter if(space(ch)) or if(separator(ch)) instead of after finding each character of a line. After that, set the first byte to 0 so the string is "empty" again:
if(space(ch))
{
printf(" %03d: %s\n", line_num++, line);
line[0] = '\0';
printf(" %03d: %c\n", line_num++, ch);
}
if(letter(ch))
{
append(line, ch);
}
if(separator(ch))
{
printf(" %03d: %s\n", line_num++, line);
line[0] = '\0';
printf(" %03d: %c\n", line_num++, ch);
}
You should probably also prepend else to both if(letter(ch)) and if(separator(ch)). This might improve performance a little since none of these conditions overlap.
Note that this is assuming that separators and spaces don't go together, but that shouldn't necessarily matter.
Here is a simplified version of this that doesn't require duplicated code:
if(letter(ch))
{
append(line, ch);
}
else
{
printf(" %03d: %s\n", line_num++, line);
line[0] = '\0';
}
if(space(ch) || separator(ch))
{
printf(" %03d: %c\n", line_num++, ch);
}