scanf("%d", int) good yesterday, not today. What is going on? - c

I am getting comfortable with the foundations of C:-
There are two iterations of scanf() in this program. The first is fully functional.
The second appearance does nothing and instead quits the program and returns to the standard command prompt line.
Also, my second for loop only prints the first 4 numbers instead of 5.
Here is the code :
int main() {
int i;
int iNum[4]
int iMenu = 0;
printf("\n\n\tPlease enter five numbers: ");
for (i = 0; i < 4; i++) {
scanf("%d ", &iNum[i]);
}
printf("\n\tThank you. Here are your numbers: \n\t");
for (i = 0; i < 4; i++) {
printf("%d", iNum[i]);
}
printf("\n\tMenu:");
printf("\n1\tSort your numbers ascending.");
printf("\n2\tSort your numbers descending.");
printf("\n3\tQuit program");
printf("\n\nWhat would you like to do?\n\tEnter your option here: ");
scanf(" %d", &iMenu);
switch (iMenu) {
case 1:
printf("\nCase1testPrint");
sortAsc();
break;
case 2:
printf("\nCase2testPrint");
sortDesc();
break;
. . .//rest of code }
As soon as the program reaches the second scanf(), the program ends and returns to command prompt.
This is baffling, and I have tried many variations on what could be wrong. Please provide what you may.
Here is what it looks like if I run the program. Notice my entry "1" appears in the command line instead of the program:
C:\Users\Cortland\Documents\C projects>gcc arraysort.c
C:\Users\Cortland\Documents\C projects>a
Please enter five numbers: 3
6
5
4
5
Thank you. Here are your numbers:
3 6 5 4
Menu:
1 Sort your numbers ascending.
2 Sort your numbers descending.
3 Quit program
What would you like to do?
Enter your option here:
C:\Users\Cortland\Documents\C projects>1

Your for loop reads four numbers, not five.
You enter five numbers. The first four are read in the for loop. The fifth is read by
scanf(" %d", &iMenu);
So you've entered 3 6 5 4 as the four numbers, and then 5 as the choice of what to do. You haven't shown us the entire switch statement, but my guess is that it doesn't handle the value 5, and that it falls through and your program terminates.
(Also, you should always check the value returned by scanf(), and take some action if it indicates that the input operation failed.)

There are a couple of errors.
First off, the second line of your main() function contains a syntax error - there should be a semicolon at the end. This should stop your program from even compiling.
Second, even though you say you want the user to enter 5 numbers, your array and loops all use the number 4. The reason your program still allows you to enter five numbers, however, is because of how you've written the formatting string in your calls to scanf(). Instead of:
scanf("%d ", &iNum[i]);
use
scanf("%d", &iNum[i]);
Notice the lack of a space at the end of the formatting string? That's where your problems come in. Even though you are allowed to enter five numbers, the program only stores and checks four of them. The last number is stuck in the input stream - until, that is, your next call to scanf(). This fetches your last number, which is put through the switch/case statement (failing all cases, since you didn't input "1", "2" or "3"), and the program reaches the end of main() and exits. The "1" in the command line comes from trying to input something when the program has already ended.
Summarized:
1: Add the missing semicolon
2: Change the number used in the declaration of iNum and in the for loops from 4 to 5
3: Edit your scanf() calls, removing whitespace from the formatting strings.
This fixed the problem on my end.

Related

Are there better ways to clear stdin when looking for a specific kind of input in C?

fairly new programmer here just trying to understand if there is a better way to do this and hoping to get some feedback.
TL;DR: Is there a better way to clear stdin when looking for a specific input?
For some background, I've been learning C for the past 3 weeks and scanf() has been our "go to" function for user input. After looking around for answers to this question, I'm beginning to learn that scanf() is not always preferred.
In this part of the assignment that I'm working on, I created this while loop that is supposed to run while the user input is a nonzero, positive integer. It took a while, but to get to this point I now understand that if a string is inputted instead of an integer when scanf("%d", &variable); is assigned while using leads to an infinite loop as stdin does not get cleared.
I tried to solve this problem by checking to see the return of the scanf() functions, and running the loop while the return is equal or less than 0 (which would mean that the scanf() function broke and did not return anything since it saw a char instead of an int).
The thing is, the code seems to work great until we encounter one scenario, which is where we have characters followed by an integer.
For example:
Input = 1
program runs with no issues
Input = string
program runs loop, asks for new valid input
Input = string string
program runs loop, asks for new valid input
Input = 123string
program proceeds, but then next loop with an int scanf() is infinite. 123 is stored as an int to variable.
My current understanding of the issue is that scanf() reads the integers until we get to the characters and then "string\n" gets stored to stdin, creating an infinite loop in the next part. To solve the issue, I added a fflush(stdin); before the next integer scanf() loop which seems to work.
So my question is: Would somebody be willing to show me some other ways to do this other than adding a fflush(stdin); line before every int scanf() loop? I'm sure there are better ways but I don't rightly know who to ask and the internet seemed like a good resource. Thank you.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int squareLen = 0;
int numColors = 0;
int infiniteLoopStop;
// Asks for user input of desired Square Length
printf("Please enter the finished side length (in inches) of one square.\n> ");
while (squareLen < 1) {
infiniteLoopStop = scanf("%d", &squareLen);
if (infiniteLoopStop <= 0 || squareLen < 1) {
printf("\nInvalid input. Enter a nonzero, positive integer.\n> ");
fflush(stdin);
}
}
// Temporary solution to problem
fflush(stdin);
// Asks for int input of colors and loops while number of colors is not 2 or 3
printf("How many colors are you using? Enter 2 or 3.\n> ");
while (numColors < 2 || numColors > 3) {
infiniteLoopStop = scanf("%d", &numColors);
if (infiniteLoopStop <= 0 || numColors < 2 || numColors > 3) {
printf("Invalid, please enter 2 or 3.\n> ");
fflush(stdin);
}
}
printf("\n");
return 0;
}

