Limiting a loop in C - c

I have wrote a program for an assignment. The problem I am having is that I can not figure out how to make a for loop that limits the amount of data that can be entered. For example, for this assignment the user can enter lets say 100 grades. Any advice on how and where to add the for loop?
#include <stdio.h>
#include <stdlib.h>
/* Kimberly Brand - IT2240 * 05/17/2022
*/
int main (void) {
// defines a max of 100
#define maxnum 100
int i, grade[maxnum], maxentered;
i = 0;
printf ("Welcome! \n");
printf ("Please enter your grades, enter -1 when finished \n\n");
// while statemtn accepts numbers over 0
while (i < 100) {
printf ("please enter your grade ");
scanf ("%i", & grade[i]);
// ends program if - 1 is entered
if (grade[i] == -1) { //max entered only accepts 100
maxentered = i;
i = 100;
} else
i++;
}
printf ("Your grades are :\n");
for (i = 0; i < maxentered; i++) {
// displays grade entered
printf ("%i", grade[i]);
printf ("\n");
}
printf ("Thank you!\n");
}

while is a looping construct, and you do already limit the amount of data that can be read.
If you initialize maxentered to maxnum (for the event where the limit is met before the user enters -1), and change the bounds of the loop as well (to avoid the magic number 100 that may not be kept in sync with the size of the array), this program will work just fine (assuming scanf never fails).
#include <stdio.h>
#include <stdlib.h>
/* Kimberly Brand - IT2240 * 05/17/2022
*/
int main (void) {
// defines a max of 100
#define maxnum 100
int i, grade[maxnum], maxentered = maxnum;
i = 0;
printf ("Welcome! \n");
printf ("Please enter your grades, enter -1 when finished \n\n");
// while statemtn accepts numbers over 0
while (i < maxnum) {
printf ("please enter your grade ");
scanf ("%i", & grade[i]);
// ends program if - 1 is entered
if (grade[i] == -1) { //max entered only accepts 100
maxentered = i;
i = 100;
} else
i++;
}
printf ("Your grades are :\n");
for (i = 0; i < maxentered; i++) {
// displays grade entered
printf ("%i", grade[i]);
printf ("\n");
}
printf ("Thank you!\n");
}
That said, it can be cleaned up somewhat.
Always check the return value of scanf is the expected number of successful conversions that took place. We are looking for one conversion to occur, so we want the return value to be 1.
Once the loop is complete, the original indexing variable can be thought of as holding the length of the valid entries in the array. This can just be reused as the new bound when accessing the data.
size_t is the appropriate type for indexing memory and dealing with object sizes. While it does not matter all that much for smaller data structures, it is a good habit to practice.
#include <stdio.h>
#define MAX_ENTRIES 100
int main(void) {
int grades[MAX_ENTRIES];
size_t len = 0;
printf("Welcome!\nPlease enter your grades, enter -1 when finished.\n\n");
while (len < MAX_ENTRIES) {
printf("Please enter your grade: ");
if (1 != scanf("%d", &grades[len])) {
fprintf(stderr, "Failed to read input.\n");
return 1;
}
if (grades[len] == -1)
break;
len++;
}
printf("Your grades are:\n");
for (size_t i = 0; i < len; i++)
printf("[#%zu] %d\n", i + 1, grades[i]);
printf("Thank you!\n");
}

Instead of setting i directly to 100, you can use a break statement to exit the loop.
https://en.cppreference.com/w/cpp/language/break
// ...
while (i < 100) {
printf ("please enter your grade ");
scanf ("%i", & grade[i]);
// ends program if - 1 is entered
if (grade[i] == -1) { //max entered only accepts 100
maxentered = i;
break; // <<< NEW
} else
i++;
}
// ...

