Portability Concerns
Using the > and < operators on characters is not a portable solution for this in C. For the special case of the digits '0'...'9' you can do this because the C Standard specifies that these characters must be encoded contiguously and in ascending order.
It is unlikely that using comparison operators to check whether a character is alphabetic in the manner (ch >= 'A' && ch <= 'Z') will cause problems on most modern systems, but problems do occur. Certainly it could be a problem on older systems, such as legacy systems installed at institutions many years ago. This is exactly why the functions described in ctype.h should usually be preferred: these can be relied upon to work portably.
Portable Solutions
But if this is not possible more portable solutions than the aforementioned char comparison which relies upon a particular character encoding can be had.
Being unable to use arrays is a severe (and artificial) constraint. Of the two solutions below, the first solution does use an array (keepers) to encode characters which should be written to output. There is another solution following which does not use such an array, and I think that it meets all of OP's requirements, yet the second solution is a bit more awkward and error-prone to write.
Both solutions are more portable than using (ch >= 'A' && ch <= 'Z') methods, and both give the same results:
$ cat poem_modified.txt
The house cat sits
And smiles and sings
He knows a lot
Of secret things
Using an Array
The first solution defines an array keepers which is initialized by a string literal to contain all characters which should be written to output. As characters are read from input, the program checks in keepers to see if the character is present in this list; if so it is written to output, and if not the next character is read from input.
#include <stdio.h>
int main(void) {
// Open input file and check for errors
const char *input_file = "poem.txt";
FILE *input = fopen(input_file, "r");
if (input == NULL) {
fprintf(stderr, "Unable to open file %s for input\n", input_file);
return 1;
}
// Open output file and check for errors
const char *output_file = "poem_modified.txt";
FILE *output = fopen(output_file, "w");
if (output == NULL) {
fprintf(stderr, "Unable to open file %s for output\n", output_file);
fclose(input);
return 1;
}
char keepers[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ \n";
for (int ch = fgetc(input); ch != EOF; ch = fgetc(input)) {
// Is `ch` an alphabetic character?
size_t idx = 0;
char keeper = keepers[idx];
while(keeper != '\0') {
if (ch == keeper) {
putc(ch, output);
break;
}
keeper = keepers[++idx];
}
}
fclose(input);
fclose(output);
return 0;
}
Using Brute Force
The second solution does the same thing as the first, but without the array. Here instead of using an array to hold the list of characters which should be kept, an if statement with a very long conditional expression encodes this information.
#include <stdio.h>
int main(void) {
// Open input file and check for errors
const char *input_file = "poem.txt";
FILE *input = fopen(input_file, "r");
if (input == NULL) {
fprintf(stderr, "Unable to open file %s for input\n", input_file);
return 1;
}
// Open output file and check for errors
const char *output_file = "poem_modified.txt";
FILE *output = fopen(output_file, "w");
if (output == NULL) {
fprintf(stderr, "Unable to open file %s for output\n", output_file);
fclose(input);
return 1;
}
for (int ch = fgetc(input); ch != EOF; ch = fgetc(input)) {
// Is `ch` an alphabetic character, space, or newline?
if (ch == 'a' || ch == 'b' || ch == 'c' || ch == 'd' || ch == 'e'
|| ch == 'f' || ch == 'g' || ch == 'h' || ch == 'i' || ch == 'j'
|| ch == 'k' || ch == 'l' || ch == 'm' || ch == 'n' || ch == 'o'
|| ch == 'p' || ch == 'q' || ch == 'r' || ch == 's' || ch == 't'
|| ch == 'u' || ch == 'v' || ch == 'w' || ch == 'x' || ch == 'y'
|| ch == 'z' || ch == 'A' || ch == 'B' || ch == 'C' || ch == 'D'
|| ch == 'E' || ch == 'F' || ch == 'G' || ch == 'H' || ch == 'I'
|| ch == 'J' || ch == 'K' || ch == 'L' || ch == 'M' || ch == 'N'
|| ch == 'O' || ch == 'P' || ch == 'Q' || ch == 'R' || ch == 'S'
|| ch == 'T' || ch == 'U' || ch == 'V' || ch == 'W' || ch == 'X'
|| ch == 'Y' || ch == 'Z' || ch == ' ' || ch == '\n')
{
putc(ch, output);
}
}
fclose(input);
fclose(output);
return 0;
}