I have a problem with the input for a postfixed notation calculator in C.
My teacher asked me to use scanf("%s",token) to get the input. To stop reading tokens, I check if the value returned by scanf is EOF. It works if I use input redirection when testing, but if I write the expression on the Windows cmd I fall into an endless loop. How can I stop scanf when I simply press enter without entering a string?
Here's the code:
#include <stdio.h>
#include <ctype.h>
#include "stack.h"
int main(){
int a,b,t,stop;
char token[10],c;
do{
stop = scanf("%s",token);
if (stop == EOF){
break;
}
if (isdigit(token[0])){
t = atoi(token);
push(t);
}else{
a = top();
pop();
b = top();
pop();
c = token[0];
switch(c){
case '+': t = a + b;
break;
case '-': t = a - b;
break;
case '*': t = a * b;
break;
case '/': t = a / b;
break;
}
push(t);
}
} while(1);
printf("Result: %d\n",top());
}
The problem is in the if block after the stop variable inizialisation, I think. Sorry for my English, I'm an Italian student, I tried to be as neat as I can.
"How can I stop scanf when I simply press enter without entering a string?"
Using scanf() to read '\n' (Enter) is challenging. fgets() or fgetc() is a better approach. But the following shows how to nearly do it with scanf().
The %s in scanf("%s",token); first consumes leading white-space including '\n'. Code must first detect any potential '\n' before calling scanf("%s",token);.
char ws[2];
// Consume white-space, but not \n
scanf("%*[ \f\r\t\v]"); // Depending on locale, this may not be a complete list
if (1 == scanf("%1[\n]", ws) {
break;
}
stop = scanf("%s",token);
if (stop == EOF){
break;
}
A cleaner way to do this.
int ch;
while (isspace(ch = fgetc(stdin)) && ch != '\n');
if (ch == '\n') {
break;
}
ungetc(ch, stdin);
stop = scanf("%s",token);
if (stop == EOF){
break;
}
Only one more question: to stop the program, I had to type ctrl+z
twice. Can you tell me why?
Usually the C standard input in line buffered text mode is implemented by calling a system specific function which reads a line and returns the number of characters in it (including the newline character); when the number 0 is returned, this is considered EOF. Now, when you enter "3 5 +(crtl+z)(ctrl+z)", the first Ctrl-Z ends the input line and causes the reading function to return 5, but this does not indicate EOF to the standard input functions; only after the second Ctrl-Z ist pressed without intervening input, 0 is returned and recognized as EOF.
Related
I want to break this loop when the user press enters twice. Meaning, if the user does not enter a character the second time, but only presses enter again, the loop must break.
char ch;
while(1) {
scanf("%c",&ch);
if(ch=='') { // I don't know what needs to be in this condition
break;
}
}
It is not possible to detect keypresses directly in C, as the standard I/O functions are meant for use in a terminal, instead of responding to the keyboard directly. Instead, you may use a library such as ncurses.
However, sticking to plain C, we can detect newline characters. If we keep track of the last two read characters, we can achieve similar behavior which may be good enough for your use-case:
#include <stdio.h>
int main(void)
{
int currentChar;
int previousChar = '\0';
while ((currentChar = getchar()) != EOF)
{
if (previousChar == '\n' && currentChar == '\n')
{
printf("Two newlines. Exit.\n");
break;
}
if (currentChar != '\n')
printf("Current char: %c\n", currentChar);
previousChar = currentChar;
}
}
Edit: It appears that the goal is not so much to detect two enters, but to have the user:
enter a value followed by a return, or
enter return without entering a value, after which the program should exit.
A more general solution, which can also e.g. read integers, can be constructed as follows:
#include <stdio.h>
#define BUFFER_SIZE 64U
int main(void)
{
char lineBuffer[BUFFER_SIZE];
while (fgets(lineBuffer, BUFFER_SIZE, stdin) != NULL)
{
if (lineBuffer[0] == '\n')
{
printf("Exit.\n");
break;
}
int n;
if (sscanf(lineBuffer, "%d", &n) == 1)
printf("Read integer: %d\n", n);
else
printf("Did not read an integer\n");
}
}
Note that there is now a maximum line length. This is OK for reading a single integer, but may not work for parsing longer input.
Credits: chux - Reinstate Monica for suggesting the use of int types and checking for EOF in the first code snippet.
You can store the previous character and compare it with the current character and enter, like this:
char ch = 'a', prevch = '\n';
while(1){
scanf("%c",&ch);
if((ch=='\n') && (ch == prevch)){// don't know what needs to be in this condition
break;
}
prevch = c;
}
Note that the previous character by default is enter, because we want the program to stop if the user hits enter at the very start as well.
Working like charm now
char ch[10];
while(1){
fgets(ch, sizeof ch, stdin);
if(ch[0]=='\n'){
break;
}
}
So I've tried so much but I can't input a string even using: fgets, gets, scanf, and scanf("%[^\n]%*c",pharse). I need a string with the spaces. It just jumps the code line of input I think.
Please answer with a explanation of why it doesn't work
https://repl.it/#YashKumar11/String#main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
const int DIMMAX=100;
char pharse[DIMMAX+1];
int stringLength;
int choice=0;
while(choice != '5'){
printf("1)Enter a new pharse.");
printf("\n2)");
printf("\n3)");
printf("\n4)");
printf("\n5)\n");
scanf("%d",&choice);
switch(choice){
case 1:
printf("\n=====================\n");
scanf ("%[^\n]%*c",pharse); //<-----------------------It jumps here
printf("\n=====================\n");
stringLength = strlen(pharse);
printf("%s",pharse);
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
default:
printf("\nNot a valid option.\n\n");
break;
}
}
return 0;
}
the statement to input the parase fails because the input for choice leaves a \n in the input stream.
When the second call to scanf() is made, it immediately returns (with a returned value of 0) because the first character input is \n.
suggest following each call to scanf() with:
int ch;
while( (ch = getchar()) != '\n' && ch != EOF );
that also implies that the format string of the second call to scanf() should have the %*c removed.
Your problem is not in the line that you try to read the string, but in the previous call to scanf()
scanf() was written to scanf formatted input. Keyboard input is not that. It can be everything except formatted. The user has over 100 keys to choose from
When the user types a '1' to input a phrase scanf() does not consume the newline. In fact the user can type 1 here we go to enter some text!
and then ENTER. And scanf() will be ok with just the '1'. The rest of the chars would be left there for the program to read. scanf() has no way to know what is left there.
Also scanf() return an int with the number of values read, and it can be zero if the user entered no digits. And you did not tested in your code.
Compare with your code a bit modified below
#define DIMMAX 100
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char phrase[DIMMAX + 1];
int stringLength;
printf("1) Enter a new phrase");
printf("\n2)");
printf("\n3)");
printf("\n4)");
printf("\n5) Exit\n\nOption: ");
fgets(phrase, DIMMAX, stdin);
while (phrase[0] != '5')
{
switch (phrase[0]) {
case '1':
printf("\n=====================\n");
fgets(phrase, DIMMAX, stdin);
printf("\n=====================\n");
stringLength = strlen(phrase);
phrase[strlen(phrase) - 1] = 0; // deletes the '\n'
printf("Phrase: '%s', len = %zd\n\n", phrase, strlen(phrase));
break;
case '2':
break;
case '3':
break;
case '4':
break;
case '5':
break;
default:
printf("\n'%c' (dec %d) is not a valid option.\n\n",
phrase[0], phrase[0]);
break;
}
printf("1) Enter a new phrase");
printf("\n2)");
printf("\n3)");
printf("\n4)");
printf("\n5) Exit\n\nOption: ");
fgets(phrase, DIMMAX, stdin);
}; // while()
return 0;
}
Maybe it helps to understand.
Note that instead of stopping rigth at the digit, like scanf(), fgets() read up to and including the newline, so if you are using printf() and not puts() to output it, you must take the last byte off the string read
This question already has answers here:
How to clear input buffer in C?
(18 answers)
Closed 5 years ago.
I have attached output image of my program. you can see the problem i am facing by clicking here
Below code is my program to read an input from an user as character and check whether it is an alphabet or an number using my_isalpha() and my_isalnum() functions of my own versions of built in function isalpha() and isalnum().
Not working for second iteration of while loop
#include <stdio.h>
#define NUM 1
#define ALPHA 2
#define ASCII 3
#define BLANK 4
int main()
{
char option;
do
{
//declaration of function
char character;
int user_option, status;
//get the character from the user
printf("Enter the Character:");
//clears both buffers to read the character
fflush(stdin);
fflush(stdout);
//reads one character at a time
character = getchar();
//prompt the user for the option to check
printf("Choice Below Option\n");
printf("1.isalnum\n2.isalpha\n");
printf("Enter your Option:");
scanf("%d", &user_option);
//validation of the user_option
switch(user_option)
{
case 1:
status = my_isalnum(character);
if(status == NUM)
{
printf("Character '%c' is an number", character);
}
else
{
printf("Character '%c' is not a number", character);
}
break;
case 2:
status = my_isalpha(character);
if(status == ALPHA)
{
printf("Character '%c' is an Alphabet", character);
}
else
{
printf("Character '%c' is not Alphabet",character);
}
break;
default:
puts("Invalid Choice.....");
}
printf("\nDo you want to continue?[Y/N]:");
scanf(" %c", &option);
}while (option == 'Y' || option == 'y');
fflush(stdin);
fflush(stdout);
return 0;
}
//Function chaecks for the Number
int my_isalnum(char character)
{
return (character >= '0' && character <= '9')? NUM : -1;
}
//functionn checks for the alphabets
int my_isalpha(char character)
{
return (character >= 'a' && character <= 'z' || character >= 'A' && character <= 'Z') ? ALPHA: -1;
}
above code works properly for the first time but during second iteration of while loop. when I give "Y" as an input code dirrectly jumps to user_option part of scanf .rather then waiting for "getchar()"- function.
Even after filushing the buffer using fflush() function i am not able to prompt the program for the character input.
Flushing stdin is undefined behavior. Flushing is meant for output stream not input stream.
As per standard ยง7.21.5.2
If stream 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.
Also int getchar(void) : get char() returns an int.
Quickfix: Remove fflush(stdin) from code.
printf("\nDo you want to continue?[Y/N]:");
scanf(" %c", &option);
getchar(); // this dummy getchar() will consume the `\n` from stdin.
}while (option == 'Y')
Note:
Also as other solutions suggest to use fpurge() is an option but again it is non-standard and non-portable.
Here
//clears both buffers to read the character
fflush(stdin);
fflush() doesn't clear stdin buffer as you expected. fflush() is for flushing output stream like stdout not input stream stdin.
To resolve this issue one way is to use extra getchar() to consume \n character. for example
scanf(" %c", &option);
getchar(); /* dummy getchar */
Also here
char character; /* change the type of character to int */
character = getchar();
getchar() return type is of int not char, you need to change the type of character. From the manual page of getchar()
int getchar(void);
I'm Writing a program for Billing System. I'm using do-while loop in my program. And the program is executed according to user input. If the user want to continue the execution, the program will be continue. But I Got a prob in Execution. I was trying my logic in simple do-while loop. The same Problem arises for simple do-while loop also.
Problem is: If the input is yes, the program does not get the further input from user.
That simple do-while loop is:
#include <stdio.h>
main()
{
int c;
char ch;
do
{
printf("enter the no less then 4:");
scanf("%d",&c);
switch(c)
{
case 1:
printf("In 1\n");
break;
case 2:
printf("In 2\n");
break;
case 3:
printf("In 3\n");
break;
}
printf("do u want to continue?:");
ch=getchar();
}while(ch=='y');
}
If i put while(ch != 'n') instead of while(ch=='y') the program working fine. I couldn't understand the problem behind this. Please Help me to rectify this. And Explain about this problem.Thank u in advance.
first run, 3 is printed, user types "y" and presses return
getchar() reads 'y' and program loops
second time, getchar() reads newline character from the previous key press
newline is not 'y' so program does not loop
Several problems:
getchar returns an int, not a char, so ch must be an int just like c.
scanf needs a pointer to go with the %d, so it should be scanf("%d", &c);
The while should rather test for EOF, as in while ((ch = getchar()) != EOF)
Note that the input will contain the newlines, which you should deal with (e.g. ignore).
This should be quite robust:
#include <stdio.h>
int main(void)
{
int c, ch;
for (;;) {
printf ("Enter a number (1, 2 or 3):");
fflush (stdout);
if (scanf ("%d", &c) == 1) {
switch (c) {
case 1:
printf ("In 1\n");
break;
case 2:
printf ("In 2\n");
break;
case 3:
printf ("In 3\n");
break;
}
printf ("Do you want to continue? [y/n]:");
fflush (stdout);
while ((ch = getchar ())) {
if (ch == 'y')
break;
else if (ch == 'n' || ch == EOF)
return 0;
}
} else {
printf ("That was not a number. Exiting.\n");
return 0;
}
}
}
While(ch=='y') or the character whatever in while() it will sent to case 3 as per your coding....y is pressing ,it wil sent to case 3 otherwise it wont work
Instead of reading the answer using getchar, use fgets.
As others explained, the second getchar call gives you the newline, which was typed after the first y.
With fgets, you'll get everything the user typed. Then you can check if it's y (just check the first character, or use strcmp).
I'm new to c programming and I'm facing this problem with my program
I have a loop that gets a char form the input buffer
while(c = getchar()){
if(c == '\n') break;
if(c == '1') Add();
if(c == '2') getInput(); // this is where the headache starts
....
}
here is the getInput() function
void getInput()
{
char ch = getchar();
if(ch == '1') doSomething();
....
}
but when calling getchar() from the getInput() function it only gets characters that were left in the input buffer from the last call of getchar(). and what i want it to do is to get newly typed characters.
I've been googling for two hours for a decent way to clear the input buffer but nothing helped. So a link to a tutorial or an article or something is very appreciated and if there's another way to implement this then please tell me.
First of all there will be == comparison operator rather than = assignment operator in the if condition in this code.
while(c = getchar()){
if(c = '\n') break;
if(c = '1') Add();
if(c = '2') getInput(); // this is where the headache starts
....
}
And for stop taking input try EOF which from keyboard can be given by prssing CTRL+D.
EDIT : The problem is with the \n which is actually taken as input when you press ENTER key on the key board. So change just one line of code.
if (c ==\n) break; to if (c == EOF ) break; and as I said EOF is the end of input.
Then your code will work fine.
Flow of code :
step 1: suppose `2` is input
step 2: getInput() is called
step 3: suppose `1` as input // in getInput
step 4: doSomething() is called // from getInput
step 5: After completion of doSomething again come back to while loop ,
but in your case you have already given `\n` character as an input
when you pressed `1` and `ENTER`.And thus loop terminates.
but after changing the code as I said , this should work.
NOTE: To understand code flow and for debugging purposes it's best practice to put printf() in various places in functions and see the output as which lines are executing and which are not.
This should work: (Example of clearing input buffer)
#include <stdio.h>
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;
}
/*
* Program output:
*
Flushing input
blah blah blah blah
Enter some text: hello there
You entered: hello there
*
*/