While GetChar != EOF terminating inconsistently - c

I have these two blocks of code, the aim of both of which is to get some user inputs, to make a cryptography script.
int keyPrompt(){
/* this prompts the user for the Caesar encryption key */
int c;
printf("Enter key value between 1-9: ");
while((c=getchar()) != EOF && c != '\n'){
return c;
}
}
int cryptPrompt(){
/* this asks the user whether they want to encrypt or decrypt */
int d;
printf("Do you want to encrypt or decrypt?(E/D): ");
while((d=getchar()) != EOF && d != '\n'){
/*
if(d == 'E'){
return 1;
}
else if (d == 'D' ){
return -1;
}
*/
return d;
}
}
The problem I'm having is that when I run the file, the first while loop behaves as I expect it to: I enter a value, hit enter and it goes to the next line. With the second while loop, when it executes the function, it skips asking the user for an input and simply goes straight to the next line of good, not storing any return value.
Any idea why it's doing this?

Consider what this code does:
int keyPrompt(){
/* this prompts the user for the Caesar encryption key */
int c;
printf("Enter key value between 1-9: ");
while((c=getchar()) != EOF && c != '\n'){
return c;
}
}
After printing the prompt, it reads an input character. If that character is an EOF or a newline, it exits the loop and falls off the end of the function (without a return, which leads to undefined behavior if the returned value is not ignored). If its NOT an EOF or newline, it returns the character.
In no case will the while loop ever actually loop.
Consider what happens if you call this code and enter a key+newline. The key will be read and returned, and the newline will be left in the input buffer. Now consider what happens if you call another function like this -- the first thing it will read is the newline left over from the keyPrompt function...

Related

How to take input until enter is pressed twice?

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;
}
}

In C, why do I only need getchar() to remove characters sometimes?

I am trying to use getchar() to remove characters from the input buffer. In the following code, the user is asked to input a choice to select, and then depending on the choice, another input is required, either type int or type char (string).
In the int case, getcar() is not needed and scanf takes in input correctly. But in the char case, scanf fails to get input without using getchar() beforehand. Is there a reason why that is?
printf("Available Ciphers:\n1) Caesar Cipher\n2) Vigenere Cipher\nSelected Cipher: ");
if(scanf("%d", &choice) != 1){
printf("Error: Bad selection!\n");
exit(EXIT_SUCCESS);
} else if (choice != 1 && choice != 2){
printf("Error: Bad Selection!\n");
exit(EXIT_SUCCESS);
//If the choice entered is correct, then run the following.
} else {
if(choice == 1){
printf("Input key as nuumber: ");
if(scanf("%d", &caesarkey) != 1){ //Why is getchar() not needed here?
printf("Error: Bad Key!\n");
exit(EXIT_SUCCESS);
}
//morecode here
} else if (choice == 2){
printf("Input key as string: ");
while(getchar() != '\n'); //Why is this needed here?
/*Uses scanf and not fgets, since we do not want the
key to contain the newline character '\n'. This is
due to the fact that the newline character is not
considered in the function that encrypts and decrypts
plaintext and ciphertext.*/
if(scanf("%[^\n]s", vigencipherkey) != 1){
printf("Error, Cannot read inputted key!\n");
exit(EXIT_SUCCESS);
}
//More code here..
}
}
It seems that you are scanning for a string rather than an int, and as such, you are passing in an int rather than the address of an int.
Change this line
if(scanf("%[^\n]s", vigencipherkey) != 1){
To
if (scanf("%d", &vigencipherkey) != 1) {
In order to read the remainder of the line input by the user, you can use this function:
int flush_line(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
Notes:
c must be defined as int to accommodate for all values of the type unsigned char and the special negative value EOF.
you should test for '\n' and EOF otherwise you will have an endless loop on premature end of file without a trailing newline, such as would occur if you redirect the input of your program from an empty file.
you can test for end of file by comparing the return value of flush_line() with EOF.

when scanf returns 0 in c and just doesn't work

'when there is no successful assignments' i know that scanf returns 0 to indicate it, but is that the only thing that it does? this is my code:
#include<stdio.h>
int main(void) {
int val,x;
x=scanf("%d",&val);
if(x==1)
printf("success!");
else{
printf("try again\n");
scanf("%d",&val);
}
return 0;
}
if i enter a number, it works fine but if i enter a character scanf doesn't work anymore, this is what i get:
k
try again
process returned 0 (0x0) execution time :2.578 s
press any key to continue.
_
meaning that it doesn't allow me to enter a new value, why is that? is there something wrong in the code? if yes how can i fix it? should i stop using scanf?
When scanf doesn't work, the invalid data is still left in the stream. You'll have to read and discard the data from the stream first before you can enter more data.
#include<stdio.h>
int main(void) {
int val,x;
x=scanf("%d",&val);
if(x==1)
printf("success!");
else{
// Discard everything upto and including the newline.
while ( (x = getchar()) != EOF && x != '\n' );
printf("try again\n");
scanf("%d",&val);
}
return 0;
}
The scanf family of functions are broken-as-specified and should never be used for anything.
The correct way to write this program is to use getline, if available, or fgets otherwise, to read an entire line of user input. Then use strtol to convert the input to a machine integer, taking care to check for errors:
errno = 0;
result = strtol(line, &endptr, 10);
if (endptr == line || *endptr != '\n' || errno)
// invalid input

C, can not read input

#include <stdio.h>
#include <stdlib.h>
int main()
{
int i,j;//count
int c;//for EOF test
int menu;
unsigned int firstSize = 12811;
unsigned int lastSize;
char * text=malloc(firstSize);
if(text == NULL){
printf("\n Error. no Allocation.");
exit(-1);
}
printf("\n for input 1e,for autoinput press 2.");
scanf("%d",&menu);
if(menu==1){
printf("enter text..");
c = EOF;
i = 0;
lastSize = firstSize;
while (( c = getchar() ) != '\n' && c != EOF)
{
text[i++]=(char)c;
//if i reached maximize size then realloc size
if(i == lastSize)
{
lastSize = i+firstSize;
text = realloc(text, lastSize);
}
}
This is the part of code which is where the problem lies.
Output when I type 1 for the scanf is:
for input 1e,for autoinput press 2.
1
enter text..
It does not let me to give input for the getchar().
But when I delete scanf for menu and use menu=1;, I can easily give input for the getchar() and it gives me output correctly:
printf("\n for input 1e,for autoinput press 2.");
scanf("%d",&menu);
instead of that
printf("\n for input 1e,for autoinput press 2.");
//scanf("%d",&menu);
menu=1;
Is it about printf scanf issues that I don't know about? In java, before taking second input, we need to put some blank. Is it like that?
The problem is that you press Enter after entering a number for your scanf. The number is consumed by the scanf while the newline character generated by the enter key press resides in the standard input stream(stdin).
When the execution of the program reaches the while loop:
while (( c = getchar() ) != '\n' && c != EOF)
getchar() sees the newline character, grabs it, assigns it to c and then, the loop doesn't execute as the condition(c != '\n') is false. This is what you were unexpecting.
You can add
while (( c = getchar() ) != '\n' && c != EOF);
anywhere between the scanf and your getchar() to clear the stdin.
An alternative way would be to use scanf("%d%*c",&menu); as suggested by #user3121023 in the comments. %*c instructs scanf to read and discard a character. It will discard the newline character if the user had typed in a number and then pressed enter for the scanf.
Other stuff:
c = EOF; isn't required. Neither is the cast here: text[i++]=(char)c;. You also do not need two variables lastSize and firstSize. You should also check the return value of realloc.

how to handle the input buffer in c

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
*
*/

Resources