Un-expected program result (addition of letters)

In my recently begun quest to learn C one of the first things I have made is a very basic "sum of 2 numbers program".
/* Basic addition prog */
#include <stdio.h>
int main(void) {
int v_1; /* first var */
int v_2; /* second var*/
int answer; /* Sum of 2 vars*/
printf("Simple addition calculator \n");
printf("enter first number: ");
scanf("%d", &v_1);
printf("enter second number: ");
scanf("%d", &v_2);
answer = v_1 + v_2;
printf("%d\n", answer);
}
When I run this and enter 2 numbers everything runs fine and I will get the correct answer.
The output will look like:
enter first number: 1
enter second number: 1
=2
I decided I'd try and break it by using letters instead of numbers expecting at first that I'd input 2 letters and it'd either convert them into numeric values or would error out and crash.
However this isn't what happens instead I get the following:
enter first number: a
enter second number: = 32765
My question isn't so much "how do I fix this" as it is "what is actually happening here?
EDIT
Again this question is more about trying to understand what is happening than trying to fix a problem. I'm not looking for "how can this be avoided?" I'm looking for "what causes it and why?"
Tl;Dr
I really can simplify what I want to know down to 2 questions.
Why am I getting unique junk data for each letter of the alphabet that I enter?
i.e 32764 for every time I enter a and 32767 every-time I enter b ?
Why does the second variable input get skipped ?
Check the result of scanf("%d", &v_1);. If it is not 1, v_1 is not updated.
Why does the second variable input get skipped ?
Entering non-numeric input for scanf("%d", &v_1); will neither consume that input nor change v_1.
That is also why scanf("%d", &v_2); did not wait for input, it tried to use the same input and also failed.
Why am I getting unique junk data for each letter of the alphabet that I enter? i.e 32764 for every time I enter a and 32767 every-time I enter b ?
Code is just getting the uninitialized values of v_1, v_2. An optimizing compiler may not even "create" v_1 until the scanf("%d", &v_1); and so the uninitialized v_1 may be dependent on the text entered. Since this is undefined behavior, the result may differ tomorrow or on another machine.
Try the same thing with initialized values.
int v_1 = 0; /* first var */
int v_2 = 0;

Wondering about while loop

