Printf: pops out after the break statement - c

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

Related

Limiting a loop in 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.

Why are my values for sum and count being lost each loop?

I'm getting a consistent divide by zero error, even though each loop should be populating the variables. Code below:
#include <stdio.h>
void calculateAverage()
{
int grade, count, sum;
double average;
sum = 0;
count = 0;
grade = 0;
average = 0.0;
int coolvalue = 0;
while (coolvalue==0)
{
scanf("%d", &grade);
if (grade == -1)
{
sum, sizeof(double);
count, sizeof(double);
average = (sum / count);
printf("%lf", &average);
break;
}
else
{
if ((grade > 100) || (grade < -1))
{
printf("Error, incorrect input.\n");
break;
}
else
{
sum = +grade;
count = count + 1;
return count;
return sum;
}
}
}
coolvalue = 1;
}
int main(void)
{
while (1)
calculateAverage();
while (1) getchar();
return 0;
}
Even while using return, I'm not able to properly increment the value of sum or count.
There are multiple issues in your code.
scanf("%d", &grade); - you don't check the value returned by scanf(). It returns the number of values successfully read. If you enter a string of letters instead of a number, scanf("%d") returns 0 and it does not change the value of grade. Because of this the code will execute the rest of the loop using the previous value of grade. You should restart the loop if the value returned by scanf() is not 1:
if (scanf("%d", &grade) != 1) {
continue;
}
Assuming you enter 10 for grade this block of code executes:
sum = +grade;
count = count + 1;
return count;
return sum;
sum = +grade is the same as sum = grade. The + sign in front of grade doesn't have any effect. It is just the same as 0 + grade.
You want to add the value of grade to sum and it should be sum += grade. This is a shortcut of sum = sum + grade.
return count makes the function complete and return the value of count (which is 1 at this point) to the caller. The caller is the function main() but it doesn't use the return value in any way. Even more, your function is declared as returning void (i.e. nothing) and this renders return count incorrect (and the compiler should warn you about this).
return sum is never executed (the compiler should warn you about it being dead code) because the function completes and the execution is passed back to the caller because of the return count statement above it.
Remove both return statements. They must not stay here.
If you enter -1 for grade, this block of code is executed:
sum, sizeof(double);
count, sizeof(double);
average = (sum / count);
printf("%lf", &average);
break;
sum, sizeof(double) is an expression that does not have any effect; it takes the value of sum then discards it then takes the value of sizeof(double) (which is a constant) and discards it too. The compiler does not even generate code for it.
the same as above for count, sizeof(double);
average = (sum / count);:
the parenthesis are useless;
because both sum and count are integers, sum / count is also an integer (the integral result of sum / count, the remainder is ignored).
you declared average as double; to get a double result you have to cast one of the values to double on the division: average = (double)sum / count;
if you enter -1 as the first value when the program starts, count is 0 when this code is executed and the division fails (division by zero).
printf("%lf", &average); - you want to print the value of average but you print its address in memory. Remove the & operator; it is required by scanf() (to know where to put the read values). It is not required by printf(); the compiler generates code that passes to printf() the values to print.
break; - it passes the execution control after the innermost switch or loop statement (do, while or for). It is correct here and makes the variable coolvalue useless. You can simply remove coolvalue and use while (1) instead.
All in all, your function should look like:
void calculateAverage()
{
int sum = 0;
int count = 0;
int grade = 0;
double average = 0.0;
while (1) {
if (scanf("%d", &grade) != 1) {
// Invalid value (not a number); ignore it
continue;
}
// A value of -1 signals the end of the input
if (grade == -1) {
if (count > 0) {
// Show the average
average = (double)sum / count;
printf("Average: %lf\n", average);
} else {
// Cannot compute the average
puts("You didn't enter any value. Cannot compute the average.\n");
}
// End function
return;
}
if ((grade < -1) || (100 < grade)) {
puts("Error, incorrect input.\n");
// Invalid input, ignore it
continue;
}
sum += grade;
count ++;
}
}
Quite a few corrections need to be made.
The while loop in the calculateAverage() function. That's an infinite loop buddy, because you are not changing the value of that coolValue variable anywhere inside, instead you make it 1 only when it exits the loops, which it never will.
So, use while(1) {...}, and inside it, check for the stopping condition, i.e, if (grade == -1) { ... } and inside it calculate and print the average and return. This will automatically break the while.
You're not checking if the input grade is actually a valid integer or not. Check the value of scanf for that, i.e, use if (scanf("%d", &grade) != 1) { ... }
The expression sum = +grade; is just another way of writing sum = 0+grade which in turn is nothing but sum = grade. Replace this with sum += grade;. This is the right way to write a shorthand for addition.
Two return statements..a very wrong idea. First of all, a function can have just one return(in an obvious way I mean, at once). Secondly, the function calculateAverage() is of return-type void. there's no way how you can return double value from it. So remove these two statements.
I have attached the code below which works. Also do go through the output which I have attached.
CODE:
#include <stdio.h>
void calculateAverage()
{
int grade, count = 0, sum = 0;
double average;
printf("\nenter the grades... enter -1 to terminate the entries\n.");
while (1) {
printf("\nEnter the grade: ");
if (scanf("%d", &grade) != 1) {
printf("\nInvalid characters entered!!!");
continue;
}
else if(((grade > 100) || (grade < -1))) {
printf("\nInvalid grade entered!!!");
continue;
}
else {
if (grade == -1) {
average = sum/count;
printf("\nAverage value of grades: %.3lf",average);
return;
}
else {
sum += grade;
count++;
}
}
}
}
int main(void)
{
calculateAverage();
return 0;
}
OUTPUT:
enter the grades... enter -1 to terminate the entries.
Enter the grade: 50
Enter the grade: 100
Enter the grade: 60
Enter the grade: -1
Average value of grades: 70.000
Perhaps it is better for the function to be of type double instead of void. Although it is not my favorite solution it is close to what you want.
#include <stdio.h>
double calculateAverage(void)
{
double average;
int sum = 0, count=0, grade;
while (1)
{
scanf("%d", &grade);
if ((grade > 100) || (grade < -1))
printf("Error, incorrect input.\n");
else if (grade != -1)
{sum = sum+ grade; count = count + 1;}
else
break;
}
if (count==0)
average=-1.0; //none valid input. Notify the main()
else
average=(double)sum/count;
return average;
}
int main(void)
{
double result;
result= calculateAverage();
if (result!=-1.0)
printf("\n average= %lf",result);
else
printf("No grades to calculate average");
getchar();
return 0;
}

