#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;
}
Related
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.
In my c class today I was troubling with the scanf() command, we were just learning pointers and we got a question asking us to get an array, and print it reversed without using the [] for anything but declaring the (int) array. Of course it seems like a piece of cake but not when you accidentally write:
scanf("%d ", arr + i);
Did you notice the space after the %d? Sure did take me a while to figure it out but for some reason that makes loops go crazy, and I wanted you guys to help me (and my teachers) to figure out why does that happen. Example:
#include <stdio.h>
#define LEN 10
void arrayInput(int * arr, unsigned int len);
void arrayReverseOutput(int * arr, unsigned int len);
int main(void)
{
int arr[LEN] = { 0 };
arrayInput(arr, LEN);
arrayReverseOutput(arr, LEN);
system("pause");
return 0;
}
void arrayInput(int * arr, unsigned int len)
{
unsigned int i = 0;
printf("Enter 10 numbers: ");
for (i = 0; i < len; i++)
{
//printf("i = %d \n", i); see what happens when you use this line
scanf("%d ", arr + i);
}
}
void arrayReverseOutput(int * arr, unsigned int len)
{
int i = 0;
printf("The numbers in reverse order: ");
for (i = --len; i >= 0; i--)
{
printf("%d ", *(arr + i));
}
}
I'm really curios to see what's going on with that scanf... it's as if it requires 2 inputs at the first time it runs but somehow still manages to put the inputs in their right position in the array...
Thanks for taking your time to read this <3
A space in the format string tells scanf() to match zero or more whitespace characters, until the match fails. Spaces (' '), newlines('\n'), carriage returns ('\r'), and tabs ('\t') are among the whitespace characters. When a space occurs at the end of a format string, scanf() will try to match whitespace characters from the input until no match is found. But, scanf() can only return when a match fails, or end of file is reached. Thus, in the case of a statement like:
scanf("%d ", arr + i);
the call to scanf() will appear to hang, greedily waiting for more input from the user. Whenever the Enter key is pressed, a newline is sent and matched by scanf(), which is still waiting for a failing match. Or end of file. You can escape such a loop by signalling end of file from the keyboard with Ctrl-D on Linux, or Ctrl-C on Windows.
It is almost always a mistake to terminate a scanf() format string with a space. A newline ('\n') is also a whitespace character, and has the same effect when placed at the end of a format string.
Note that spaces can be used effectively in scanf() format strings. For example:
int retval = scanf(" %c %c", &c1, &c2);
Here, if a previous IO operation has left a newline in the input stream (a not uncommon occurrence), the leading whitespace directs scanf() to read and ignore it. The second space in the format string tells scanf() to expect zero or more whitespace characters between the input characters to be converted. This allows the user to input the characters with an intervening space. Without the added whitespace, if a user entered a b\n, c2 would end up holding the value for a space character, and the b would be left behind in the input stream for the next IO operation to pick up. Also note that scanf() returns the number of successful conversions, allowing the program to check whether the input is as expected. If retval in the above line is anything other than 2, something has gone wrong.
I dont really uderstand the code below. How does it work exactly (I/O buffers I mean). I dont need a \ncharacter in my code an it still works! Can anyone explain it to me step by step?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int x = -1;
do
{
printf("Give x: ");
scanf("%d", &x);
}while(x<=0);
printf("x = %d\n", x);
x = -1;
while(x<=0)
{
printf("Give x: ");
scanf("%d", &x);
}
printf("x = %d\n", x);
return 0;
}
According to scanf's documentation on cplusplus.com:
Whitespace character: the function will read and ignore any whitespace characters
encountered before the next non-whitespace character (whitespace characters include
spaces, newline and tab characters -- see isspace). A single whitespace in the format
string validates any quantity of whitespace characters extracted from the stream
including none).
This is why you don't need to specify the \n in scanf the next scanf call will simply ignore it.
Stripping away the parts OP likely understand, look at the scanf() calls.
The "%d" format specifier says to scan though optional whitespace (space, tab, \n, etc.) and then scan an int. This typically continues until a character is encountered that does not belong to the int. Then that character is "ungotten" (put back in the input buffer).
Say your input was " 123 -456". After the first while loop " -456" would remain in the input buffer. The second while loop would consume the " -456". Assuming that stdin was closed after the -456, scanf() would then detect there is no more data and set x to the value -456. As x is still negative, the second while loop performs scanf() again. This time, no data and scanf() does not change x and returns EOF, which sadly is not monitored. Result: endless loop.
Now try " 123a 456". After the first while loop "a 456" would remain in the input buffer. The second while loop would call scanf() and fail to convert anything as a does not begin a number - thus x remains -1. scanf() would return 0, which unfortunately is not monitoring. The a, not begin consumed, would remain in the input buffer. The 2nd while loop again calls scanf() which would do the same thing resulting in an endless loop.
do {
...
scanf("%d", &x);
} while (x<=0);
...
x = -1;
while (x<=0) {
...
scanf("%d", &x);
}
Far better to use fgets()/sscanf() pair for input from user input.
(User input is evil!)
I write a C program to pick the data from the the std input, which starts with a number indicating the number of the data sets, then there are N pairs of data, in the form: (x y), so I write the code as below:
#include <stdio.h>
int main()
{
int n_sets;
scanf("%d", &n_sets);
int i;
for(i = 0; i < n_sets; ++i)
{
int m, n;
scanf("(%d %d)", &m, &n);
printf("%d\t%d\n", m, n);
}
return 0;
}
but it doesn't work. After I input the number of the data set, the program print the uninitialized m&n directly. But when I add a space before the (%d %d), it works fine. Somebody can explain this?
When you have character literals in your argument to scanf(), it expects to find those literals exactly as specified in the format string.
scanf("%d", &n_sets);
correctly reads n_sets, and stops at the newline or other whitespace character in the buffer. The next scanf() :
scanf("(%d %d)", &m, &n);
expects to find an open parenthesis at the beginning of the input, but finds a whitespace character instead. So it fails, and scanf() returns without having read anything. Consequently, your m and n remain uninitialized, and garbage results.
When you put in the space before the open parenthesis like so:
scanf(" (%d %d)", &m, &n);
it tells scanf() to skip any leading whitespace before the parenthesis in the input buffer, so the program works correctly.
change
scanf("%d", &n_sets);
to
scanf("%d\n", &n_sets);
and input your n_sets ending up with a [enter], it works.
Assuming your input is like this:
2 (1 2) (3 4)
There is a space(or new line?) after the first number, so change the scanf in the loop to:
scanf("\n(%d %d)", &m, &n);
// ^^
It sounds like the input into the program has some amount of whitespace before the value you want scanf to parse. The space in the string tells scanf to ignore whitespace. Without it, scanf is looking for an exact match immediately.
My little program below shall take 5 numbers from the user, store them into an array of integers and use a function to print them out. Sincerly it doesn't work and nothing is printed out. I can't find a mistake, so i would be glad about any advice. Thanks.
#include <stdio.h>
void printarray(int intarray[], int n)
{
int i;
for(i = 0; i < n; i ++)
{
printf("%d", intarray[i]);
}
}
int main ()
{
const int n = 5;
int temp = 0;
int i;
int intarray [n];
char check;
printf("Please type in your numbers!\n");
for(i = 0; i < n; i ++)
{
printf("");
scanf("%d", &temp);
intarray[i] = temp;
}
printf("Do you want to print them out? (yes/no): ");
scanf("%c", &check);
if (check == 'y')
printarray(intarray, n);
getchar();
getchar();
getchar();
getchar();
return 0;
}
Change your output in printarray() to read:
printf("%d\n", intarray[i]);
^^
That will add a newline after each number.
Normally, output written to the console in C is buffered until a complete line is output. Your printarray() function does not write any newlines, so the output is buffered until you do print one. However, you wait for input from the user before printing a newline.
Change to that:
char check[2];
And also that:
scanf("%s", check);
if (!strcmp(check,"y"))
printarray(intarray, n);
Hope that helped. Your scanf("%c", &check); failed. Instead of y you end up having NL (ASCII code 10), which means the if part fails.
I don't know if it a nice fix though. Maybe someone could give a better one. Keep in mind if you input something bigger (eg yess) you going to get a bit unlucky ;)
Aside from the suggestions about printing the \n character after your array (which are correct), you also have to be careful with your scanf that expects the "yes/no" answer. Muggen was the first one to notice this (see his answer).
You used a %c specified in your scanf. %c specifier in scanf does not skip whitespace, which means that this scanf will read whatever whitespace was left in the input buffer after you entered your array. You hit the "Enter" key after entering the array, which put a newline character into the input buffer. After that scanf("%c", &check) will immediately read that pending newline character instead of waiting for you to enter "yes" or "no". That's another reason your code does not print anything.
In order to fix your scanf, you have to force it to skip all whitespace characters before reading the actual answer. You can do that by scanf(" %c", &check). Note the extra space before %c. Space character in scanf format string forces it to skip all continuous whitespace beginning from the current reading position. Newline character happens to be whitespace, so it will be ignored by this scanf.
printf("%d", intarray[i]);
add new line after this