patterncMinor
Size improvements for cat reimplementation
Viewed 0 times
sizereimplementationcatforimprovements
Problem
I have written a reimplementation of cat that will be compliant with most scripts, and that is as small and fast as possible. Can anybody suggest some size improvements for it?
I'm sorry that the indentation is messed up, I use tabs in my code.
In clang version 3.5.0 on Ubuntu the generated binary size is 5200 bytes with these options:
Improvements
I added some more error checking, added -u and - and also wrote a function that writes out a file to avoid repeating myself. Also changed short int to int, printf to putchar, an
#include /* we need printf, fprintf, FILE,
* fopen, fclose and that sort of
* stuff */
#include /* for exit, EXIT_SUCCESS, and
* EXIT_FAILURE */
int main(int argc, char *argv[])
{
FILE *fp; /* file to cat */
short int ch; /* character to print */
unsigned short int cp; /* currently printing argv[?] */
unsigned short int failed = 0; /* how many failed to print */
if (argc < 2) { /* if not enough args act as pipe */
for (;;) { /* infinite loop */
if ((ch = fgetc(stdin)) == EOF) {
exit(EXIT_SUCCESS);
} else {
printf("%c", ch);
}
}
}
for (cp = 1; cp <= argc - 1; cp++) { /* for each file in cli args */
fp = fopen(argv[cp], "r"); /* open the file */
if(fp == NULL) {
fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[cp]);
failed++; /* increment the number of failed */
continue; /* go back to beginning */
}
while ((ch = fgetc(fp)) != EOF) {
printf("%c", ch);
}
fclose(fp); /* close the file */
}
exit(failed); /* exit with the number of files */
} /* that failed */I'm sorry that the indentation is messed up, I use tabs in my code.
In clang version 3.5.0 on Ubuntu the generated binary size is 5200 bytes with these options:
-Oz -fomit-frame-pointer -sImprovements
I added some more error checking, added -u and - and also wrote a function that writes out a file to avoid repeating myself. Also changed short int to int, printf to putchar, an
Solution
-
Do not repeat yourself. Copying
-
Avoid naked loops. Every loop does an important job that deserves a name. This is strong enough reason to factor it out as a function:
-
Expect errors
-
-
-
Handle options. At least recognize a standalone
Do not repeat yourself. Copying
stdin doesn't differ from copying any other file. There is no need to special case stdin as you do at lines 15-21.-
Avoid naked loops. Every loop does an important job that deserves a name. This is strong enough reason to factor it out as a function:
-
Expect errors
-
fgetc may fail. Once fgetc returns EOF, call feof or ferror to see what has actually happened.-
printf may fail. Make sure to detect (printf returns -1) and report (analyze errno) errors.-
Handle options. At least recognize a standalone
- as a fake file name referring to stdin.Context
StackExchange Code Review Q#90302, answer score: 3
Revisions (0)
No revisions yet.