Scanf repeats itself in C - c

This is a simple program in which the user enters a series of numbers which are then added. The result is printed on the screen. Here's the code:
int main() {
int * numbers;
int result = 0;
int howMany;
int i;
printf("How many numbers would you like to add?\n");
scanf(" %d\n", &howMany);
numbers = (int *) malloc(howMany * sizeof(int));
for(i = 0; i < howMany; i++){
printf("Please enter number %d.\n", i + 1);
scanf(" %d\n", &numbers[i]);
result = result + numbers [i];
}
printf("Result: %d", result);
return 0;
}
But there is a problem. The program asks for how many numbers the user would like to add twice for some reason. Why is that? How can I fix it?
Also, not sure if this is related but the results also make no sense. Sometimes they are correct, other times they aren't, not sure why either.
Thanks.

The program asks for how many numbers the user would like to add twice for some reason. Why is that? How can I fix it?
Your program prompts me only once for how many numbers. It does, however, defer asking for each specific number until after I enter it, and then it requires an extra non-blank line after the last (late) prompt before it outputs the result.
Also, not sure if this is related but the results also make no sense. Sometimes they are correct, other times they aren't, not sure why either.
It is related: the fact that the per-number prompts are late is confusing you about which numbers are being added.
This all comes down to your scanf() formats, as #Mark already remarked (albeit somewhat tersely). Any nonempty run of whitespace, including newlines, in a scanf() format matches a possibly-empty run of whitespace. When it is matching such a run, scanf() has to keep scanning until it sees a non-whitespace character. Interactive input is line-buffered, however, so no new input is available to it until you send a whole new line. Then the first non-whitespace character on that next line is ready and waiting for the following scanf().
scanf() can be quite tricky to use correctly, especially for interactive input. It is best suited for fixed-format input. You can do this with scanf() -- #Mark showed you how -- but the usual recommendation around here is to use fgets() to read input one line at a time, and sscanf() (or your choice of other mechanism) to parse each line. Even that can be a challenge to make bullet-proof, but you start out on firmer footing.

Your problem was because of your erroneous placement of the newline characters in your printf and scanf functions.
Here is the code you are probably looking for:
int main() {
int * numbers;
int result = 0;
int howMany;
int i;
printf("How many numbers would you like to add?: ");
scanf("%d", &howMany);
numbers = (int *) malloc(howMany * sizeof(int));
for(i = 0; i < howMany; i++){
printf("Please enter number %d: ", i + 1);
scanf("%d", &numbers[i]);
result = result + numbers [i];
}
printf("Result: %d\n", result);
return 0;
}

Related

How to set the limit of the for loop to work until end of line/until specific string is reached

So I'm basically trying to make a for loop that scans the input line. The input is always one double float number and then one string. It continues scanning until the string = is reached. Each number value is stored to an array of double and each string to an array of char.
Problem is that the input line can be arbitrarily long and I don't know how to make it
The program should work as a basic calculator which reads one double float, then one operator as a string, and performs operation. If another number follows, then perform the operation with this number. If the equal sign = is reached, the program outputs the result.
int main() {
double res;
double in[10];
char *op[10][5];
int arrCheck[10];
for(int i=0; i<=5; i++) {
scanf("%lf %s ", &in[i], op[i]);
arrCheck[i] = opCheck(op[i]);
}
return 0;
}
This is the main section of my program so far. I managed to get it working and storing the data correctly. Although it always works only on predefined limit (i<=5, for instance). Is it legal to write condition like:
for(i = 0; i<'\n'; i++), or i<=?
I would expect it to continue scanning and storing the data until it reaches the equal sign =.
Try this:
for(int i = 0; (i <= 5) && (strcmp(op[i], "=") != 0); i++) {
...
}
And on your question, it is not legal to compare integers with strings. This is why string comparing functions exist.
You can also break from for loop like this:
int main()
{
double res;
double in[10];
char op[10][5];
int arrCheck[10];
for(int i=0;i<=5;i++){
scanf("%lf %s ", &in[i], op[i]);
if (strcmp(op[i], "=") == 0)
break;
arrCheck[i] = opCheck(op[i]);
}
return 0;
}
Which is even better solution than the one posted previously.
Since you are reading with scanf and the "%s" conversion-specifier, you will consume leading whitespace before each operator stored in op[n]. There is no need to call strcmp, you can simply check the first character by dereferencing the pointer, e.g.
if (scanf ("%lf %s", &in[i], op[i]) != 2 || *op[i] == '=')
break;
A short example omitting opCheck(op[i]) not included in your question, you could do something similar to:
#include <stdio.h>
int main (void) {
double in[10];
char op[10][5];
int i = 0, n;
while (i < 10) {
if (scanf ("%lf %s", &in[i], op[i]) != 2 || *op[i] == '=')
break;
i++;
}
n = ++i;
puts ("\nequation: ");
for (i = 0; i < n; i++)
printf (" %g %s", in[i], op[i]);
puts (" res");
}
(note: the use of while (i < 10) rather than a for (i = 0; i < 10; i++). You do not want to increment i in case of a matching or input failure. You only increment i after validating both conversions succeeded)
Example Use/Output
$ ./bin/eqnread
5.1 + 6 - 2 + 25 * 4 =
equation:
5.1 + 6 - 2 + 25 * 4 = res
So I'm basically trying to make a for loop that scans the input line. The input is always one double float number and then one string.
If you care about lines specifically (which are ended by \n -or by \r on some operating systems), you cannot use scanf alone, because scanf deals with all kind of space characters (including the space, the tabulation, the newline, the formfeed characters) in the same way, so ignores the specificity of end of line characters (\n and/or \r).
So the good way is to read the entire line first with fgets (or getline(3) on Linux) and later to parse that line. Be careful about very long lines, they could happen.
How would you parse that read line is a different question: manual lexing and parsing, or sscanf, or strtok or strtod, etc... come to mind.
And you did not define what a string is for you. What about spaces inside it? What about input lines that are longer than what you expect (e.g. a line of a thousand characters)? The %s for scanf would stop at the first space.
Don't forget to read carefully the documentation of every used function. Learn How to debug small programs.
Be also aware that, practically speaking, in 2019 UTF-8 is used everywhere, and that may add complications to your scheme (and to what strings are in practice).
The program should work as a basic calculator
It seems that you then should care about operator precedence. Then, recursive descent parsing comes to mind.

