Why isn't my while loop functioning properly? - c

My task is to exit the loop only if the user types "n" or "N".
Here is my code:
#include<stdio.h>
int main()
{
char alpha;
printf("This loop will repeat. Do you wnat to repeat? (Press n or N to exit). ");
scanf("%c", &alpha);
if(alpha != 'n' || alpha != 'N')
{
printf("Do you still want to repeat? (Press n or N to exit). ");
}
while(alpha != 'n' || alpha != 'N');
return 0;
}
The problem is my code is not looping at all.

Comments in code:
#include <stdio.h>
int main(void)
{
char alpha;
printf("This loop will repeat. Do you wnat to repeat? (Press n or N to exit). ");
// You need a "do" to start a block of code,
// otherwise the "while" loop runs forever
do
{
// Put a space before the format specifier to consume the trailing
// newline left by previous calls to scanf
scanf(" %c", &alpha);
// You want the "and" operator, not "or"
if(alpha != 'n' && alpha != 'N')
{
printf("Do you still want to repeat? (Press n or N to exit). ");
}
}
// Same here, you want the "and" operator, not "or"
while(alpha != 'n' && alpha != 'N');
return 0;
}
A better approach (test the condition only once and check the result of scanf):
#include <stdio.h>
int main(void)
{
char alpha;
printf("This loop will repeat. Do you wnat to repeat? (Press n or N to exit). ");
while (scanf(" %c", &alpha) == 1)
{
if(alpha != 'n' && alpha != 'N')
{
printf("Do you still want to repeat? (Press n or N to exit). ");
}
else break;
}
return 0;
}

Related

User input with scanf using while loop

I'm having a problem with multiple characters while using a while loop. I'm writing a code that would direct the user to a new function based on the input of either "y" or "n". When I scanf for one character it works fine; however, when the user types in multiple characters the while loop repeats.
#include <stdio.h>
int main()
{
char x;
printf("type in letter n or y\n");
scanf("%c", &x);
while (x!= 'Y' && x!='N' && x!= 'n' && x!='y')
{
printf("Invalid, please type Y/N to continue: \n");
scanf(" %c", &x);
}
if (x== 'Y' || x == 'y')
{
printf("y works");
}
if (x =='N' || x =='n')
{
printf("n works");
}
}
For example, if I type in hoyp, it would say "Invalid, ..." 2 times and then the "y works" would be written on the third line. How can the code be changed so that the invalid would only be said once, and the user must input again to allow the program to continue?
This is how scanf behaves. It keeps reading in all the characters you've entered. You can accept a string as input first using fgets and extract and check only its first character. fgets allows you to specify the exact number of characters to be read. I have first declared a char array of size 4096. This will work when the input is up to 4095 characters. You can adjust the size as per your needs.
#include <stdio.h>
int main()
{
char x, buffer[4096];
printf("type in letter n or y\n");
fgets(buffer, 4096, stdin);
x = buffer[0];
while (x!= 'Y' && x!='N' && x!= 'n' && x!='y')
{
printf("Invalid, please type Y/N to continue: \n");
fgets(buffer, 4096, stdin);
x = buffer[0];
}
if (x== 'Y' || x == 'y')
{
printf("y works");
}
if (x =='N' || x =='n')
{
printf("n works");
}
}
Here is my approach to the problem:
I have used fgets() instead of scanf(). See why
here.
I have used the suggestion by users jamesdlin and M.M in this question to solve the repeated printing issue when the input is more than one character or if the input is empty. I encourage you to read the whole thread to know more about this issue.
(Optional) Used some extra headers for better code readability in the loop conditions. I think the fgets() could be used in the condition of the while() but I got used to the pattern I have written below.
Edit: added a condition to reject inputs with length > 1. Previously, inputs that starts with 'y' or 'n' will be accepted (and are interpreted as 'y' or 'n' respectively) regardless of their length.
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
void clearInput();
int main()
{
// allocate space for 'Y' or 'N' + '\n' + the terminator '\0'
// only single inputs will be accepted
char _inputbuff[3];
char choice;
bool isValidInput = false;
while(!isValidInput) {
printf("Please enter your input[y/n]: ");
// use fgets() instead of scanf
// this only stores the first 2 characters of the input
fgets(_inputbuff, sizeof(_inputbuff), stdin);
// don't accept empty input to prevent hanging input
if(_inputbuff[0] == '\n') {
printf("Empty input\n");
// go back to the top of the loop
continue;
}
// input is non-empty
// if the allocated space for the newline does not
// contain '\n', reject the input
if(_inputbuff[1] != '\n') {
printf("Input is more than one char.\n");
clearInput();
continue;
}
choice = _inputbuff[0];
// printf("The input is %c\n", choice);
// convert the input to uppercase for a 'cleaner' code
// during input validation
choice = toupper(choice);
// the input is not 'Y' or 'N'
if(choice != 'Y' && choice != 'N') {
printf("Please choose from Y or N only.\n");
// go back to the top of the loop
continue;
}
// the input is 'Y' or 'N', terminate the loop
isValidInput = true;
}
// conditions for 'Y' or 'N'
if(choice == 'Y') {
printf("The input is Yes.\n");
return 0;
}
if(choice == 'N') {
printf("The input is No.\n");
return 0;
}
}
void clearInput() {
int _clear;
// clear input stream to prevent repeated printing of invalid inputs
while ((_clear = getchar()) != '\n' && _clear != EOF ) { }
}
(This is my first time answering a question and it has been a while since I have used C so feel free to give suggestions/corrections regarding my answer. Thanks!)