Undefined reference error to function that is actually defined in C

I wrote this program to build a number diamond. The issue is that when I compile the program, it throws the error
build2.c:(.text+0x5): undefined reference to `get_input'
collect2: error: ld returned 1 exit status
I've tried for hours to figure out what exactly the problem is (e.g. if there is a spelling mistake or something similar), but the function call looks identical. I have attempted to rename it, write it as both a prototype and as an implementation, and nothing seems to work. Is there an issue that I'm not seeing?
//Define prior to main
int is_valid(int);
int get_input(void);
void print_pattern(int);
//Main
int main(void){
int diamond_size;
//diamond_size = get_input();
//value from get imput method used for diamond size
print_pattern(get_input());
return 0;
}
void print_pattern(int size){
int length, num, i, j;
//beginning of new diamond
printf("\n");
//Define each integer to work in layout of diamond
//First for loop fans out
for(i=1; i <= size; i += 2){
length = size-i+1;
num = 1;
printf("%*s", length," ");
for(j = 0; j < i; j++){
printf("%d ", num);
num++;
}
printf("\n");
}
//second for loop fans in
for(i=size-2; i >= 1; i -= 2){
length = size-i+1;
num = 1;
printf("%*s", length," ");
for(j = 0; j < i; j++){
printf("%d ", num);
num++;
}
printf("\n");
}
int is_valid(int value){
int rem;
//uses remainder to determine if it is odd or even; an even number will not have a reaminder in this case
rem = value % 2;
if (rem == 0){
printf("You've entered a even number. Please try again.\n");
return (0);
}
//greater than 9 cnd
if (value > 9){
printf("You have entered a number greater than 9. Please try again.\n");
return (0);
}
//less than 1 cnd
if (value < 1){
printf("You have entered a number less than 1. Please try again.\n");
return (0);
}
return (1);
}
int get_input()
{
int cont, number, valid;
cont = 1;
while (cont = 1)
{
printf("Enter an odd number less than 9 and greater than 0 < ");
scanf("%d", &number);
valid = is_valid(number);
if (valid == 1)
{
cont = 0;
}
}
return number;
}
}
You seem to have nested functions; this is (a) a non-standard GCC extension, and (b) I presume the scope of the nested get_input() function is the enclosing function, not the file scope. The solution is to move get_input() to file scope. At the end of print_pattern() add an extra }, and delete the final } at the end of the file.
Also, please format your code - most IDEs these days have options to tidy it up, and with correct indentation you may have seen your problem earlier.
Oh, and as a bonus bug fix, you also have in get_input():
while (cont = 1)
This will always be true - use this instead:
while (cont == 1)
The function print_pattern is not terminated at proper place but instead at the very end of the file:
void print_pattern(int size){
...
... end of the loop
}
... more functions
...
... end of print_pattern
}
This results into defining nested functions instead of global level.
It's generally good habit to indent the blocks, in which case you would realized the mistake very quickly.

Program to compute the average of values: if to test chars

Please, take a look at a program that prompts the user to enter 3 values and computes the average of these values.
I decided to add a test condition that checks if the user has entered a number or a character.
// a program that calculates the average of an array of 3 floating-point values; with for loop
#include <stdio.h>
int main (void)
{
float values[3];
float element;
float sum = 0;
int i;
printf ("Please, enter 3 floating values: \n");
for ( i = 0; i < 3; i++)
{
if (scanf ("%f", &element) == 1)
{
if ( (element >= 'a' && element <= 'z') || (element >= 'A' && element <= 'Z') )
printf ("Sorry, you have entered letters\n");
else if (element <= 0)
printf ("Please, enter positive values\n");
else
values[i] = element;
sum += values[i];
}
}
printf ("The average of 3 values is %.2f\n", sum / 3);
return 0;
}
When I run the program, I get the following problems:
1) it seem to work with positive numbers;
2) when I try to enter negative numbers, the program does print the required statement, but the result is still incremented into i, hence lowering the number of further entries; also, even if the number is negative, the program still comes up with some average nonsense value.
Please, enter 3 floating values:
-75
Please, enter positive values
98
Sorry, you have entered letters
-786.9
Please, enter positive values
The average of 3 values is 2087205705198174400484999168
3) when I test the program with letters, it still returns some average, though a zero one:
Please, enter 3 floating values:
jklj
The average of 3 values is 0.00
I would be grateful for your help!
Your element will never contain letters, since you've declared it as float and scanned it as float. If you wish to know if you were given a letters, you should read a string, test it, and only then convert it to float (comparing element to 'a' is actually comapring it to the ASCII code of 'a' = 97).
About the wrong sum - you forgot the curly braces for your else block. Change it to:
else {
values[i] = element;
sum += values[i];
}
If you want your program to end if negative numbers are entered you can use the return statement or deincrement the value of i for more cases. As for letter it never enters the if block so you can use an else. Try the following:
#include <stdio.h>
int main (void)
{
float values[3];
float element;
float sum = 0;
int i;
printf ("Please, enter 3 floating values: \n");
for ( i = 0; i < 3; i++)
{
if (scanf ("%f", &element) == 1)
{
if (element <= 0)
{
printf ("Please, enter positive values\n");
i--; // or use the return statement
}
else
{
values[i] = element;
sum += values[i];
}
}
else
{
printf("You entered special characters");
return;
}
}
printf ("The average of 3 values is %.2f\n", sum / 3);
return 0;
}

How to select multiple elements in an array with C?

Is there a way to select multiple elements in array using one line of code in C? For instance, say I had the following code (assuming I already asked the user for twenty numbers, the first ten I asked to be positive and the last ten I asked to be negative):
if (myArray[0 through 9] > 0)
{
printf("Thank you for providing positive numbers!");
}
else
{
printf("Sorry, please try again!");
}
if (myArray[10 through 19] < 0)
{
printf("Thank you for providing negative numbers!");
}
else
{
printf("Sorry, please try again!");
}
What code could I substitute for "through"? I am fairly new to this language, and have never heard of a way of doing so. I know that with this particular code I could make two arrays, one for the positive numbers and one for the negative numbers, but I am curious to know for other programming projects.
Thank you for reading and answering!
There's nothing built-in that does it, you need to write a loop. Don't forget that array indexes start at 0.
int all_positive = 1;
int i;
for (i = 0; i < 10; i++) {
if (myArray[i] <= 0) {
all_positive = 0;
break;
}
}
if (all_positive) {
printf("Thank you for providing positive numbers!\n");
}
int a[20];
// entering values for the array
_Bool first_positive = 1;
for ( size_t i = 0; i < 10 && first_positive; i++ )
{
first_positive = 0 < a[i];
}
if ( first_positive ) puts( "Hura, first 10 elements are positive" );
_Bool last_negative = 1;
for ( size_t i = 10; i < 20 && last_negative; i++ )
{
last_negative = a[i] < 0;
}
if ( last_negative ) puts( "Hura, last 10 elements are negative" );
Instead of type name _Bool you can use type int if your compiler does not support _Bool
The program requests number of rows (1D array).
Then asks for 2 integers, whole numbers.
Then asks user to select 2 rows.
The sum of the 2 selected rows is then added.
#include <stdio.h>
int main ()
//1D_Array. Load Element and Add Sumline .
//KHO2016.no5. mingw (TDM-GCC-32) . c-ansi .
{
//declare
int a,b,c,d,e,sum1=0;
int array[50];
int i,j,elm1,elm2;
//valuate
printf ("Plot a number of elements [1 - 20]: ");
scanf ("%d",&a);
printf ("Plot a value : ");
scanf ("%d",&b);
printf ("Plot an increment value : ");
scanf ("%d",&c);
//calculate
{for (i<0;i<=a;i++)
{array[i] =(b+(++c)); // set value for variable [i], inside the array subscript. the vairable [i] must have an INT, and an increment to function !
sum1 = (sum1 + array[i]);
printf ("Row [%.2d] : %.2d + %.2d = %d\n",i,b,c,array[i]);}
printf ("\nSum total = %d\n",sum1);}
printf ("\nRow [%.2d] = %d\n",b,array[b]);
printf ("Row [%.2d] = %d\n",a,array[a]);
printf ("Select 2 Rows :\n");
scanf ("%d%d",&elm1,&elm2);
d=elm1;
e=elm2;
printf ("You selected Row [%.2d] = %d\n",d,array[d]);
printf ("You selected Row [%.2d] = %d\n",e,array[e]);
printf ("The sum of two selected Rows [%d]+[%d] : %d + %d = %d\n",d,e,array[d],array[e],array[d]+array[e]);
//terminate
return 0;
}

Resources