Do you mean you want to change the while loop you have for a for loop?
Your while loop already limits the amount of data pretty successfully.
while (i < 100) {
printf ("please enter your grade ");
scanf ("%i", & grade[i]);
// ends program if - 1 is entered
if (grade[i] == -1) { //max entered only accepts 100
maxentered = i;
i = 100;
} else
i++;
}
If you where to change (i < 100) for (i < 5) your code would limit the amount of entries in the array to 5 even though it could store 100 entries.
But a for-loop is probably better than a while loop in this scenario. It would look something like this:
for(i = 0; i < 100; i++){
//And then just add the code you want to execute inside
//I would recommend using a 'break;' statement instead of relying
//on 'i = 100' to break out of the loop.
}
As a side note, you never gave maxentered a default value, so your program will crash if you never type -1 but instead type as many grades as your loop lets you.

Related

Sorting array elements to find the largest and smallest number in C

I'm solving this problem where I need to give some inputs, find the largest and smallest among them. Here is the problem statement
Ivan Vasilyevich came to the market and decided to buy two watermelons: one for himself and another for the wife's mother. It is clear to choose for himself the heaviest watermelon, and for mother-in-law the lightest. But there is one problem: there are many watermelons and he does not know how to choose the lightest and the heaviest one. Help him!
Input
The first line contains the number of watermelons n (n ≤ 30000). The second line contains n numbers, each number is a mass of corresponding watermelon. All weights of watermelons are positive integers and do not exceed 30000.
Output
Print two numbers: the weight of watermelon that Ivan Vasilyevich will buy for his mother-in-law and the weight of watermelon that he will buy himself, or print the message "Ooops!" (without quotes), if someone left without watermelon
Here's my code
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, w[30000], gw, lw;
scanf("%d", &n);
n = abs(n);
for (i = 0; i < n; i++)
{
scanf("%d", &w[i]);
}
if (n >= 2)
{
for (i = 0; i < n; i++)
{
if (w[0] < w[i])
w[0] = w[i];
gw = w[0];
}
for (i = 0; i < n; i++)
{
if (w[0] > w[i])
w[0] = w[i];
lw = w[0];
}
printf("%d %d", lw, gw);
return 0;
}
else
{
printf("Ooops!");
return 0;
}
}
I'm getting wrong answer(96/100). What am I getting wrong?
You do not need to allocate space for an array of 30k integers to find the min and max weights entered.
First, initialize min and max weights to the first integer entered and then update min and max accordingly as you read more weights. Use the variable cur (an integer) to store the last integer (i.e. weight) read.
That way, you do it all in one pass, rather than in multiple loops.
If you use scanf, it is good practice to check it's return value. For reference (from the C99 standard):
The scanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
In our case, when our scanf call is of the form scanf("%d", &a) where a is some int, we expect the call scanf("%d", &a) to return 1.
While it is good practice to check the return value, it is not absolutely necessary. If this is a program for one of your classes and you have never worked with the return value of scanf, you could remove all the checks for the return value below and the program should function the same. That said, it would show great initiative if you do check for the return value and reference the C standard in your justification for checking it (as the return value provides very useful information).
#include <stdio.h>
#include <stdlib.h>
#define MAX_WAT 30000 /* maximum number of watermelons */
int main(void) {
int n, i, min, max, cur;
/* prompt user for number of watermelons */
printf("Enter number of watermelons: ");
/* read integer, checking return value of scanf as expected */
if (scanf("%d", &n) != 1) {
printf("error in scanf\n");
exit(EXIT_FAILURE);
}
if (n > MAX_WAT) {
printf("Please enter less than %d watermelons.\n", MAX_WAT);
return 0;
}
/* if zero or one watermelons, at least one person leaves without */
if (n <= 1) {
printf("Ooops!\n");
return 0;
}
/* initialize min, max to first integer and update
min, max accordingly as new weights are read */
printf("Enter weights of %d watermelons: ", n);
scanf("%d", &cur);
min = max = cur;
for (i = 1; i < n; i++) {
if (scanf("%d", &cur) != 1) {
printf("error in scanf\n");
exit(EXIT_FAILURE);
}
if (cur < min)
min = cur;
if (cur > max)
max = cur;
}
printf("Ivan Vasilyevich: %d\nMother: %d\n", max, min);
return 0;
}
Example Session 1:
Enter number of watermelons: 5
Enter weights of 5 watermelons: 2 5 1 9 10
Ivan Vasilyevich: 10
Mother: 1
Example Session 2:
Enter number of watermelons: 1
Ooops!
Example Session 3:
Enter number of watermelons: 30001
Please enter less than 30000 watermelons.
do not modify your original array
initialize your gw and lw
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, w[30000], gw, lw;
scanf("%d", &n);
n = abs(n);
for (i = 0; i < n; i++)
{
scanf("%d", &w[i]);
}
if (n >= 2)
{
gw = w[0];
for (i = 0; i < n; i++)
{
if (gw < w[i]) gw = w[i];
}
lw = w[0];
for (i = 0; i < n; i++)
{
if (lw > w[i]) lw = w[i];
}
printf("%d %d", lw, gw);
return 0;
}
else
{
printf("Ooops!");
return 0;
}
}

