I have 2 fgets into my code and both of them aren't wait for input...
This is an example of the first fgets...
printf("Insert path: ");
if(fgets(dirpath, BUFFGETS, stdin) == NULL){
perror("fgets dir path");
close(sockd);
}
and, as i've written before, also the next fgets is not waiting for my input :(
Before the first fgets i have 2 scanf("%ms", &string); (if this could be the trouble).
i think scanf does not read in the linebreak. You can try to read it in first with an additional fgets after scanf().
Related
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
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);
I'm currently practicing File I/O in C. I created a program where I get a file and extract data from it and I would like an option to change the file that is being read. The problem that I'm encountering is that for example I have two files: sample1.txt and sample2.txt. If I chose sample1.txt as the first file to be read and then I wanted to change the file to sample2.txt what ends up happening is that the filename does not change to sample2.txt but instead always stays what ever filename the first file has.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <assert.h>
#include <time.h>
#include <ctype.h>
int main()
{
char file_location[100]={0};
char new_location[100]={0};
FILE* fPointer=NULL;
int choice;
printf("Enter the filename that you wish to open.\n");
scanf("%[^\n]s",file_location); // I enter sample1.txt//
printf("%s\n",file_location);
fPointer=fopen(file_location,"r"); // success,sample1.txt is currently being read.//
if (fPointer==NULL)
{
printf("File error!,invalid file name! program will now exit.\n");
exit(0);
}
else
{
printf("Success!\n");
}
printf("Do you want to change the file being read\n); //Now I want to change the file,from sample1.txt to sample2.txt//
prinft("Enter 1 to change, 0 to exit the program\n);
do{
scanf("%d",&choice);
printf("You entered %d\n",choice);
if(choice<0||choice>1)
{
printf("Error,please choose between 1 and 0\n");
}
}while(choice!=1||choice!=0);
switch(choice) // I enter 1,go to case1//
{
case 0:
printf("Exiting program now\n");
exit(0);
break;
case 1:
fclose(fPointer);
printf("Enter the filename that you wish to open.\n");
scanf("%[^\n]s",new_location); //scanf does not even prompt me to enter a string.//
printf("%s\n",new_location); //nothing prints//
fPointer=fopen(new_location,"r"); // fpointer still points to sample1.txt//
break;
}
return 0;
}
Could anyone explain to me why my code keeps failing?
Any constructive criticism ,notes about File I/O is appreciated.
The fundamental problem is that your code mishandles newlines. This method of obtaining input probably does not do what you think it does:
scanf("%[^\n]s",new_location);
First, there is no reason for the trailing s here. Second, this will leave a trailing newline behind in the input stream. This newline is ignored when you call scanf("%d",&choice);, since the %d conversion specifier skips over leading whitespace characters. But, this second call to scanf() also leaves a newline character behind, and this is not ignored by the final call to scanf(), since %[^\n] tells scanf() to read characters until a newline is encountered.
One fix is to simply remove the scanset from your scanf() statements:
scanf("%s", new_location);
This will ignore leading whitespace characters, so the newline left behind from the previous call to scanf() will be ignored.
Also, when you open the new file, you are using file_location instead of new_location.
You will need to change your do loop condition to:
while(choice != 1 && choice != 0);
since you want to repeat the loop only if the user enters a number that is both not 0 and not 1.
If you want to read lines that include spaces, which is what [^\n] is sometimes used for, a better alternative is to use fgets(). This function keeps the newline, so you will need to remove it from the filenames. Also, if you are using fgets() to get the strings, it is best to use fgets() to get the numeric input, by reading the user input into a buffer and using sscanf() to parse it. Then your input code would look like:
/* Get first filename, and remove the newline */
printf("Enter the filename that you wish to open.\n");
fgets(file_location, sizeof file_location, stdin);
file_location[strcspn(file_location, "\r\n")] = '\0'; // remove newline
...
/* Get numeric input; this keeps the newline, so it does not interfere
* with the next call to `fgets()` */
char buffer[100];
fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, "%d", &choice);
...
/* Get the new filename, and remove the newline */
printf("Enter the filename that you wish to open.\n");
fgets(new_location, sizeof new_location, stdin);
new_location[strcspn(new_location, "\r\n")] = '\0'; // remove newline
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;
}
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.