Do...while in C to terminate a program - c

I am using do...while as a loop control in C language. I need to terminate the program when the user enters "99", else the user should guess the number to terminate the program, until then the program will run. Here is the code. I don't have any compiler error, but instead it prints the number 0 to the number the users entered.
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int num = 0;
do {
scanf("Enter the magic number to terminate this program: %d\n", &num);
printf("You entered : %d\n", num);
num++;
} while (num != 100);
printf("\nThe magic number is correct and the program is terminated:");
return 0;
}
Any help is appreciated.

scanf is not like Python's input, for example. It requires the exact input that you specify in the format string. In your particular case, you are expecting the users to enter "Enter the magic number to terminate this program: ", followed by a number.
One way to check this is to use the return value, which tells you the number of matched arguments:
k = scanf("...\n", &num);
printf("scanf managed to get %d inputs\n", k);
The solution is to split the input and output portions:
printf("Enter the magic number to terminate this program: ");
scanf("%d", &num);
scanf will automatically filter out whitespace between inputs, including the newlines that the user enters. You can also consume those explicitly with either "%d\n" or equivalently "%d ". However, you shouldn't do that. scanf treats any whitespace characters as "any number of whitespace", and will block until it receives the next non-whitespace character. It will also cause a problem if your stream ends without a trailing newline.

Related

Program To Check If A Number Is Present In An Array

I wrote the below C code to check if a number is present in an array whose elements are input by the user. But weirdly it's skipping the the third printf statement, directly taking the input and printing Enter the number you wish to look for after taking that input. What is causing this? Included input and output box below code.
CODE:
#include <stdio.h>
#include <stdlib.h>
void main() {
int arr[30], size, i, num, flag=0;
printf("Enter size of array. \n");
scanf("%d",&size);
printf("Enter %d array elements one by one. \n",size);
for (i=0; i<size; i++) {
scanf("%d \n",&arr[i]);
}
printf("Enter the number you wish to look for. \n");
scanf("%d",&num);
for(i=0;i<size;i++) {
if (num == arr[i]) {
flag++;
}
}
if (flag>0) {
printf("The number %d is present in the array.",num);
} else {
printf("The number %d is not present in the array.",num);
}
}
INPUT/OUTPUT:
Enter size of array.
5
Enter 5 array elements one by one.
1
2
3
4
5
5
Enter the number you wish to look for.
The number 5 is present in the array.
You can see that Enter the number you wish to look for. should come before 5, but it is not so.
Solved
Simply fixed by removing \n from scanf.
In scanf, a space character already represents any whitespace. So in your "%d \n" the function already processes the new line right after the last digit, but then you force it to wait for another newline.
This causes the program to wait for yet another line. After it's input, the program continues and asks for the number to search, and at that point the input was already entered.
Just use only one space in scanf, it will already work for the newline, ideally before the digit itself so that you don't need one extra line to complete the operation:
scanf(" %d", arr + i);
The space in the input format string "%d \n" tells the input system to
consume... all available consecutive whitespace characters from the input
(described here)
So when you enter your last number 5, the system now tries to consume all whitespace characters. To do that, it waits for additional input, until it's not a whitespace. So, paradoxically or not, to consume spaces, the system has to read a non-space, which is the second 5 you input.
To fix this behavior, you can tell your system to input only a number, without consuming whitespace:
scanf("%d",&arr[i]);
However, this will leave the whitespace in the buffer, which may interfere with later input. To discard the whitespace, you can use various techniques, described e.g. here.
In my opinion, the most correct technique (however, maybe the most cryptic one) is
scanf("%d%*[^\n]%*c",&arr[i]);
%d - read the number
%*[^\n] - read a string, terminated by a newline byte; discard it and don't store it anywhere
%*c - read a byte (which is a newline byte); discard it and don't store it anywhere
BTW in your format string "%d \n", there are two whitespaces: a regular space and an end-of-line. They both tell scanf to consume all whitespaces in input. The effect is exactly the same as with one space "%d " or with one end-of-line "%d\n", so this particular format string may be highly confusing to whoever reads your code (including yourself).

scanf test failing inside a function in C