A question about break statement in c programming

I wrote this loop to add numbers, and the break to get out of the loop if the number entered is less than zero, and in last print the calculated numbers without adding the negative number. but the problem is even I wrote the break statement before the addition when I enter 15 and 15 and -2 the output is 28 rather than 30
I found out how to fix that, what I want to know is why
and thank you.
#include <stdio.h>
void main()
{
int j = 1, num = 0, rslt = 0;
while (1) {
if (num < 0) break;
printf("enter a number : ");
scanf("%d", &num);
rslt = rslt + num;
}
printf("the resluts are %d\n", rslt);
}
Currently, you are effectively testing the input of the previous iteration, after already adding it to your result. Instead, check the number immediately after the user enters it, before you perform any calculations.
#include <stdio.h>
int main(void)
{
int num = 0, rslt = 0;
while (1) {
printf("enter a number : ");
scanf("%d", &num);
if (num < 0)
break;
rslt += num;
}
printf("the results are %d\n", rslt);
}
You might also want to check that scanf returns the number of successful conversions you were expecting (in this case one), to handle the event where the user enters invalid input.
if (1 != scanf("%d", &num))
break;

Why is this for loop getting ignored? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I'm not sure what i'm doing wrong but the for loop is not initializing
The code just goes immediately to displaying the printfs. That have no values in them since the for loop didn't activate
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define PAUSE system("Pause")
main() {
// INITALIZE VARIABLES
int number = 0;
int i = 0;
int odd = 0;
int even = 0;
int totalNum = 0;
int tempNum = 0;
int count;
printf("Enter a number between 2 and 25\n");
scanf("%i", &number);
do{
if (number < 2 || number > 25)
printf("That was an invalid number please try again\n");
scanf("%i", &number);
} while (number < 2 || number > 25);
printf("Enter how many numbers you want to input\n");
scanf("%i", &count);
for (i = 1; i == count; ++i){
printf("input numbers\n");
scanf("%i", &tempNum);
if (tempNum % 2 == 0)
even++;
else
odd++;
totalNum = totalNum + tempNum;
} // END FOR LOOP
// DISPLAY OUTPUT
printf("You entered %i numbers\n", count);
printf("The sum of the %i numbers is %i\n", count, totalNum);
printf("The average of the %i numbers is %i\n", count, totalNum / count);
printf("You entered %i odd numbers and %i even numbers\n", odd, even);
PAUSE;
} // END MAIN
Your loop will only execute at best once, when count == 1 as you initialize i to 1.
If you enter a 1 for count,
printf("Enter how many numbers you want to input\n");
scanf("%i", &count);
the loop will run exactly once, until i increments to 2
You probably want:
for (i = 1; i <= count; ++i){
do{
if (number < 2 || number > 25)
printf("That was an invalid number please try again\n");
scanf("%i", &number);
} while (number < 2 || number > 25);
it should be...
do{
if (number < 2 || number > 25){
printf("That was an invalid number please try again\n");
scanf("%i", &number);
}
} while (number < 2 || number > 25);
else it asks always another number
i = 1, so i == count; gives false therefore the loop is ignored.
A for loop in C works like this:
for ( variable initialization; condition; variable update ) {
/* Do something... */
}
The loop will execute for as long as condition is true. So, when you do:
for (i = 1; i == count; ++i)
The loop will execute for as long as i == count is true. So, unless count holds 1 when this line is executed, the loop will never run.
As others pointed out, you probably want this:
for (i = 1; i <= count; ++i)
So your loop will run for all values of i, until it reaches count.
As a side note i should point out that the usual way to write for loops in C is something like this:
for (i = 0; i < count; i++)
We start with i = 0 because C arrays are zero-based, so the Nth element of an array has index n-1
You were so close. In addition to fixing your loop test clause for (i = 1; i <= count; i++), I would suggest using " %d" for your format specifier. Your do loop need only be a while loop to avoid printing your invalid number message every time.
Additionally, While not an error, the standard coding style for C avoids caMelCase variables in favor of all lower-case. See e.g. NASA - C Style Guide, 1994.
With those changes, (and changing your odd/even check to a simple &) you could write your code as follows.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
// #define PAUSE system("Pause")
int main (void)
{
int number, i, odd, even, totalnum, tempnum, count;
number = i = odd = even = totalnum = tempnum = count = 0;
printf ("enter a number between 2 and 25: ");
scanf (" %d", &number);
while (number < 2 || number > 25) {
printf ("invalid number, again (between 2 and 25): ");
scanf (" %d", &number);
}
printf ("numbers to input: ");
scanf (" %d", &count);
for (i = 1; i <= count; i++) {
printf ("input number %2d: ", i);
scanf (" %d", &tempnum);
if ((tempnum & 1) == 0)
even++;
else
odd++;
totalnum = totalnum + tempnum;
}
printf ("You entered %d numbers\n", count);
printf ("The sum of the %d numbers is %d\n",
count, totalnum);
printf ("The average of the %d numbers is %d\n",
count, totalnum / count);
printf ("You entered %d odd numbers and %d even numbers\n",
odd, even);
// PAUSE;
return 0;
}
note: main is type int (e.g. int main (int argc, char **argv) or simply int main (void) to indicate no arguments taken). Since it is type int it will return a value to the shell. While historic implementations may have allowed void main that is no longer the case for portable code.
Example Use/Output
$ /bin/forskipped
enter a number between 2 and 25: 4
numbers to input: 4
input number 1: 1
input number 2: 2
input number 3: 3
input number 4: 4
You entered 4 numbers
The sum of the 4 numbers is 10
The average of the 4 numbers is 2
You entered 2 odd numbers and 2 even numbers
Look it over and let me know if you have any questions.

Printf: pops out after the break statement

Being at the very beginning of learning programming,
C in particular, I am struggling with how to restrict
printf only to the valid outputs, i.e. to make sure
that printf does not appear after the "break" statement.
I understand that my test for scanf is within the for
loop, and when i reaches 3 the for loop stops and printf
appears. I hope to find the correct way to both test
scanf, and make sure printf doesn't appear after
the break statement (in case user types in integers).
// a program that calculates the average of an array
of 3 floating-point values and check if correct inputs
are types in scans (only floating values)
#include <stdio.h>
#include <stdbool.h>
int main (void)
{
float values[3];
float element, average;
float sum = 0;
int i, n;
bool is_float;
printf ("Please, enter 3 floating values: \n");
for ( i = 0; i < 3; i++)
{
scanf ("%f", &element);
is_float = 1;
n = (int) element;
if (n - element == 0 || element == 0 )
{
is_float = 0;
printf ("Sorry, invalid input\n");
break;
}
else
{
values[i] = element;
sum += values[i];
}
}
printf ("The average of 3 values is %.2f\n", sum / 3);
return 0;
}
Thank you!
If you want the program to exit directly after this line:
printf ("Sorry, invalid input\n");
then you must replace the break statement directly below that printf line with something like this:
return 1;
On another note, when you want to print error messages, you should use fprintf() instead of printf(). The entire for loop would look like this:
for (i = 0; i < 3; i++)
{
scanf ("%f", &element);
is_float = 1;
n = (int) element;
if (n - element == 0 || element == 0 )
{
is_float = 0;
fprintf (stderr, "Sorry, invalid input\n");
return 1;
} else {
values[i] = element;
sum += values[i];
}
}

For loop guessing game in C

a program to get the user to guess the number that the program has picked as the lucky number. It uses one for loop and plenty of if statements. The problem is that my code stops after 2 tries, but suppose to give user 3 tries. Here is what I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int iSecret, iGuess;
srand(time(NULL));
iSecret = rand() % 20 + 1;
int tries = 0;
printf("\nWelcome to the number guessing game!\nFor each game, you have at most 3 chances to guess a secret number from 1 to 20.\n");
for (tries = 0; tries < 3 || iSecret == iGuess; tries++)
{
printf("Please, enter a number between 1 and 20! ");
scanf("%d", &iGuess);
if (iGuess == iSecret)
{
printf("\nCongratulations! You won!");
return 0;
}
else if (iGuess > iSecret)
{
tries++;
printf("\nYour guess was too high.\n");
}
else if (iGuess < iSecret)
{
tries++;
printf("\nYour guess was too low.\n");
}
if (tries == 3)
break;
}
printf("\nYou have reached your third trials. The correct number is %d.\n",
iSecret);
return 0;
}
You are incrementing tries twice: once in the for definition, and also later in the body of the loop.
Remove the extra tries++ statements.
You increment tries inside the code, as well as in the for statement. Strip out the tries++ statements in the if-blocks.
You're incrementing the variable tries multiple times during loop execution,
once every turn and everytime you didn't guess your secret right
for loop already increments tries .. you don't need to do tries++ inside if statements
you don't need the || condition in for loop as you are already doing the check in if statements
here is the fixed code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int iSecret, iGuess;
srand ( time(NULL) );
iSecret = rand() % 20 + 1;
int tries = 0;
printf("\nWelcome to the number guessing game!\nFor each game, you have at most 3 chances to guess a secret number from 1 to 20.\n");
for (tries = 0; tries < 3 ; tries++) {
printf ("Please, enter a number between 1 and 20! ");
scanf ("%d", &iGuess);
if(iGuess == iSecret){
printf ("\nCongratulations! You won!");
return 0;
}
else if (iGuess > iSecret){
printf ("\nYour guess was too high.\n");
}
else if (iGuess < iSecret){
printf ("\nYour guess was too low.\n");
}
}
printf ("\nYou have reached your third trials. The correct number is %d.\n", iSecret);
return 0;
}
Output:
$ ./test
Welcome to the number guessing game!
For each game, you have at most 3 chances to guess a secret number from 1 to 20.
Please, enter a number between 1 and 20! 2
Your guess was too low.
Please, enter a number between 1 and 20! 3
Your guess was too low.
Please, enter a number between 1 and 20! 4
Your guess was too low.
You have reached your third trials. The correct number is 10.
in addition to incrementing tries too many times, the code is overly complicated, you can simplify the logic like
int main ()
{
int iSecret, iGuess;
srand ( time(NULL) );
iSecret = rand() % 20 + 1;
int tries = 0;
printf("\nWelcome to the number guessing game!\nFor each game, you have at most 3 chances to guess a secret number from 1 to 20.\n");
for (tries = 0; tries < 3; tries++) {
printf ("Please, enter a number between 1 and 20! ");
scanf ("%d", &iGuess);
if(iGuess == iSecret) {
printf ("\nCongratulations! You won!");
return 0;
}
printf ( "\nYour guess was too %s.\n", iGuess>iSecret?"high":"low");
}
printf ("\nYou have reached your third trials. The correct number is %d.\n", iSecret);
return 0;
}

Resources