stopping scanf on pressing enter - c

I am writing a C program which takes string input and print each word in a separate line. But the program is not stopping even after pressing enter. Please suggest a solution.
#include<stdio.h>
#include<string.h>
int main(void)
{
char str[50];
while(scanf("%s",str)&&strcmp(str,"\n"))
printf("%s\n",str);
}

You need to use fgets to read the line and if the input is just a single character which is newline character then break else keep continuing.
while(fgets(str,sizeof(str),stdin))
{
if(strcmp(str,"\n") == 0)
break;
else
{
size_t n = strlen(str);
if(n>0 && str[n-1] == '\n')
str[n-1] = '\0';
printf("%s\n",str);
}
}
PS: fgets() comes with a newline character and we need to supress the newline character as shown above.

Related

Is there an elegant way to handle the '\n' that gets read by input functions (getchar(), fgets(), scanf()) in C?

I am trying a simple exercise from K&R to append string2 at the end of string1 using pointers. In case of overflow i.e. buffer of string1 can't contain all of string2 I want to prompt the user to re-enter string2 or exit.
I have written the following code:
#include<stdio.h>
#include<string.h>
#define MAXLINE 1000
int get_input(char *s);
int str_cat(char *s, char *t);
void main()
{
char input1[MAXLINE], input2[MAXLINE], c;
get_input(input1);
check:
get_input(input2);
if((strlen(input1) + strlen(input2) + 2) <= MAXLINE)
{
str_cat(input1, input2);
printf("%s\n", input1);
}
else
{
input2[0] = '\0';
printf("String overflow\n Press: \n 1: Re-enter string. \n 2: Exit.\n");
scanf(" %d", &c);
if(c == 1){
input2[0] = '\0';
get_input(input2);
goto check;
}
}
}
int get_input(char *arr)
{
int c;
printf("Enter the string: \n");
while(fgets(arr, MAXLINE, stdin))
{
break;
}
}
int str_cat(char *s, char *t)
{
while(*s != '\0')
{
s++;
}
while((*s++ = *t++) != '\0')
{
;
}
*s = '\0';
}
Initially, I was using the standard getchar() function mentioned in the book to read the input in get_input() which looked like this:
int get_input(char *arr)
{
int c;
printf("Enter the string: \n");
while((c = getchar()) != '\n' && c != EOF)
{
*arr++ = c;
}
*arr = '\0';
}
I am new and I read this and understood my mistake. I understand that one isn't supposed to use different input functions to read stdin and the '\n' is left in the input stream which is picked by the getchar() causing my condition to fail.
So, I decided to use fgets() to read the input and modified the scanf("%d", &c) as mentioned in the thread with scanf(" %d", c). This does work (kinda) but gives rise to behaviors that I do not want.
So, I have a few questions:
What's a better way to fgets() from reading the input on encountering '\n' than the one I have used?
while(fgets(arr, MAXLINE, stdin))
{
break;
}
fgets() stops reading the line and stores it as an input once it either encounters a '\n' or EOF. But, it ends up storing the '\n' at the end of the string. Is there a way to prevent this or do I have to over-write the '\n' manually?
Even though I used the modified version of scanf(" %d", &c), my output looks like
this: (https://imgur.com/a/RaC2Kc6). Despite that I get Enter the string: twice when prompted to re-enter the second string in case of an overflow situation. Is the modified scanf() messing with my input? And how do I correct it?
In general, do not mix fgets with scanf. Although it may be a bit bloaty, you will avoid many problems by being consistent with reading input with fgets and then parse it with sscanf. (Note the extra s)
A good way to remove the newline is buffer[strcspn(buffer, "\n")] = 0
Example:
// Read line and handle error if it occurs
if(!fgets(buffer, buffersize, stdin)) {
// Handle error
}
// Remove newline (if you want, not necessarily something you need)
buffer[strcspn(buffer, "\n")] = 0;
// Parse and handle error
int val;
if(sscanf(buffer, "%d", &val) != 1) {
// Handle error
}
// Now you can use the variable val
There is one thing here that might be dangerous in certain situations, and that is if buffer is not big enough to hold a complete line. fgets will not read more than buffersize characters. If the line is longer, the remaining part will be left in stdin.

Check if string is empty, then continue

I'm creating a very basic shell. When the user hits enter without typing any commands, the program should go to next line and continue.
If the user type any command, the program should print a text message.
I'm having issues with the empty string condition.
Tried strcmp() with another char array.
#include <stdio.h>
#include <string.h>
int main(void){
char input[256];
char str[4] = {"exit"};
do
{
printf("CSC327> ");
scanf("%[^\n]", &input);
if(getchar() == '\n')
continue;
if(strcmpi(input, str))
printf("Command not found!\n");
}while(strcmpi(input,str));
printf("\nGoodbye.");
return 0;
}
If you want to check if a string is empty, just use
int lenght = strlen(your_string)
The length of the string is returned. If it is 0, the string is empty.
First the working version of code here!.
Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int my_strcmp(char *a, char *b)
{
while(*a == *b){
a++;
b++;
}
///check line ending
if (*a == '\n' && *b=='\0')
return 0;//are equal
return 1;
}
int main(void)
{
char input[256]; //Array of characters for user input
int flag = 1;
do
{
printf("CSC327> ");
fgets(input, 256, stdin); //Read user input
if(*input == '\n')
continue;
if(my_strcmp(input, "exit")){ //Compare temp with 'exit' case insensitive
printf("Command not found!\n");
}
else{
printf("Ok! Exiting\n");
flag=0;
}
}while(flag);
printf("\nGoodbye.");
return 0;
}
Main problem is in strcmp() function. I prefer to write a simple version under the name of my_strcmp() to work exactly in this question.
Consider last character of string source and destination.
source ending is '\n' and destination is '\0'.
An ugly version to do this comparison used here. my_strcmp() can be very better but now just enough.
You call strcmp() two times, by using a flag one of them can be remove.
As Steve Summit say at comment we can use if(*input == '\n') continue; instead of your way.
Related link about writing a shell
Tutorial Write a Shell in C by Stephen Brennan, GitHub
Making your own Linux Shell in C
Want to build a simple shell? Here’s how you do it.
In brenns shell Consider line 187 if (position >= bufsize) as Steve Summit say in comment you must handle a situation if user input a larger buffer input.
Take a look at ASCII table that guide me to find out why builtin strcmp() not work properly because of different line ending 10 vs. 0.
Edit
Use '\n' instead of 10 as suggested in comment
my_strcmp() not work as case intensive compare I will improve it soon.
fgets() add \n line feed character at the end of inputted string. i.e: input[last]= '\n'. But char s[] = "test" adds '\0'
at the end of string s. For this we cant compare simply these string with library functions for example strcmp and others.
change this character and use library function strcasecmp()
By this do while loop can be rewrite
do
{
printf("CSC327> ");
fgets(input, 256, stdin); //Read user input
//fgets add \n at the end of string
/// "salam" add \0 at end of string
///change last char
input[strlen(input)-1]='\0';
//printf("len: %ld", strlen(input));
if(*input == '\n')
continue;
if(strcasecmp(input, "exit")){ //Compare temp with 'exit' case insensitive
printf("Command not found!\n");
}
else{
printf("Ok! Exiting\n");
flag=0;
}
}while(flag);
printf("\nGoodbye.");
return 0;
}
int main()
{
char input[256]; //Array of characters for user input
char temp[4]; //Array of 4 characters for getting the first 4 characters of input
do
{
printf("CSC327>");
fgets(input, 256, stdin); //Read user input
strncpy(temp, input, 4); //Get first 4 characters of input
if(strlen(input) == 1) //Determine if input is empty
continue;
if(strcmpi(temp, "exit")) //Compare temp with 'exit' case insensitive
printf("Command not found!\n");
}
while(strcmpi(temp, "exit"));
printf("\nGoodbye.");
return 0;
}//main ends