I'm trying to do a program with a simple game for a user to guess the number. My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 30
#define TRYING 5
void guessnumber(int, int, int *);
int main(void) {
int mytry = 1;
guessnumber(MAX, TRYING, &mytry);
if (mytry <= TRYING)
printf("Congratulations! You got it right in %d tries\n", mytry);
else
printf("Unfortunately you could not guess the number in the number of tries predefined\n");
printf("End\n");
return EXIT_SUCCESS;
}
void guessnumber(int _n, int _m, int *_mytry) {
srandom(time(NULL));
int generated = 0, mynum = 0, test = 0;
generated = rand() % (_n + 1);
printf("Welcome to \"Guess the number\" \n");
printf("A number between 0 and %d was generated\n", _n);
printf("Guess the number:\n");
while (*_mytry <= TRYING) {
test = scanf(" %d", &mynum);
if (test != 1 || mynum < 0 || mynum > MAX)
printf("ERROR: please enter a valid number \n");
else
if (mynum > generated)
printf("Wrong! The number your trying to guess is smaller\n");
else
if (mynum < generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry = *_mytry + 1;
}
}
Okay, now the program is working pretty ok except for one thing: the scanf test.
It works if I try to enter a number out of my range (negative or above my upper limit) but it fails if I for example try to enter a letter. What it does is that it prints the message of error _m times and then it prints "Unfortunately you could not guess the number in the number of tries predefined" and "End".
What am I doing wrong and how can I fix this?
In case, a character is entered, you're trying to detect it correctly
if(test!=1 ......
but you took no action to correct it.
To elaborate, once a character is inputted, it causes a matching failure. So the input is not consumed and the loop falls back to the genesis position, only the loop counter is increased. Now, the previous input being unconsumed, is fed again to the scanf() causing failure once again.
This way, the loop continues, until the loop condition is false. Also, for every hit to scanf(), as unconsumed data is already present in the input buffer, no new prompt is given.
Solution: You need to clean the input buffer of existing contents when you face a failure. You can do something like
while ((c = getchar()) != '\n' && c != EOF);
to clean the buffer off existing contents.
When you enter a letter, scanf() leaves the letter in the input stream since it does not match the %d conversion specifier. The simplest thing to do is use getchar() to remove the unwanted character:
if (test != 1) {
getchar();
}
A better solution would be to use fgets() to get a line of input, and sscanf() to parse the input:
char buffer[100];
while (*_mytry<=TRYING)
{
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
fprintf(stderr, "Error in fgets()");
exit(EXIT_FAILURE);
}
test=sscanf(buffer, "%d", &mynum);
if(test!=1 || mynum<0 || mynum>MAX)
printf ("ERROR: please enter a valid number \n");
else if(mynum>generated)
printf("Wrong! The number your trying to guess is smaller\n");
else if(mynum<generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry=*_mytry+1;
}
In the above code, note that the leading space has been removed from the format string. A leading space in a format string causes scanf() to skip leading whitespaces, including newlines. This is useful when the first conversion specifier is %c, for example, because any previous input may have left a newline behind. But, the %d conversion specifier (and most other conversion specifiers) already skips leading whitespace, so it is not needed here.
Additionally, your code has srandom() instead of srand(); and the call to srand() should be made only once, and probably should be at the beginning of main(). And, identifiers with leading underscores are reserved in C, so you should change the names _m, _n, and _mytry.

How to omit characters from an inputted number in C?

I'm new to C and have been playing about and having created a basic input output program for integers (See below) I was wondering how I would go about making my program omit characters from an inputted number and then print the number without said omitted characters so for example if I wanted it to omit non-primes 1234567 entered would print 2357. Here is my current code:
#include <stdio.h>
int main() {
int number;
// printf() dislpays the formatted output
printf("Enter an integer: ");
// scanf() reads the formatted input and stores them
scanf("%d", &number);
// printf() displays the formatted output
printf("You entered: %d", number);
return 0;
}

Sum of n numbers

#include <stdio.h>
int main()
{
int m,i,sum,num;
i=0;
sum=0;
scanf("%d ",&m);
while(i<m){
scanf("%d ",&num);
sum=sum + num;
i=i+1;
printf("Value of sum= %d\n",sum);
//continue;
}
printf("Sum= %d ",sum);
}
In the above code it should display the sum of n numbers. But in my code it is taking one extra value of m (m is number of values to take to compute the sum).
For example if I take m as 3 it takes 4 input and displays the sum of 3.
As others(#BLUEPIXY and #BillDoomProg) have already pointed in the comments, your problem is the space in your scanf format string. Also check this answer.
Change both your scanf format string from:
scanf("%d ",&m);
...
scanf("%d ",&num);
To:
scanf("%d", &m);
...
scanf("%d", &num);
Just remove the space and it will work fine.
scanf()
From the manual
The format string consists of a sequence of directives(...)
A directive is one of the following:
A sequence of white-space characters (space, tab, newline, etc.; see
isspace(3)). This directive matches any amount of white space, including
none, in the input.
Also note that stdin is buffered, so the results are a little different from what you would expect:
man stdin
Notes
The stream stderr is unbuffered. The stream stdout is line-buffered when
it points to a terminal. Partial lines will not appear until fflush(3) or
exit(3) is called, or a newline is printed. This can produce unexpected
results, especially with debugging output. The buffering mode of the
standard streams (or any other stream) can be changed using the setbuf(3)
or setvbuf(3) call. Note that in case stdin is associated with a terminal,
there may also be input buffering in the terminal driver, entirely
unrelated to stdio buffering. (Indeed, normally terminal input is line
buffered in the kernel.) This kernel input handling can be modified using
calls like tcsetattr(3); see also stty(1), and termios(3).
So, lets examine your program step by step.
Your program starts running and you enter the number 2. This is what the input buffer looks like:
2\n
scanf("%d ", &m) assigns 2 to the m variable and starts trying to match a space. It gets a NL and EOL. Control is still with this scanf because it just matched a newline (considered a white-space) and is waiting to match more, but instead it got the End-Of-Line, so it is still waiting when you type:
1\n
Then reads stdin again and realizes that the next character in the input stream is not a space and returns (it's format string condition was done). At this point, you enter the loop and your next scanf("%d ",&num) is called and it wants to read an integer, which it does: it reads 1 and stores that in the num variable. Then again it starts matching white-spaces and gets the new-line and it repeats the above pattern. Then when you enter:
2\n
That second scanf gets a character different than a white-space
and returns, so your loop scope keeps executing printing the current sum.
The loop break condition is not met, so it starts again. It calls the
scanf and it effectively reads an integer into the variable, then the
pattern repeats itself...
3\n
It was waiting for a white-space but it got a character instead. So your
scanf returns and now the loop break condition is met. This is where you exit your loop, prints the whole sum and get that weired felling that it
"added" 3 numbers but the sum is adding only the first 2 (as you intended
in the first place).
You can check that 3 hanging in stdin with a simple addition to your code:
#include <stdio.h>
int main()
{
int m, i, sum, num;
char c;
i = 0;
sum = 0;
scanf("%d ", &m);
while (i < m) {
scanf("%d ", &num);
sum = sum + num;
i = i + 1;
printf("Value of sum= %d\n", sum);
}
while((c = getchar()) != '\n')
printf("Still in buffer: %c", c);
return 0;
}
That will output (with the above input, of couse):
$ ./sum1
2
1
2
Value of sum= 1
3
Value of sum= 3
Still in buffer: 3
This is because you have a space after your %d in the scanf lines.
Change
scanf("%d ",&num);
To
scanf("%d",&num);
Scanf usually ignores whitespaces, so you don't want spaces in your format strings.
It's causes of extra space in scanf(). Change scanf("%d ",&num) to scanf("%d",&num)
From Scanf(), fscanf(), You can follow this.
The scanf() family of functions reads data from the console or from a
FILE stream, parses it, and stores the results away in variables you
provide in the argument list.
The format string is very similar to that in printf() in that you can
tell it to read a "%d", for instance for an int. But it also has
additional capabilities, most notably that it can eat up other
characters in the input that you specify in the format string.
You should write:
int main()
{
int m,i,sum,num;
i=0;
sum=0;
scanf("%d",&m);
while(i<m){
scanf("%d",&num);
sum=sum + num;
i=i+1;
printf("Value of sum= %d\n",sum);
//continue;
}
printf("Sum= %d ",sum);
}
A refactored code will look like this
#include <stdio.h>
int main() {
int m, num, sum = 0;
scanf("%d", &m); // Let scanf automatically skip whitespace
while (m--) {
scanf("%d", &num);
sum += num;
}
printf("Sum= %d\n", sum);
return 0;
}

Ambigious nature of scanf taking input before it is asked to enter from user?

#include<stdio.h>
void main(){
int num1,num2;
printf("\n Enter number 1 \t "); // Ask for input one. >>>>>>>> line 1.
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
printf("\n Enter number 2 \t "); // Ask for input Two. >>>>>>>>> line 2.
scanf("%d ",&num2);
printf("\n Entered number is %d \n",num2);
return;
}
I wish to know REASON.Please do provide it.
The code above accepts two inputs,first input is asked(By executing line 1) then user enter one number then terminal should ask to enter second input but instead it is taking other number(before executing line2 ) and then asking to enter second input(i.e after executing line 2).
In the End is is displaying the two input that are taken before executing line two but after executing line 1.
I am confused.I am interested to know reason.
I am using GCC 4.8.2 on ubuntu 14.04 64 bit machine.
Remove spaces between the scanf of access specifier.
scanf("%d ",&num1);
to
scanf("%d",&num1);
Because the scanf get the another value due to that spaces.
And kept in the buffer. After the memory has got it get assigned.
It is for all scanf function.
if I input like
Enter Number1 1
2
Entered number is 1
Enter number2 3
Entered number is 2.
It is better to use int main() and in the end write return 0;
use fflush(stdout); to flush your buffer.
After editing here is the final code
#include<stdio.h>
int main(){
int num1,num2;
printf("\n Enter number 1 \t "); // Ask for input one. >>>>>>>> line 1.
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
printf("\n Enter number 2 \t "); // Ask for input Two. >>>>>>>>> line 2.
fflush(stdout);
scanf("%d ",&num2);
printf("\n Entered number is %d \n",num2);
return 0;
}
Here is the Demo.
You need to put
fflush(stdout);
before the scanf
This will flush your buffer
(also a good idea to check the return value of scanf)
You have given a space in scanf for %d. If you remove that space after %d the program will run
Let's take this apart slowly
#include <stdio.h>
// void main(){
int main(void) {
int num1, num2;
printf("\n Enter number 1 \t ");
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
...
Use a proper function signature for main() - but that is not the main issue.
Code prints "\n Enter number 1 \t "
"%d" directs scanf() to scan for text convertible to an int in 3 steps:
A: Scan for optional leading white-space like '\n', '\t', ' '. Throw them away.
B: Scan for text representing an integer like "+1234567890". If any digits found, save the converted result to the address &num1.
C: Scanning continues in step B until a char that does not belong to the int is found. That char is "un-read" and returned to stdin.
(This is where you get in trouble as suggested by #Chandru) " " directs scanf() to scan for any number (0 or more) white spaces including '\n', '\t', ' ' and others. Then they are thrown away - not saved.
B: Scanning continues!! until a non-white-space is found. That char is "un-read" and returned to stdin.
Lastly scanf() return the value of 1 as that is how many field specifiers were converted. Code sadly did not check this value.
Recall stdin is usually line buffered, which means input is not available to user IO until Enter is hit.
User enters 1 2 3 Enter and scanf() scans the "123" and saves 123 to &num1. Then it scans "\n" as that is a white-space in step 4. and it continues waiting for more white-space.
User enters 4 5 6 Enter and the first scanf() which is not yet done, scans '4', sees it is not a white space and puts '4' back in stdin. scanf() finally returns after 2 lines are entered. At this point "456\n" are waiting in stdio for subsequent scanf().
The second scanf() then perpetuates the issue.
Recommend use fgets() only for all user input, at least until your are very skilled in C.
printf("\n Enter number 1 \t ");
char buf[100];
fgets(buf, sizeof buf, stdin);
if (sscanf(buf, "%d", &num1) != 1) Handle_BadInput();
else printf("\n Entered number is %d \n",num1);

Resources