Getting stdin without dropping a line in the terminal - c

I have a multi-threaded application and am trying to format my output in the terminal with escape codes. The only issue I am having is that when gathering input, I cannot place an output mutex around fgets since it will block output until something is input. Consequently, there is this small window where other threads gain access to the output mutex and print before I can erase the newline created by fgets with \b.
Is there a way around this? Or is there a function in C that accepts input without entering a newline after pressing ENTER?
My code for input is as follows:
pthread_mutex_lock(&mutex_stdout);
fflush(stdout);
printf("\33[2K\r");
printf("Accept input: ");
fflush(stdout);
pthread_mutex_unlock(&mutex_stdout);
memset(buffer, 0, BUFFER_SIZE);
fgets(buffer, BUFFER_SIZE, stdin);
pthread_mutex_lock(&mutex_stdout);
buffer[strcspn(buffer, "\r\n")] = 0;
printf("\b");
pthread_mutex_unlock(&mutex_stdout);

Related

EOF key not outputting NULL in C STDIN

I use CLION as my IDE.
I have the following code snippet which is suppose to reverse lines of user input in STDIN.
void reverse(){
char str1[100];
fgets(str1, 100, stdin);
printf("%s", str1);
}
Now when I hit Ctrl+D on my machine it prints out ^Z in STDOUT.
I am trying to make, that fgets() reads each line until the user hits EOF key, how would I do this in C?
I hit Ctrl+D this registers as ^D to stdin
and the printf statement prints out ^Z.

fgets function and file handling in C

I am trying to make a program which will store the data entered by the user in a text file whose name is provided by the user. Program will terminate when the user enters exit. strcmp function of string.h is used for string comparison and fgets() is used to read data from stdin.
Here is my code.
#include<stdio.h>
#include<string.h>
void main()
{
char file[60]; // will store file name
printf("Enter file name: ");
fgets(file, 59, stdin);
FILE *fp = fopen(file, "a+"); // open file in append mode
if(fp == NULL){
printf("File not found !");
return;
}
char data[100];
printf("Enter some data to add to file(exit to terminate): ");
fgets(data, 99, stdin);
int flag = strcmp(data, "exit");
while(flag != 0){
fputs(data, fp);
fgets(data, 59, stdin);
flag = strcmp(data, "exit");
printf("%d\n", flag); // for checking whether string are correctly comapred or not
}
printf("Bye");
}
Program does not terminate even if i enter exit. I have also tried concatenating "\n" at the end of string input by user but that also doesn't help. Although, gets() function works fine, but i know it is not preferred to use to I shifted to fgets() but it doesn't work for me.
Check the man page for fgets(), it reads and stores the newline (caused by pressing ENTER) after the entered input. Thus, the strcmp() fails.
You have to manually strip the input buffer off the newline, before you can compare the input. A simple yet elegant way of doing that would be
data[strcspn(data, "\n")] = 0;
fgets reads in a complete "line", i.e. a sequence of characters until (and including!) a new line character. Hence, when a user presses "Enter", the new line will be part of the string read in and a strcmp(data,"exit") will evaluate to "not equal".
So either strip off the new line before comparison, or compare with a string literal including a new line. Since you write the data as is(i.e. including the new lines) to a file, it seems cumbersome to first strip the new line off and add it then in the output manually. So I'd actually suggest the second approach:
fgets(data, 100, stdin);
flag = strcmp(data, "exit\n");
An alternative would be to use strstr if excess characters do not matter (i.e. your program would exit if the user types "exit" or "asdfexitasdf". - both of which contain "exit".)
So
int flag = strstr(data, "exit");
if(flag != NULL)
//exit the program
else
//stay in the program

When does fgets start reading?

If I were to print a prompt to stdout:
printf("> ");
and then I said
fgets(tester, 80, stdin);
would fgets read the whole line including the "> " or would it start after that?
The prompt is output (on stdout). fgets is reading input from stdin. So no, it won't read your prompt.
Your terminal displays stdout, stderr and stdin all together, but that doesn't mean there isn't an underlying distinction between them.
stdout is typically line buffered, and printf("> "); lacks a new line, so the output may not appear on a terminal display until later. fflush(stdout) to insure it is outputted before the fgets().
printf("> ");
fflush(stdout);
fgets(tester, 80, stdin);
The fgets won't read anything because the printf will write on STDOUT and not on STDIN.
No. printf will reflect the stdout. It will never effects your stdin. The str buffer will reflect all the characters you give as an input after >.
Test for the same can be done like this:
#include<stdio.h>
int main() {
char str[80];
printf(">");
if( fgets (str, 60, stdin)!=NULL )
{
puts(str);
}
return 0;
}

C program display order

When I run the code below, it runs the system command on the 4th last line before displaying the string 'proceeding' before it! I'm wondering why and how to fix it, any ideas?
if ((strlen(command)>0) && (command[strlen (command) - 1] == '\n'))
command[strlen (command) - 1] = '\0';
printf("proceeding"); // <-- the string
strcat(command,contents);
strcat(command,subject);
system(command); // <-- offending system command
sleep (1);
printf("\n ----- Search complete for: [%s]",command);
getchar();
There are of course variables such as 'command' and 'subject' which are manipulated and declared outside the code above, so If you need context than I will post the rest of the source code below.
Pull the chain and flush:
I.e.
After
printf("proceeding");
Put
fflush(stdout);
That will flush the stuff in the buffer (bowl!)
Before the system command is executed.
Try adding a '\n' to the printf.
It forces flushing the printf buffer. Otherwise, it is not necessary that printf immediately prints the passed params. You can google flushing the buffer latter
stdout is line buffered, so it will only display what's in the buffer after it reaches a newline
change printf("proceeding"); to printf("proceeding\n"); or flush stdout with fflush(stdout); will do the work.
The stdio stdout stream is line or fully buffered by default. To set it unbuffered (and to avoid having to write a fflush(stdout) after every output operation), use the ISO C setvbuf function declared in stdio.h:
setvbuf(stdout, (char *)NULL, _IONBF, 0);
once before doing the first I/O.

How to flush the console buffer?

i have some code that run repetedly :
printf("do you want to continue? Y/N: \n");
keepplaying = getchar();
in the next my code is running it doesnt wait for input.
i found out that getchar in the seconed time use '\n' as the charcter.
im gussing this is due to some buffer the sdio has, so it save the last input which was "Y\n" or "N\n".
my Q is, how do i flush the buffer before using the getchar, which will make getchar wait for my answer?
Flushing an input stream causes undefined behaviour.
int fflush(FILE *ostream);
ostream points to an output stream or
an update stream in which the most
recent operation was not input, the
fflush function causes any unwritten
data for that stream to be delivered
to the host environment to be written
to the file; otherwise, the behavior
is undefined.
To properly flush the input stream do something like the following:
int main(void)
{
int ch;
char buf[BUFSIZ];
puts("Flushing input");
while ((ch = getchar()) != '\n' && ch != EOF);
printf ("Enter some text: ");
if (fgets(buf, sizeof(buf), stdin))
{
printf ("You entered: %s", buf);
}
return 0;
}
See Why fflush(stdin) is wrong and Flush the input buffer.
use fflush() and flushall() before printf
As far as I know, flushall is not POSIX. In order to flush a console buffer in a standard way, you can simply use the command:
fflush(NULL);
This topic seems to be a bit old but I hope this can still help the others.

Resources