Flushing standard input buffer in C

This code is a simplification from a larger project I'm working on and it sums up the problem in a simple example. I am obtaining input from the user, their name, and then clearing the buffer from any input that did not fit in the C-string. The problem is that After entering the name, the user has to push enter twice for the program to respond, and because I am using getchar() to flush the buffer there is just a clear misunderstanding in the logic of the loop I created. How can I keep the user from entering Enter twice, in otherword what am I missing? Thanks!
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#define BUFFSIZE 10
int main(void)
{
unsigned char name[BUFFSIZE];
printf("ENTER YOUR NAME: ");
fgets(name, BUFFSIZE, stdin);
name[strcspn(name, "\n")] = '\0';
//flush the input buffer
int flush;
while (flush = getchar() != '\n' && flush != EOF);
printf("Your name is: %s!\n ", name);
printf("Press enter to continue...");
getchar();
return 0;
}
The problem in your program is that you don't distinguish the two cases: a) the user's input fit into the buffer versus b) the input didn't fit. What distinguishes these cases is the presence of the newline character in the buffer. That information is destroyed when you overwrite that character:
fgets(name, BUFFSIZE, stdin);
name[strcspn(name, "\n")] = '\0';
What we need here is something like:
size_t nlcspn = strcspn(name, "\n");
bool incomplete = name[nlcspn] == 0;
name[nlcspn] = 0;
Now we have an incomplete flag to test. Only when this flag informs that the input didn't contain a newline, then we can go ahead and complete the "get line" operation of fgets with a little loop that scans until a newline is received. (In that case, some error recovery might also be a good idea, like informing the user that the input had been too long, and creating an opportunity to rectify that).
Another thing to note is that fgets returns a value which should be checked. If it returns a null pointer, it means that the stream ended before any input was consumed. The problem is that in that case, fgets doesn't put anything into the array. The array retains its previous value, which may be previously read input, or an indeterminate value ("garbage") due to uninitialized contents.
First, the remainder of the line should not be consumed if there is no remainder, otherwise an additional line will be skipped over. Secondly, assignment has a lower precedence than most operations, meaning that flush = is evaluated after
getchar() != '\n' && flush != EOF.
When comparing the result at assignment explicit parenthesis should be added:
flush = getchar() != '\n' to (flush = getchar()) != '\n'
Alternatively the assignment can be moved outside of the conditional, see below.
The following edit uses strlen to get the final character, and moves the assignment into the loop.
#include <stdio.h>
#include <string.h>
#define BUFFSIZE 10
int main(int argc, char *argv[])
{
char name[BUFFSIZE];
size_t len;
int c;
printf("ENTER YOUR NAME: ");
fgets(name, BUFFSIZE, stdin);
len = strlen(name);
if (name[len - 1] == '\n')
name[len - 1] = '\0';
else
do
c = getchar();
while (c != '\n' && c != EOF);
printf("Your name is: %s!\n ", name);
printf("Press enter to continue...");
getchar();
return 0;
}
My wild guess just reading your code is that the error is here :
while (flush = getchar() != '\n' && flush != EOF);
You want to getchar() until the output buffer is '\n' or EOF, right ? Then try this :
while (flush = getchar() != '\n' || flush != EOF);