Stop a user introducing values for an array

I have a program to introduce temperatures, and I need to ask what scale he wants to insert the data, and then receive a list of temperatures. Then I need to convert that list.
But what would I put for a stop condition in the while since 0 can be a temperature?
int main(int argc, char const *argv[]) {
int n = 0;
int temperaturas[TAMANHO];
char escala;
printf("Escala: ");
scanf("%c", &escala);
puts("Para PARAR Prima 0");
while (temperaturas[n - 1] != 0) {
if (escala == 'C') {
printf("\n\tCelcius: ");
scanf("%d", &temperaturas[n]);
} else
if (escala == 'K') {
printf("\n\tKelvin: ");
scanf("%d", &temperaturas[n]);
}
n++;
}
escreverTemperaturas(temperaturas, escala, n);
return 0;
}
From what i understood from your question , you want to the user to stop typing the temperatures whenever he wants , or when the the list is full .
Basiclly , you can simply switch your program a bit by asking the user if he wants to continue typing , otherwise when n > TAMANHO .
while ((n<= TAMANHO) || (continue != N))
{
if (escala == 'C')
{
printf("\n\tCelcius: ");
scanf("%d", &temperaturas[n]);
}
else if (escala == 'K')
{
printf("\n\tKelvin: ");
scanf("%d", &temperaturas[n]);
}
printf("Would you like continue typing the temparutres ? ");
scanf(" %c",&continue);
n++;
}
Tips :
You should control the inputs as if he doesn't type C or K it should be another condition as printing a message to inform ( same for &continue);
also i advice you to read this previousely asked question about how
scanf("%c", &escala);
should be replaced with
scanf(" %c", &escala);
Read this, about scanf:
"On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file." http://www.cplusplus.com/reference/cstdio/scanf/
So you can just use the value returned by scanf.
do {
printf("Escala: ");
scanf(" %c", &escala);
} while( escala != 'C' && escala != 'K');
do {
escala == 'C' ? printf("\n\tCelcius: ") : printf("\n\tKelvin: ");
} while( n < TAMANHO && scanf("%d", &temperaturas[n++]) == 1 );
When there's nothing left to read (or the input is not a number) scanf returns 0 breaking the loop.

How do I reduce multiple outputs

How can I limit the output to only one response when I type in multiple characters.
#include <stdio.h>
main(){
char answer;
printf("Do you want to continue(Y/N)?");
scanf("%c", &answer);
while ((answer != 'Y') && (answer != 'N')){
printf("\nYou must type a Y or an N\n");
printf("Do you want to continue(Y/N) ?");
scanf(" %c", &answer);
}
return 0;
}
Use getchar() for reading the first character, then read next characters until EOF.
Additionaly the reading outside (before) the loop is not necessary.
#include <stdio.h>
// additional function for reading remaining input
void flush();
main(){
// answer needs to be int, because getchar() can return -1 in case of EOF
int answer;
while (1) {
printf("Do you want to continue(Y/N)? ");
answer = getchar();
// read and ignore the remaining input
flush();
if ((answer == 'Y') || (answer == 'N'))
break; // exit loop
printf("\nYou must type a Y or an N\n");
}
// here answer contains 'Y' or 'N'
// do what you need with this...
return 0;
}
// function for consuming the remaining input
void flush()
{
while (getchar() != EOF); // consume input until emptying
}

Scanf in visual studio not accepting multiple cases of characters

