I'm creating a temperature converter in C. Basically, you input a minimum and maximum value in degrees Celsius, along with a step, and it displays that information in a list, along with the Fahrenheit equivalent. On some occasions, I have noticed the last Fahrenheit entry not being displayed when it should. For example, when you input a lower limit of 10, a higher limit of 30, and a step of 4, it cuts off the last Fahrenheit temperature. I know it's something to do with the last while loop, but I just can't figure it out.
#include <stdio.h>
int main (int argc, const char * argv[]) {
double l, h, s;
double lf, hf, sf;
/* Number rows in tables */
int num1, num2;
num1 = 1;
num2 = 1;
/* Lower limit input */
printf("Please give a lower limit: ");
scanf("%4lf", &l);
while (l < 0) {
printf("Lower limit must be greater than 0: ");
scanf("%4lf", &l);
}
/* Stores value for Fahrenheit conversion */
lf = l;
/* Higher limit input */
printf("Please give a higher limit: ");
scanf("%4lf", &h);
while (h <= l) {
printf("Higher limit must be greater than lower limit: ");
scanf("%4lf", &h);
}
while (h >= 50000) {
printf("Higher limit must be less than 50000: ");
scanf("%4lf", &h);
}
hf = h;
/* Step input */
printf("Please input step: ");
scanf("%4lf", &s);
while (s <= 0) {
printf("Step must be greater than 0: ");
scanf("%4lf", &s);
}
while (s >= h - l) {
printf("Step must be less than the difference in temperatures: ");
scanf("%4lf", &s);
}
sf = s;
/* Celsius table */
printf("\nCelsius\n-------\n");
while (l <= h) {
printf("%i. %4lf\n", num1, l);
num1++;
l = l + s;
}
/* Fahrenheit table */
printf("\nFahrenheit\n----------\n");
/* Converts Celsius to Fahrenheit */
lf = (lf * 1.8) + 32;
hf = (hf * 1.8) + 32;
sf = sf * 1.8;
printf("Lower input: %4lf\n", lf);
printf("Higher input: %4lf\n", hf);
printf("Step: %4lf\n----------\n", sf);
/* This while loop sometimes cuts off the last entry */
while (lf <= hf) {
printf("%i. %4lf\n", num2, lf);
num2++;
lf = lf + sf;
}
return 0;
}
The problem is with comparing the doubles, you might get into a situation where something like 10 + 1.8 evaluates to 11.800000001 and thus missing the end value.
The solution to your problem would be to first calculate the number of steps:
int steps = (h - l) / s + 1; //Might want to apply rounding
And then use a for/while loop over the integer variable instead:
for (int i = 0; i < steps; ++i) {
double t = l + (h - l) * i / (steps - 1);
}
for (int i = 0; i < steps; ++i) {
double tf = lf + (hf - lf) * i / (steps - 1);
}
while (lf <= hf)
You are comparing Double values, You will face problems of Precison & Rounding Errors, Most likely that causes the last iteration to not execute at all.
This answer of mine, should be a good read.
Choose a precision and compare it with the difference between hf and lf(abs value).
Also keep in mind with a random fixed step you will not always reach the top value of the interval. it might work if step divides h-l but it won't work otherwise.
Directly after your last while loop, add the following code (and don't forget to #include assert.h):
printf("lf = %f, hf = %f\n", lf, hf);
assert(lf == hf);
you should get this output:
Celsius
-------
1. 10.000000
2. 14.000000
3. 18.000000
4. 22.000000
5. 26.000000
6. 30.000000
Fahrenheit
----------
Lower input: 50.000000
Higher input: 86.000000
Step: 7.200000
----------
1. 50.000000
2. 57.200000
3. 64.400000
4. 71.600000
5. 78.800000
lf = 86.000000, hf = 86.000000
Assertion failed: lf == hf, file randomdudescode.c, line 77
Which is incredibly confusing, because obviously lf == hf.
This illustrates one of the quirks of C and floating point tomfoolery in general. You have to deal with rounding errors and imprecision.
Related
Our activity requires to input 4 numbers, positive or negative and only add the negative numbers.
Example:
-30.22
10.50
-2.2
-1.8
Result is -34.22 which sums up the negative numbers only.
We have not discussed the loop or array at this moment. Is it possible to solve in a mathematical equation? I can’t seem to find any answers if I try to code it.
Can it be solved using if-else-elseif statements?
Read the input into four variables, then use four if statements to add them to the total when they're negative.
float a, b, c, d;
scanf("%f %f %f %f", &a, &b, &c, &d);
float total = 0;
if (a < 0) {
total += a;
}
if (b < 0) {
total += b;
}
if (c < 0) {
total += c;
}
if (d < 0) {
total += d;
}
printf("%.2f\n", total);
You can also use the conditional operator.
float total = (a < 0 ? a : 0) + (b < 0 ? b : 0) + (c < 0 ? c : 0) + (d < 0 ? d : 0);
These assignments some teachers invent are really pathetic.
Maybe you want this:
#include <stdio.h>
int main(void)
{
float a, b, c, d;
scanf("%f %f %f %f", &a, &b, &c, &d);
float total = (a < 0 ? a : 0) + (b < 0 ? b : 0) + (c < 0 ? c : 0) + (d < 0 ? d : 0);
printf("%f", total);
}
No loops, no if/else.
But be aware that this is really terrible code.
A solution that doesn't use neither if nor while (and co.)
int main(void) {
float n1 = 0, n2 = 0, n3 = 0, n4 = 0;
printf("Insert first number: ");
scanf("-%f", &n1);
scanf("%*[^\n]");
printf("Insert second number: ");
scanf(" -%f", &n2);
scanf("%*[^\n]");
printf("Insert third number: ");
scanf(" -%f", &n3);
scanf("%*[^\n]");
printf("Insert fourth number: ");
scanf(" -%f", &n4);
scanf("%*[^\n]");
float sum = -n1 - n2 - n3 - n4;
printf("Sum of all negative numbers: %f\n", sum);
return 0;
}
Explanation
scanf("-%f", &n1) will have two possible behaviors:
in case of positive numbers (e.g.: 3.14 or +1.2), it will fail to parse the input (because it isn't able to match the first - symbol), so variable n1 stays 0;
in case of negative numbers (e.g.: -5 or -3.1), it will match the minus symbol and put the rest of the number into n1 (so n1 is either 5 or 3.1, for instance).
Basically, for all four numbers, if the user input is positive, n is 0; if the input is negative, n is the absolute value of the number (2.0 instead of -2.0 etc).
scanf("%*[^\n]") will clear the input buffer after (possible) positive numbers (because scanf() won't match positive numbers).
float sum = -n1 - n2 - n3 - n4 is a (weird) "sum", but necessary since all four numbers are either 0 or the negation of a negative number.
DISCLAIMER
This answer is considered bad practice and its technique should never be used in real programs. The only purpose of this answer is to prove that there exists a solution to OP's problem that doesn't use loops nor conditionals. Every C programmer should however use loops and/or conditionals to make their code cleaner and safer (look at the other answers for a "good" solution).
This is the code for finding the numerical solutions of 1D Heat Transfer Equation(well, possibly). The code is getting compiled but the console is not showing any output. The console is staying and not disappearing either. I have tried with getch() and getchar() also but the problem still persists. Please help!
Here's my code:
#include <stdio.h>
#include <math.h>
int
main (int argc, const char *argv[])
{
int a, p, tmax, tmin, l;
int i, j, n, o;
double m, T1, T2, x, al, H[l + 1][tmax + 1];
float k;
printf ("Enter the number of nodes: \n");
scanf ("%d", &a);
printf ("Enter the thickness of the wall: \n");
scanf ("%d", &l);
printf ("Enter the value of maximum time coordinate: \n");
scanf ("%d", &tmax);
printf ("Enter the value of minimum time coordinate: \n");
scanf ("%d", &tmin);
printf ("Enter the number of time steps: \n");
scanf ("%d", &p);
printf ("Enter the value of thermal diffusivity: \n");
scanf ("%f", &k);
printf ("Enter the value of initial temperature: \n");
scanf ("%lf", &T1);
printf ("Enter the values of temperature at both the boundaries: \n");
scanf ("%lf", &T2);
x = (l / (a - 1)); /*change in spacial coordinate*>
m = (tmax - tmin) / (p - 1); /*change in time coordinate*/
al = (k * (m)) / (pow (x, 2)); /*Formula for CFL constant*/
printf (" The vale of the constant is %lf\n", al);
printf ("the value of the constant should be less than 0.5 for the convergence of iterative
formula. \n");
for (o = 0; o <= tmax; o++)
{
H[0][o] = H[l][o] = T2; /*boundary condition*/
}
for (j = 1; j <= (l - 1); j++)
{
H[j][0] = T1; /*initial condition*/
}
if (al <= 0.5)
{
for (n = 0; n <= (tmax - 1); n++)
{
for (i = 1; i <= (l - 1); i++)
{
H[i][n + 1] =
H[i][n] + (al * (H[i + 1][n] - (2 * H[i][n]) + H[i - 1][n])); /* Iterative Formula for finding the temperature at each grid point*/
printf (" The value of Temperature[i,n] at [i,n] is:\n ");
printf ("%lf at %d , %d is", H[i][n], i, n);
printf ("\n");
}
}
}
else
{
printf ("Error! Solution is unstable. \n");
}
return 0;
}
What's wrong with my code?
Also, how can I take a mathematical function as input from the user instead of T2 in the place of the initial temperature? Sometimes, 1D unsteady heat transfer problems has initial temperature in the form of a mathematical function which can be algebric, trigonometric, hyperbolic etc. like in this problem
"Show that the solution of the ∂2θ/∂x2= ∂θ/∂t
satisfying the conditions (i) θ → 0 as t → ∞, (ii) θ = 0
when x = ±a for all values of t > 0, and (iii) θ = x when t = 0 and −a < x < a is
θ(x,t) = 2a/π ∑(n=1) to ∞((-1)^(n-1))(1/n)(sin(nπx/a) * (exp^((-((nπ)^2)* t)/a^2 )))"
So, I need to take a mathematical function as input from the user. Is there any way to do that using the C standard library? I found a way to do it using expression evaluator/parser but is there any other simpler way to solve this problem?
I have this code below which is suppose to generate the output of 11 dwarfs for input of 10 for dwarf height and values of 101, 102, 103, 104,105, 106, 107, 108, 109 as well as 110 for giant height then change to output of 12 dwarfs for values of giant height of 111-120 and so forth when the height of dwarf again is 10. Both 'n' and 's' have essentially the same solution: proper output of dwarfs for values of 101 - 109 but not correct output (should be 11, but gives 10) for the value of 110. What operators can be used to help with this. I am working on my operator usage and would strongly prefer not to use any conditional statements or if-then.
#include <stdio.h>
int main()
{
int g, d, n, s;
while(1)
{
printf("enter the heights of giant and drwafs: ");
scanf("%d%d", &g, &d);
n = g % d + (g/d) + (-g % d + 1) - (g%d + 1)/10;
s = g / d + 1;
printf("%d",s);
printf("it takes %d dwarfs to be "
"greater than or equal to giant.\n\n", s );
}
return 0;
}
Ceiling of integer division:
unsigned int dividend, divisor, c;
/* dividend != 0 && divisor != 0 */
c = 1 + ((dividend - 1) / divisor);
Your program would then look something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned int giant, dwarf, c;
printf("Height of giant: ");
scanf("%u", &giant);
printf("Height of dwarf: ");
scanf("%u", &dwarf);
/* the heights can't be 0 */
if (giant == 0 || dwarf == 0) {
printf("The heights need to be greater than 0.\n");
exit(EXIT_FAILURE);
}
/* ceil giant divided by dwarf */
c = 1 + ((giant - 1) / dwarf);
printf("It takes %u dwarfs to be as high "
"or higher than a giant.\n", c);
return 0;
}
You can use the NOT operator, if you have a remainder it will add 1, if you have no remainder it will just be the result of your division:
include <stdio.h>
int main()
{
int g, d, s;
while(1)
{
printf("enter the heights of giant and drwafs: ");
scanf("%d %d", &g, &d);
if (d <= 0 || g <= 0) // what if your user use 0 for the size of dwarf? ouch...
continue
s = g / d + !!(g % d);
printf("%d",s);
printf("it takes %d dwarfs to be "
"greater than or equal to giant.\n\n", s );
}
return 0;
}
NB: This solution works with giant = INT_MAX
Requirements for this task are as follows:
Read floating point values from stdin, each separated by a newline, and terminated by EOF.
The input values are in the range [-100,000 to +100,000].
The input will contain at least one floating-point value.
The input may contain blank lines: these should be ignored.
Apart from possible blank lines, the input is otherwise well-formed.
At EOF, output:
the smallest value seen
the largest value seen
the arithmetic mean of all the values seen
all accurate to two decimal places.
The output values must be separated by a single space character and followed by a newline character.
Examples:
Input:
7
5.6
6
Output:
5.60 7.00 6.20
Input:
11
Output:
11.00 11.00 11.00
In my code when I input 7, 5.6, and 6, my output is 5.60 7.00 5.77.
I know where the issue is but not sure how to fix it. My total variable says its value at EOF is 17.322826 which is definitely not correct.
#include <stdio.h>
int main() {
int i = 0;
float big = 0;
float small = 1000000;
float total;
float div = 0;
while (i == 0) {
float a = 0;
float flag = scanf("%f", &a);
if (flag == EOF) {
printf("%.2f %.2f %.2f %f %f\n", small, big, total / div, total, div);
break;
}
if (a > big) {
big = a;
}
if (a < small) {
small = a;
}
div++;
total = total + a;
}
return 0;
}
You forgot to initialize total to 0.
Further notes:
the classic C idiom for an infinite loop is for (;;) { ... }.
flag should be defined as an int
you should stop the loop when flag != 1 instead of just flag == EOF. An invalid input will cause the program to loop endlessly. You can actually drop this variable completely.
initializing big to 0 and small to 1000000 is incorrect: what if all values are negative? what if they are all very large?
Here is a corrected version:
#include <stdio.h>
int main(void) {
float a, big, small, total;
int div;
if (scanf("%f", &a) != 1)
return 1;
big = small = total = a;
div = 1;
while (scanf("%f", &a) == 1) {
if (big < a) {
big = a;
}
if (small > a) {
small = a;
}
div++;
total += a;
}
printf("%.2f %.2f %.2f\n", small, big, total / div);
return 0;
}
Hello Stack Community!
I am having trouble calculating the correct average for 10 integers.
The expected output average is supposed to be 140.0 with one integer value recognized as not a positive program by the compiler.
This is what I have compiled, and it recognized the negative integer but the average still comes to 150.0
Just trying to figure out what I am missing here.
Thanks!
#include <stdio.h>
int main ()
{
/* variable definition: */
int count, value, sum;
double avg;
/* Initialize */
count = 0;
sum = 0;
avg = 0.0;
// Loop through to input values
while (count < 10)
{
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum = sum + value;
count = count + 1;
}
else {
printf("Value must be positive\n");
}
}
// Calculate avg. Need to type cast since two integers will yield an integer
avg = (double) sum/count;
printf("average is %lf\n " , avg );
return 0;
}
Values are: 100 100 100 100 -100 100 200 200 200 200
You want to read exactly 10 positive numbers, with count from 0 to 9.
After reading 100 100 100 100 -100 100 200 200 200 200 the value of count is 9 (because -100 neither added to the sum nor counted), which is less that 10 so the loop is executed one more time.
This time scanf() fails, so value remains unchanged; effectively you are reading another 200.
This is why the sum of the numbers is 1500 and the average 150.
AlexP found the explanation: you must check the return value of scanf(), otherwise, you will silently accept input that is not a number and reuse the last converted value.
Also note that the cast in avg = (double) sum/count; applies to sum and binds stronger than /. It is considered good style to make this more explicit by writing avg = (double)sum / count;
Here is a modified version of your program:
#include <stdio.h>
int main(void) {
/* variable definitions */
int count, value, sum;
double avg;
/* Initializations */
count = 0;
sum = 0;
avg = 0.0;
// Loop through to input values
while (count < 10) {
printf("Enter a positive Integer\n");
if (scanf("%d", &value) != 1) {
break;
}
if (value >= 0) {
sum = sum + value;
count = count + 1;
} else {
printf("Value must be positive\n");
}
}
// Calculate avg.
// Need to type cast to force floating point division instead of integer division
if (count > 0) {
avg = (double)sum / count;
printf("average is %f\n", avg);
}
return 0;
}
If I understand your problem correctly, this is what you want to do :
int last_known_positive_value = 0;
// Loop through to input values
while (count < 10)
{
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum = sum + value;
last_known_positive_value = value;
}
else {
printf("Value must be positive\n");
sum = sum + last_known_positive_value;
}
count = count + 1;
}
check-answer-here
There are a number of different ways to approach the problem. (1) you can read your values as a string with fgets and then call sscanf and gain the benefit of a NULL return from fgets indicating EOF and a test of the buffer containing only '\n' to indicate a user pressed [Enter] to signal end of input.
(2) you can read the values numerically with scanf and then check for EOF to indicate end of input, or some other predetermined sentinel.
Regardless of which you choose, the approach is basically the same. (a) make a call to the function you are using for input, (b) check the RETURN, and (c) validate the value input is within the required range, and handle the data.
You get the drift, on all input, check the return of your read function and handle any error or EOF condition, then validate the input is within the expected range.
A quick example using your code and reading numeric values with scanf could be something like:
#include <stdio.h>
int main (void) {
/* define/initialize variables */
int count = 0, value = 0, sum = 0;
double avg = 0.0;
while (1) { /* infinite loop to process input */
int rtn;
printf ("Enter a positive Integer ([ctrl+d] to quit): ");
if ((rtn = scanf ("%d", &value)) != 1) {
if (rtn == EOF) { /* always handle user cancellation of input */
putchar ('\n'); /* tidy up with POSIX line ending */
break; /* on to final calculation */
}
}
if (value < 0) /* check out of range */{
printf ("Value must be positive\n");
continue; /* try again */
}
sum = sum + value; /* compute sum */
count = count + 1; /* increment count */
}
/* Calculate avg. (typecast to avoid integer division) */
avg = count > 0 ? (double) sum/count : 0; /* protect div by zero */
printf ("\n (%d/%d) => average: %lf\n", sum, count, avg);
return 0;
}
Example Use/Output
$ ./bin/sumavg < <(echo "100 100 100 100 -100 100 200 200 200 200")
Enter a positive Integer ([ctrl+d] to quit):
<snip>
(1300/9) => average: 144.444444
One common thread running between all complete examples is to always handle a manual EOF generated by the user allowing them to cancel an individual input, or input as a whole (you decide based on your needs). On Linux the manual EOF is generated by [ctrl+d] on windoze [ctrl+z].
Look all answers over and let me know if you have any questions related to the above.
while (count < 10) {
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum += value;
count++;
}
else {
printf("Value must be positive\n");
count++;
}
}
This will increment "count" even if negative integer is inputted.
Thus you will get the desired average.