C: Scanf function in for loops runs one more time than it should

In the following code, I want the user to input 10 floating point numbers, and then take the average of them. However, when running it, the user is forced to input 11 numbers, but the 11th one is discarded anyway. The value of the average actually turns out to be correct. I just want to know why the scanf seems to run 1 extra time.
The problem I faced was different than that of the suggested duplicate. Here, the problem was related to my understanding of the scanf function, I actually looped the correct amount of times.
see:
#include <stdio.h>
int main (void)
{
int i;
float entry[10];
float total = 0.0;
printf("please enter 10 floating point numbers\n");
for (i = 0; i < 10; ++i)
scanf("%f\n", &entry[i]);
for (i = 0; i < 10; ++i) {
total = total + entry[i];
}
printf("The average of the 10 floating point numbers is: %f\n", total / 10);
return 0;
}
The \n in the format string is causing that.
Even after 10th element is entered, scanf waits for a non-whitespace character to be entered before it is done. After the 10 numbers have been entered, you can enter any old non-whitespace character to let scanf finish.
Remove the \n from the format string. You don't need it. Use
for (i = 0; i < 10; ++i)
scanf("%f", &entry[i]);
Remove \n inside the scanf i.e. inside the first for loop, write :
scanf("%f",&entry[i]);

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

scanf() to iterate through an unknown quantity of integers

So I'm trying to find the sum of an unknown amount of user-input numbers. Here's my code
int main()
{
int tmp1 = 1;
int tmp2 = 1;
int total = 0;
printf("Enter numbers for a sum: ");
tmp2 = scanf(" %d", &tmp1);
while(tmp2 > 0){
total+=tmp1;
tmp2 = scanf(" %d", &tmp1);
}
printf("total is %d", total);
return 0;
}
It gets stuck in an endless loop, and then once i hit ctrl-c to end it, it prints the correct sum. So what I'm doing wrong is how will i know when it's done scanning all the integers, and for the loop to end; since i'm not doing it correctly now
Decided to make it stop via ctrl d, and its acceptable. thanks
In your question, it is not clear how you expect your programme to understand that there won't be anymore numbers to input. Shall it be through a specific character? Or shall it just get a line of space-separated numbers and respond with a sum?
From your code, my most sensible guess is: You want it to understand that there won't be any more numbers to add, whenever it encounters a non-digital character. My guess is so, because this is almost exactly what your code does by checking the return value from scanf.
First of all, you have to change that tmp inside your loop into tmp1 because there isn't such a variable as tmp declared. edit: well, never mind
Then try running your programme, putting in any amount of white-space (space, tab or new-line) separated numbers, and then any non-digital character you like. May be a T for example, or ThoAppelsin, it won't matter. Programme won't get beyond the first character, in fact, not even beyond the first character. After that, you shall see that the numbers have been properly added together.
Since you're confused about a non-existent infinite-loop, my second guess is that you might be actually hoping it to get a single line of space-delimited numbers, and have the sum printed; and misinterpret your programme as "in infinite loop" while it merely expects further input from you, just like it does at the very beginning.
You won't get a 0 from non-redirected scanf("%d", &var);, unless you feed it with something that doesn't match to the format string to cause abnormal termination. If there's nothing left in the input stream to consume, it will just wait for more input. But say you give an 'a' to it, then all it can do is to give up and return zero, because it couldn't do a single assignment.
If you really are hoping to have a single line of numbers, then the minimal change I could offer would be something like this:
int main(void)
{
int tmp1 = 1;
char tmp2 = 0;
int total = 0;
printf("Enter numbers for a sum: ");
scanf("%d%c", &tmp1, &tmp2);
while(tmp2 == ' '){
total+=tmp1;
scanf("%d%c", &tmp1, &tmp2);
}
printf("total is %d", total);
return 0;
}
Of course, this approach has many vulnerabilities. However, if user is to input strictly a sequence like:
3 66 2 10 6
// mind the new-line
It will work fine. But if I'm allowed to change more than minimal, this is how I would do it:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int main(void)
{
int LastNumber = 0;
int UpcomingCharacter = 0;
int Total = 0;
printf("Enter numbers for a sum: ");
while(scanf("%d%*[ \t]", &LastNumber) == 1)
{
Total += LastNumber;
UpcomingCharacter = getchar( );
if (!isdigit(UpcomingCharacter)) // eliminates a possible EOF return as well
break;
if (ungetch(UpcomingCharacter, stdin) != UpcomingCharacter)
{
fprintf(stderr, "%d: unexpected error with ungetch\n", __LINE__);
return EXIT_FAILURE;
}
}
printf("total is %d", Total);
return EXIT_SUCCESS;
}
Which should work fine on any whitespace-delimited sequence of numbers, excluding the new-lines of course.

Functions and arrays

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

Resources