I'm creating a conversion project for letters/numbers ASCII table. My code is supposed to be 'interactive', so the user would type 'y' or 'n' to answer questions on the screen. However, it doesn't want to do this twice...
I have tried:
Just trying numbers instead of characters, but it's not exactly what I want
The %[\n]*c, and %[\n]c, and %[\n]*s ... technique but it doesn't help ;-;
Testing in a different project, but the only way I am able to do it is for multiple scanf()s to be in a row.
Here is the code:
printf("Would you like to convert a number today? \n");
printf("Please press Y or N \n");
scanf("%c", &input);
if (input == 'y' || input == 'Y') { //compare input if they said 'yes'
printf("\nThank you! \nWhat number?\n");
scanf("%d", &number);
flag = test(number);
if (flag == 0) { //if there is an equivalent letter
letter = conversion(number); //find the equivalent letter
printf("\nYour Number \t ASCII letter\n");
printf("%d\t %c\n", number, letter);
}
}
else if (input == 'n' || input == 'N') {
printf("\nWould you like to convert a letter instead? This time enter 0 or 1\!\n\n"); //problem here!!
printf("I wish I could say it was to \' Spice things up \' ...but it\'s not ;-; \n\n");
scanf("%d", &input2);
if (input2 == 0) { //this needs to be checking whether the user input Y/y
printf("Great choice adventurer!\n");
printf("What letter will it be today?\n\n");
//..I would go to a different funtion here ie: test2(letter)...
scanf("%d", &number); //I showed that it worked with multiple numbers, but I can't get this to work with multiple letters
printf("%d", number);
}
if (input2 == 1) { //this needs to be checking whether the user input N/n
printf("Difficult to please, I see...\n\n");
printf("I suggest you move on with that attitude!\n\n");
printf("Bye bye then\n");
}
}
else { //if they tried to break the code
printf("Sorry I did not recognise your command...please retry\n");
printf("Press Y or N next time!\n");
}
The first check works perfectly, I just want the second check to be like the first!
Some 'solutions' caused a overflow, which I don't want if possible
Even if someone could explain why this isn't working the way I intended would be very helpful!
I'm not sure what confuses you.
Use
char foo;
scanf(" %c", &foo);
for single characters, eg. letters and
int bar;
scanf("%d", &bar);
for numbers, integers. If you type a letter instead, scanf() will fail.
%[...] is for strings.
scanf() returns the number of successful conversions (or EOF), so for
int height;
int width;
scanf("%d %d", &height, &width);
it returns 2 if successful. It might return 1 if only height could be read.
So to check for errors on user input you should do:
int height;
int width;
if (scanf("%d %d", &height, &width) != 2) {
// handle the error, maybe exit the program.
}
Your code could look like that (without error handling):
#define _CRT_SECURE_NO_WARNINGS // you said Visual Studio? Without it you should get
// warnings about some functions being insecure.
#include <ctype.h> // isalpha() returns true if the value is a letter
#include <stdlib.h> // EXIT_SUCCESS
#include <stdio.h> // puts(), printf(), scanf()
int main(void)
{
for(;;) { // for-ever ... endless loop since the user exits by answering
// 'n' or 'N' two times
puts("Would you like to convert a number today?\nPlease press Y or N:");
char input;
if (scanf(" %c", &input) != 1) // We reached EOF ... end of file
break; // that's improbable for stdin,
// but input could be redirected to
// read from a file instead.
if (input == 'y' || input == 'Y') {
puts("\nThank you!\nWhat number?");
int number;
scanf("%d", &number);
if (isalpha((char unsigned)number)) // *)
printf("\nYour Number \t ASCII letter\n%d\t %c\n\n", number, number);
else
puts("Sorry, but that's not the ASCII code of a letter :(\n");
}
else if (input == 'n' || input == 'N') {
puts("\nWould you like to convert a letter instead?\nPlease press Y or N:");
scanf(" %c", &input);
if (input == 'y' || input == 'Y') {
puts("\nGreat choice adventurer!\nWhat letter will it be today?");
char letter;
scanf(" %c", &letter);
if (isalpha(letter))
printf("\nYour letter \t ASCII code\n%d\t %c\n\n", letter, letter);
else
puts("Sorry, but that's not a letter :(\n");
}
else if (input == 'n' || input == 'N') {
puts("\nDifficult to please, I see...\n\nI suggest you move on with that attitude!\n");
puts("Bye bye then.");
return EXIT_SUCCESS;
}
}
else {
puts("Sorry I did not recognize your command... Please retry.");
puts("Press Y or N next time!\n");
}
}
}
*) isalpha() (and the other functions in <ctype.h>) expects a value that fits in a unsigned char or the value EOF. It has undefined behaviour for other values. Since we read user input into an int we cannot be sure that's the case so we have to cast the value to unsigned char before passing it to isalpha() (and friends).
Next time you ask a question please include your full code, including variable declarations, functions like test() and conversion() and #includes. But please, post an example that focuses on your problem at hand. All that dialog you included would not have been necessary.