how can I force scanf to take the \n character as input?

I am trying to take string input in an infinite while loop that saves the string in the same array every time, but I wish this loop to terminate when I press Enter
The code looks something like this:
int main()
{
char input[1000];
while (1)
{
scanf("%s",input);
if (input[0] == '\n'){ break; } //the problem is that scanf never gets the \n
else{...}
}
return 0;
}
A newline, \n, is considered a white-space character.
If you read the C11 spec, chapter §7.21.6.2 you can see, regarding the %s format specifier with scanf() family
s
Matches a sequence of non-white-space characters.
So, using a scanf() call with %s, you cannot intake a (only) \n, which is indeed a white-space charterer.
You need to use getc() to read a newline.
Alternatively, you can use fgets() which actually reads and stores the trailing newline.
FWIW, int main() should better be int main(void), at least.
The conversion "%c" matches any character including whitespace. If you really need to use scanf(), use it with that.
// you can put this in a loop
char ch;
if (scanf("%c", &ch) != 1) /* error */;
printf("the character read is '%c' and has value %d\n", ch, ch);
Note that solutions using other functions (getc(), fgets()) are way better.
Edit:
You can tell scanf() to accept specific char with scanf("%[a-zA-Z0-9 ]", ...);
Instead, use fgets() to read the line and strcspn() to lop off the potential trailing '\n'
int main(void) {
char input[1000];
while (fgets(input, sizeof input, stdin)) {
input[strcspn(input, "\n")] = '\0';
if (input[0] == '\0') {
break;
} else {
; // ...
}
}
return 0;
}
or don't lop off the '\n' #R Sahu
int main(void) {
char input[1000];
while (fgets(input, sizeof input, stdin)) {
if (input[0] == '\n') {
break;
} else {
; // ...
}
}
return 0;
}
Instead of using scanf, using fgets.
while (1)
{
if ( fgets(input, sizeof(input), stdin) == NULL )
{
// Error reading. Perhaps EOF is reached.
break; //???
}
if (input[0] == '\n'){ break; }
else{...}
}
Use fgets(input, 1000, stdin) instead.
Then use size_t s = strlen(input); and, if the returned length is adequate, look at input[s - 1] which will be the newline character, which you can test with input[s - 1] == '\n'.

