Journal Articles

CVu Journal Vol 12, #1 - Jan 2000 + Letters to the Editor
Browse in : All > Journals > CVu > 121 (30)
All > Journal Columns > LettersEditor (132)
Any of these categories - All of these categories

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.

Title: The Wall

Author: Administrator

Date: 08 January 2000 13:15:34 +00:00 or Sat, 08 January 2000 13:15:34 +00:00

Summary: 

Body: 

A Reply to the Harpist

Dear Francis and The Harpist,

Thank you for your comments on my code rewrite printed in C Vu 11.6, of code originally presented in C Vu 11.5. I have rewritten the code incorporating some of The Harpists suggestions and have restructured it so that it now has one entry point and one exit point. To reply to some of The Harpist's comments without being too defensive: When I originally wrote the code I used the Symantec Think C Standard Library manual to check the specification of fprintf(). The manual stated that EOF was returned in the event of an error. However K+R 2nd Edition agrees with The Harpist in that it should return a negative number. As most file-related functions return EOF on error I assumed that the manual was correct. I suppose the moral is that first you need a good reference to the Standard Library and that "Standard" has a slightly different meaning to compiler vendors than it does to the rest of us.

ERROR_SUCCESS was a result of reading too many Microsoft header files and API reference documents, where this is a standard value.

The original purpose of using the superfluous variable newch was to provide positioning for further character translation, for example ASCII to EDCDIC or Rot13 as I hinted in the accompanying notes. I have removed this in the reworked code.

So why did I use exit()? I took the approach adopted by K+R in Section 7.6 Error Handling - Stderr and Exit. My reasoning was that the function might be abstracted into a separate function and that if we have a major problem, then we should call exit() which would ensure that any open files would be closed and a return code passed to the caller. Since exit is equivalent to return in a main() routine it probably doesn't make any difference in this case.

The new code caters for filenames with embedded spaces if the filename is passed in quotes. A fixed size buffer is allocated to remove the quotes before further processing. I haven't worried about the possibility of buffer overflow in this case. If it was thought to be a concern or this code was to be used in a production environment I would add code based on that in checkISBN* to either allocate a buffer dynamically or restrict the number of input characters.

With regard to The Harpist's other comments I remain to be convinced that not using some punctuation or capital letters in variables is a good move. Isn't error_file_close easier to read that errorfileclose?

I don't like the if (!(infile = fopen(filename,"rb"))) instead of if ((infile = fopen(filename,"rb")) == NULL) for two reasons. The first is that it is more complex than the original without adding significant benefit. It is an example of code condensing that does not add clarity. The Standard states that fopen() will return NULL in the event of a failure and the original code tests against this. The second objection is the assumption that NULL will be represented as 0 (and so !NULL will be non-zero). The Standard leaves the internal representation of NULL to the implementor and while 0 in an assignment will be coerced into the true NULL representation I do not believe that the Standard has anything to say about !NULL. I accept that the probability of failure is very small with modern compilers from major vendors.

Catriona O'Connell

There is considerable room for opinion as to what constitutes good style. Personally I am unhappy with names that become whole phrases and think that it is often a sign of a deficient vocabulary (though not always). The standard gives certain guarantess. One of these that in a context requiring a Boolean value NULL evaluates as false and !false always evaluates as true. This means that !NULL is equivalent to true regardless as to the internal representation of NULL.

The Harpist

#include <stdio.h>
#include <stdlib.h>
enum {success, 
    error_missing_argument,
    error_extra_arguments,
    error_read_failure,
    error_write_failure,
    error_file_close
  };
int main(int argc, char **argv) {
// The program will read a file and sends the output
// to stdout replacing the line returns with newlines.
  int ch;
  int retcode = success;
  FILE *infile;
  char *p1;
  char *p2;
  char filename[FILENAME_MAX+1];
  if (argc == 1){
    if (fprintf(stderr,"No filename passed to %s\n",argv[0]) < 0) abort();
    retcode = error_missing_argument;
  }
  else if (argc > 2){
    if (fprintf(stderr,"Error in filename passed to %s\n", argv[0]) < 0) abort();
    retcode = error_extra_arguments;
  }
  else {
// Strip the quote marks from the filename if there are any.
    for(p1=argv[1], p2=filename;*p1 != '\0';p1++) {
      if (*p1 != '"') {
        *p2 = *p1;
        p2++;
      }
    }
    *p2 = '\0';
    if ((infile = fopen(filename,"rb")) == NULL){
      if (fprintf(stderr,"Error opening file %s\n",filename) < 0) abort();
      retcode = error_read_failure;
    }
    else {
      while ((EOF != (ch = getc(infile))) && (retcode == success)){
        if (ch == '\r') ch = '\n';
        if (EOF == putchar(ch)) {
          if (fprintf(stderr,"Problem writing to stdout.\n") < 0) abort();
          retcode = error_write_failure;
        }
      }
      if (EOF == fclose(infile)) {
        if (fprintf(stderr,"Problem closing file %s\n",filename) < 0) abort();
        retcode = error_file_close;
      }
    }
  }
  return retcode;
}

Notes: 

More fields may be available via dynamicdata ..