I started learning C 3 weeks ago, and while learning while loops I tried to build an addition program, basically you keep adding numbers it additions them and after 2nd number it gives you a subtotal for every addition, and if you press 0 to quit It gives you a final sum then quits.
Now I have one main, one additional question. The main question is, I had to use sum = 0 before the while functions, if I use it after "the while" it gives me the number I entered as the result. Now I really wonder what is the idea behind it. When I write it like below does it equates "sum with 0"
for the start and changes the value as I enter another number, or there is some other idea behind it.
And the additional question is , why do I need to use 2 getchar(); to make my program stay on the screen, why not one?
#include <stdio.h>
int main(void)
{
float num;
float sum;
printf(" please enter a number +0 to start the program (0 to quit): \n");
scanf(" %f", &num);
sum =0; //THIS HERE**********************
while (num > 0)
{
printf("please enter integer:\n");
scanf("%f", &num);
sum = sum + num;
printf("current sum is = %f\n", sum);
}
printf("final sum is = %f\n", sum);
getchar();
getchar();
return 0;
}
If you put sum=0 inside the while loop it will be called each time the while loop loops.
This means when you reach sum=sum+num, you will actually be calculating sum=0+num.
You have two use two getchar() calls because the first one is sucking up an additional character that was not absorbed by your scanf. Probably this character is a newline, so you cannot see it. The second getchar() then keeps your terminal open because it is waiting for a character.
To figure out if my hypothesis is correct about the first getchar() you could try this:
char temp = getchar();
printf("%d",(int)temp); //Print out the character number from the first getchar
getchar(); //This keeps the window open
If I use it after the while it gives me the number I entered as the result.
This is because when you do this
while (num > 0) {
sum = 0;
...
sum = sum + num;
}
the value that has been accumulated by sum on prior iterations of the while loop gets erased each time the loop iterates, meaning that only the last value would be added to sum (and kept as the result of the additions).
why do I need to use 2 getchar();
Because when scanf consumes the last number the end-user has entered, it reads everything up to, but not including, the '\n' character, which corresponds to the Enter key. This '\n' character remains in the buffer, waiting to be consumed by your program. The first call of getchar() consumes that "lingering" '\n', while the second one makes your program stay on screen until you press enter again.
= in most programming languages is different from the mathematical =. It does not mean that the two sides will permanently be equal to each other; rather, it means that the right-hand side should be computed and that the result should be assigned to the variable on the left-hand side. Later, another line might change the variable value to something else.
Thus, sum = sum + num; means that the current values of sum and and num are to be added, and the result is to be put back into sum. In order for this to work the way you wish, sum must be 0 the first time this line is executed; hence, you need sum = 0; somewhere. However, if this line is inside the loop, it is repeatedly executed, so that the result of the previous summation disappears and is replaced with 0 before each new number.

Inputting Multiple values through Scanf - C

I am trying to solve an SPOJ problem. I am stuck here.
For the input, it asks me the following to take as input
Next line contain n elements, ai (1<=i<= n) separated by spaces.
I can use a loop and input each element given separately by the user through scanf. But as per the problem criteria, I am assuming that we need to take the input through scanf at once in a single line. Like scanf("%d %d %d", &a1 &a2 e.t.c).
But the range is like over 10^6, I am not sure how we can dynamically input multiple values through scanf in a single line.
You can run your iteration as you say, because scanf does not care what kind of whitespace separates integer inputs.
So: for (i = 0; i < n; ++i) scanf("%d", &array[i]); will work for inputs of the type:
3 2 1 2 3 8
as well as the type
3
2
1
2
3
8
Does not matter whether you input the numbers in a single line, this will work as scanf ignores the white spaces
int arr[1000001]; // Take an array to store the inputs
for(i=1;i<=n;i++)
{
scanf("%d",&arr[i]);
}

How to take 2 inputs in a single line in C language?

for(i=0;i<t;++i)
{
scanf("%d",&arr[i]);
scanf("%d",&brr[i]);
a=arr[i];
b=brr[i];
}
This code block is taking inputs in two separate line(after pressing enter),ex
12
45
How to modify it so that it take both the numbers in a single line(after pressing space),ex
12 45
How to modify it so that it take both the numbers in a single
line(after pressing space)
Your code already does this (it already works if you pass "12 45" - you can put any amount of whitespace between them). If you want to you can use a single scanf call with something like:
scanf("%d %d", &arr[i], &brr[i]);
When using scanf it is a wise decision to check the return code, i.e. the number of scanned elements.
rc = scanf(...);
if (rc != 2)
/* We scanned less than we expected! */

Resources