Scanning character caused problem in devC

So my code does the following:
Ask what's the option
If option is 1: Scan some numbers
If option is 2: Print those numbers
After each option, ask if user wanted to continue choosing (Y/N)
This is my main code
while(yesnocheck==1)
{
printf("What's your option?: ");
scanf("%d",&b);
switch(b){
case 1:
printf("How many numbers?: ");
scanf(" %d",&n);
a=(struct sv*)malloc(n*sizeof(struct sv));
for(int i=0;i<n;i++)
scanf("%d",&((a+i)->num));
break;
case 2:
for(int i=0;i<n;i++)
printf("%d\n",(a+i)->num);
break;
}
yesnocheck==yesnochecker();
}
And this is the yesnochecker function:
int yesnochecker()
{
char yesorno;
printf("Do you want to continue? (Y/N)");
while(scanf("%s",&yesorno))
{
if(yesorno=='Y')
return 1;
if(yesorno='N')
return 0;
printf("*Wrong input. Please reenter (Y/N): ");
}
}
So on dev C++, my code won't run correctly. After it's done option 1, when I enter "Y" then choose option 2, case 2 will display some weird numbers. However it works well on online C compilers.
And then, when I change the char yesorno in yesnochecker() function to char yesorno[2] and treat it as a string, the code does work.
Can someone shed some light?
It is a bad idea to read a char c with scanf("%s", &c);. "%s" requires a buffer to store a string. The only string which fits into a char is an empty string (consisting only of a terminator '\0' – not very useful). Every string with 1 character requires 2 chars of storage – 1 for the character, 1 for the terminator ('\0'). Providing a char for storage is Undefined Behavior.
So, the first hint was to use the proper formatter instead – "%c".
This is better as it removes the Undefined Behavior. However, it doesn't solve another problem as the following sample shows:
#include <stdio.h>
int cont()
{
char c; do {
printf("Continue (y/n): ");
scanf("%c", &c);
printf("Input %c\n", c);
} while (c != 'y' && c != 'n');
return c == 'y';
}
int main()
{
int i = 0;
do {
printf("Loop iteration %d.\n", ++i);
} while (cont());
/* done */
return 0;
}
Output:
Loop iteration 1.
Continue (y/n): y↵
Input 'y'
Loop iteration 2.
Continue (y/n):
Input '
'
Continue (y/n): n↵
Input 'n'
Live Demo on ideone
WTH?
The scanf("%c") consumes one character from input. The other character (inserted for the ENTER key) stays in input buffer until next call of any input function.
Too bad, without ENTER it is hard to confirm input on console.
A possible solution is to read characters until the ENTER key is received (or input fails for any reasons). (And, btw., getc() or fgetc() can be used as well to read a single character.):
#include <stdio.h>
int cont()
{
int c;
do {
int d;
printf("Continue (y/n): ");
if ((c = fgetc(stdin)) < 0) {
fprintf(stderr, "Input failed!\n"); return 0;
}
printf("Input '%c'\n", c);
for (d = c; d != '\n';) {
if ((d = fgetc(stdin)) < 0) {
fprintf(stderr, "Input failed!\n"); return 0;
}
}
} while (c != 'y' && c != 'n');
return c == 'y';
}
int main()
{
int i = 0;
do {
printf("Loop iteration %d.\n", ++i);
} while (cont());
/* done */
return 0;
}
Output:
Loop iteration 1.
Continue (y/n): y↵
Input 'y'
Loop iteration 2.
Continue (y/n): Hello↵
Input 'H'
Continue (y/n): n↵
Input 'n'
Live Demo on ideone
Please, note, that I changed the type for the read character to int. This is because getc()/fgetc() return an int which is capable to store any of the 256 possible char values as well as -1 which is returned in case of failing.
However, it isn't any problem to compare an int with a character constant (e.g. 'y'). In C, the type of character constants is just int (SO: Type of character constant).

Resources