Entering more characters skips prompts

well I have a buffer of I'm assuming 10 characters. I notice when I enter 9 characters though it will skip prompt EX.
Enter a p value:
123456789
Enter a q value:
Enter a k value:
But if I put in 8 or less it will accept it normally as the program is intended, even if the user inputs letters or special characters.
My code:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <ctype.h>
int main()
{
char pbuffer[10], qbuffer[10], kbuffer[10];
int p=0, q=0, k=0;
int r, i, Q, c, count, sum;
char a[3];
a[0]='y';
while(a[0]=='y' || a[0]=='Y')
{
printf("Enter a p value: \n");
fgets(pbuffer, sizeof(pbuffer), stdin);
p = strtol(pbuffer, (char **)NULL, 10);
printf("Enter a q value: \n");
fgets(qbuffer, sizeof(qbuffer), stdin);
q = strtol(qbuffer, (char **)NULL, 10);
printf("Enter a k value: \n");
fgets(kbuffer, sizeof(kbuffer), stdin);
k = strtol(kbuffer, (char **)NULL, 10);
while(p<q+1)
{
Q=p;
sum=0;
count=0;
while(Q>0)
{
count++;
r = Q%10;
sum = sum + pow(r,k);
Q = Q/10;
}
if ( p == sum && i>1 && count==k )
{
printf("%d\n",p);
}
p++;
a[0]='z';
}
while((a[0]!='y') && (a[0]!='Y') && (a[0]!='n') && (a[0]!='N'))
{
printf("Would you like to run again? (y/n) ");
fgets(a, sizeof(a), stdin);
}
}
return 0;
}
fgets will read in as many characters as it can until it hits either a newline, EOF, or the size of the buffer. It also saves one extra character for a string-terminating \0. So, if you type in 123456789\n and have a 10-character buffer, fgets knows that it can only fit 9 characters in that buffer, so it reads in the first 9 and appends a NULL, giving you 123456789\0 in your buffer, and \n still in STDIN. Then, you call fgets a second time. It doesn't wait for input, because there is already a \n in STDIN, so it reads up to that \n, which happens to be only one character. So, your second buffer is now \n\0, and STDIN is now empty.
Either make your buffers large enough to store the strings that you're going to input, or flush STDIN after every fgets. Likely something like:
while((c = getchar()) != '\n' && c != EOF)
/* Ignore the character */ ;
Add this line after the fgets
scanf("\n");
Instead of reading into a char buffer first, you could use scanf(), e.g. scanf("%d", &p) could replace both fgets() and strtol().
Actually fgets retains the \n character when the size argument provided to it is less than the characters entered. In your case you provided value 10 as size to fgets.
so When you enter 9 characters, it fills the buffer with them and waits for an enter from you to stop reading. And when you press the enter it just puts the null character in the end of it and forward the enter to next prompt and hence skipping it.
check the examples in the answer to a question https://stackoverflow.com/a/11180652/1386897.
Flush the stdin after to the calls to fgets using
int c;
while((c = getchar()) != '\n' && c != EOF);
The reason why fgets dosen't wait for the user to enter data is because fgets knows that the buffer is full (9 chars and one space for \0) and appends a \0 in the end of the string and leaves the \n in the stdin which is taken by the next fgets

Resources