Input handling
scanf("%d", &n);
We can't safely use n
unless scanf()
successfully converted at least one value (and it can't convert more, because we only asked for one conversion). Therefore:
if (scanf("%d", &n) != 1) {
fputs("Input should be numeric!\n", stderr);
return EXIT_FAILURE;
}
Consider also checking that n
is positive.
We could loop until we get a valid input. Personally, I would take the number to generate as a command-line argument:
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "Usage: %s NUMBER\n", argv[0]);
return EXIT_FAILURE;
}
char *end;
long n = strtol(argv[1], &end, 0);
if (n < 1 || !*end) {
fprintf(stderr, "Usage: %s NUMBER\n", argv[0]);
return EXIT_FAILURE;
}
⋮
}
Or we could just generate an "infinite" list, and let users filter with standard tools (head
) to get the length required. When I say "infinite" list in quotes like that, I mean that we should stop it only when i * i
would overflow its type. We could change i
to unsigned long long
(or even uintmax_t
from <stdint.h>
) if we will really need the extra range.
Paging
if(i % 24 == 0){
printf("Press Enter to continue...");
if(getchar() == '\n'){
continue;
}
}
It seems inconvenient to have output stop every 24 lines, even when I'm using a much larger (virtual) terminal, or writing output to a file. It would be better if we adapted better to the terminal size (e.g. using getenv("ROWS")
if that's present). However, this is something that we have standard tools for, and interactive users will probably want to use their own choice of pager. So my recommendation is to not duplicate that functionality in one's own programs.
In any case, there's a bug. If the input character is not a newline, then the behaviour is no different to when it is - continue
at the end of a loop skips nothing!
Minor bits
For very large integers, the format string %10d%10d
will run the numbers into each other. It's a good idea to have at least one space so that when the minimum width overflows, they are still separated.
In main()
(and only that function), we can omit return 0;
at the end.
Simplified program
The result is greatly pared down:
#include <stdint.h>
#include <stdio.h>
int main(void)
{
for (int i = 1; i <= INT_MAX/i; ++i) {
printf("%10d %10d\n", i, i*i);
}
}
We can use this in pipelines:
squares | head -n 20 >twenty_squares
And interactively:
squares | head -n 200 | more
Or interactively until we get bored:
squares | more