Building on what already exists
Most programs are edits of programs that already work. Learn to start from existing information and from the C library instead of from an empty file.
After this lesson
You should be able to
- Turn a problem statement into a data requirements list before writing code.
- Call standard library functions such as sqrt, pow, fabs and abs correctly.
- Explain why a library function needs both a header and, sometimes, a linker flag.
Start from the data, not the code
Before writing a line, list three things: what you are given, what you must produce, and what you need in between. For a circle problem you are given the radius, you must produce area and circumference, and in between you need the constant pi. That list becomes your declarations almost word for word.
This is not a formality. Most first-year bugs are not syntax errors — they are a missing input or a value the program never computed. A requirements list makes those visible before the compiler ever runs.
/* Given: radius
Produce: area, circumference
Between: PI */
#define PI 3.14159
double radius, area, circumference;The library has already solved it
C ships with tested functions for common mathematics. sqrt(x) gives a square root, pow(x, y) raises x to the power y, fabs(x) gives the absolute value of a double, and abs(n) does the same for an int. Writing your own square root is not resourceful; it is slower, less accurate, and untested.
Each family lives in a header. Maths functions need #include <math.h>. Miss the header and the compiler assumes the function returns an int, which quietly truncates your answer instead of failing loudly.
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 2.0;
printf("%.4f\n", sqrt(x)); /* 1.4142 */
printf("%.4f\n", pow(x, 10)); /* 1024.0000 */
printf("%.4f\n", fabs(-7.5)); /* 7.5000 */
return 0;
}Read the function's contract
Every library function has a contract: what types it takes, what type it returns, and what inputs are legal. sqrt expects a non-negative double. Passing a negative value is not a crash — it returns a special not-a-number value that then poisons every calculation it touches.
So guard the input rather than the output. Test x >= 0 before calling sqrt, instead of trying to detect the strange result afterwards.
Try it yourself
Read the three coefficients of a quadratic equation and print its two real roots, refusing politely when the roots are not real.
Need a hint?
Compute the discriminant first and test it before you call sqrt.
Check the worked solution
The discriminant b*b - 4*a*c decides everything, so it is computed once and tested before sqrt ever sees it — that is guarding the input rather than inspecting a strange output. Note 2 * a is written as a double expression; if a were an int and you wrote (-b + root) / 2 * a, precedence would divide first and then multiply, which is a different formula entirely.
#include <stdio.h>
#include <math.h>
int main(void)
{
double a, b, c, disc, root;
printf("Enter a, b, c: ");
scanf("%lf %lf %lf", &a, &b, &c);
if (a == 0) {
printf("Not a quadratic equation.\n");
return 1;
}
disc = b * b - 4 * a * c;
if (disc < 0) {
printf("Roots are not real.\n");
return 0;
}
root = sqrt(disc);
printf("x1 = %.4f\n", (-b + root) / (2 * a));
printf("x2 = %.4f\n", (-b - root) / (2 * a));
return 0;
}Quick check
You call sqrt but forget #include <math.h>. What is the most likely result?
Why this lesson exists
Syllabus mapping
Building Programs from Existing Information · Library Functions
Maps to course outcomes CO2, CO3.