Halt while loop if the condition is not met - c

I'm trying to add a while loop inside the program. After it executes it's supposed to ask you if you want to continue and type in "y" if you do and "n" if you don't. If they do it's supposed to start over again, if not then it stops.
The thing is I wanted to make a message pop up if someone types in something other then "y" or "n" to require them to do that. The problem is the while loop will go on whatever they write in.
char cnd[100];
while(cnd[0] != 'n') {
printf("Program executing\n");
printf("Would you like to launch the program again? If not then type in 'n', if you do then type in 'y': ");
scanf("%s", &cnd);
while(cnd[0] != 'n' || cnd[0] != 'y') {
printf("You have to type in either 'y' or 'n':");
scanf("%s", &cnd);
}
}
return 0;
I tried to even test this by printing the user input before and after the statement. It does seem to be correct, so I don't know why the while loop won't work.

Let's translate your loop condition to plain English:
cnd[0] != 'n' || cnd[0] != 'y'
Basically, you're saying:
If the first character in cnd is something other than n, or the first character in cnd is something other than y, enter the loop.
This is unfalsifiable since cnd[0] will always be either not n or not y - it can't be both at the same time.
You should instead be asking:
If the first character in cnd is something other than n, and the first character in cnd is something other than y, enter the loop.

your while loop checks if it isn't y or isn't n one of those is always true try this instead
while(cnd[0] != 'n' && cnd[0] != 'y') {

The condition cnd[0] != 'n' || cnd[0] != 'y' is always true. You meant to use && (logical and).
You also need to drop & from &cnd (in both scanf calls) as that'd result in format specifier mismatch.
Also in the very first iteration cnd is uninitialized. You're better off using a do ..while loop or start cnd with "y" such as: char cnd[100] = "y";
Note the problems with scanf too.

read what you wrote (as code, not as english)
while(cnd[0] != 'n' || cnd[0] != 'y') {
if cnd[0] = 'n' then it doesnt = 'y' and vice versa.
you mean
while(cnd[0] != 'n' && cnd[0] != 'y') {
ie give the error is its not n and its not y

First and foremost: Why do you read a string when you want a single character? Use getchar(). Then check if there is other garbage after that character in the stream and act accordingly: Error message, clearing stdin:
#include <stdbool.h>
#include <ctype.h>
#include <stdio.h>
void clear(FILE *stream)
{
int ch;
// eat everything until a newline or EOF is encountered:
while ((ch = fgetc(stream)) != EOF && ch != '\n');
}
bool only_whitespace(FILE *stream)
{
int ch;
// eat all whitespace until a newline or EOF is encountered:
while ((ch = fgetc(stream)) != EOF && isspace((char unsigned)ch) && ch != '\n');
// ^^^^^^^^^^^^^^ don't pass signed values
// to the functions from <ctype.h>
if (ch == '\n') { // when the last character read was a newline
ungetc(ch, stream); // put it back into the stream
return true; // and tell the caller that all we encountered
} // was whitespace
return false;
}
int main(void)
{
int again;
do {
puts("Program executing\n");
while (printf("Would you like to launch the program again? If not then type in 'n', if you do then type in 'y': "),
(again = getchar()) != EOF && again != 'y' && again != 'n' || !only_whitespace(stdin))
{
fputs("Input error!\n\n", stderr);
if (again != '\n') // when the character read was not a newline
clear(stdin); // there could be other garbage left in the stream
}
clear(stdin);
} while (again == 'y');
// return 0; // Since C99 (i think) the effect of execution reching the end of main() without
// encountering a return-statement is the same as return 0; (same in C++)
}

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

How to detect last character in a C string when within a getchar() loop

Suppose I have the following which allows the entering in of text:
printf("Enter in your text\n");
while ((c=getchar()) != EOF) {
putchar(c);
if (last_char) // the last character before the user presses enter.
do_something();
}
Is there a way for me to detect if the character is the last one in the text input (without getting out of the loop)? Or is that not possible the current organization of things above?
Something list this?
printf("Enter in your text\n");
int c,last_char;
do
{
c = getchar();
if (c == '\n')
{
// it's the last char... do something with last_char
printf("\nThe last char was: %c\n", last_char);
}
last_char = c;
} while (c != EOF);
How about-
int c = 0;
while((c = getchar()) != EOF)
{
putchar(c);
// assuming that ';' is the character. you can change
// this to any acceptable character here
if(c == ';')
{
printf("\nYou entered ';' character\n");
// do something here
}
}
Is there a way for me to detect if the character is the last one in the text input (without getting out of the loop)?
No.
stdin is best thought of as a stream of data. Code cannot know beforehand if end-of-file or enter ('\n') will arrive
How to detect last character in a C string when within a getchar() loop
Instead detect when end-of-file occurs and operate on the previous character after the loop.
printf("Enter in your text\n");
int previous = EOF;
int c;
while ((c=getchar()) != EOF) {
previous = c;
}
do_something(previous);
If one needs the character before enter, while ((c=getchar()) != '\n' && c != EOF) { would suffice.

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.

C "comparison between pointer and integer" warning for menu

I'm trying to write a program that involves comparing chars as part of a menu system for a program that decodes resistor codes. At the end of the menu it asks if you want to decode another resistor, repeating the program if the user selects "yes".
This is the code I have so far:
//used for repeating input menu
int menu = 0;
char menuChoice = 0;
//rest of program goes here
printf("Do you want to decode another resistor? (y/n)");
scanf("%c", &menuChoice);
while(menuChoice != "y" && menuChoice != "Y" && menuChoice != "n" && menuChoice != "N")
{
if(menuChoice != "Y" && menuChoice != "y")
{
if(menuChoice == "N" || menuChoice == "n")
{
menu = 0;
}
else
{
printf("Invalid choice.");
}
}
}
When I try to compile with GCC, I end up with a warning that says "comparison between pointer and integer." Since scanf only accepts a pointer, I don't know how exactly to compare the scanned char with to "Y" or "n". Is there something I'm missing here?
You are using the string literal syntax "a" instead of the char literal syntax 'a'
More about the difference
Adjust your comparisons. Presently they compare a an integer (or char such as menuChoice) to an array (such as "y").
// menuChoice != "y"
menuChoice != 'y'
The while(menuChoice != "y") && ...) likely should be removed.
The if(menuChoice == "N" ... should be else if(menuChoice == "N" ...).

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