[comp.lang.c] TO C OR NOT TO *C

jon_hogan-doran%713.600@fidogate.fido.oz (Jon Hogan-doran) (10/11/89)

Original to: all
Hmm. While reading through my Microsoft C Manual, under the
stdio section , it said (something like this) that getc(fd)
returned an int value .. and yet later on he gave an example
(something like this):
 
char ch;
ch=getc(ttyd);
......
 
Being only a self-taught Hacker [TRAD] of C-Source, i've
never quit understanded, or new, what happened in classes
like this; and what C does. I also wondered what happened
when:
 
e.g char ch, int i, unsigned int uni, 
 
char *getprt(); (returns a pointer to the char)
int getint();
 
E.G 1:      i=getprt
E.G 2:     ch=getprt
 
Also.. if i have an int value, does :
 
this work:
 
      uni=(unsigned)(i) or (unsigned)i
      (I'm not worries about the syntax - only the result !)
 
Also   :  char *chprt
 
no later on does 
        ... chprt=(some func that returns a pointer)
             ^-|
               Does this mean "char *chprt" or "char chptr"
                if it is: "char *chprt" then does
 
           *chprt=(some func that returns a pointer)
             ^-|
                Does this mean "char *chprt" here or "char **chprt"
 
ETC... ETC...
Now if you know the ANSWERS to these problems pleas reply !!!
1. No "I think that its...." - Thinks are know good - I
   want the whole truth and nothing but the TRUTH"
 
yr. sincrerly
 
[JON] Hogan-doran Hacked [TRAD]

--- TMail v1.12b
 * Origin: Prophet TBBS - First TBBS in Australia (3:713/600)

henry@utzoo.uucp (Henry Spencer) (10/17/89)

In article <16107@nswitgould.cs.uts.oz> jon_hogan-doran%713.600@fidogate.fido.oz (Jon Hogan-doran) writes:
>... it said (something like this) that getc(fd)
>returned an int value .. and yet later on he gave an example
>(something like this):
> 
>char ch;
>ch=getc(ttyd);

Barring unusual situations, his example is simply wrong.  getc does return
an int.  The value will fit in a char except in one important case:  EOF.
Unless you have reason to be *absolutely certain* that end-of-file will
not occur when attempting to read that character, the result of getc should
*never* be assigned to a char without first testing to see if it is equal
to EOF.  That usually means assigning it to an int first, so you can test
the value and then use it.
-- 
A bit of tolerance is worth a  |     Henry Spencer at U of Toronto Zoology
megabyte of flaming.           | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

djones@megatest.UUCP (Dave Jones) (10/18/89)

From article <1989Oct16.172249.18387@utzoo.uucp>, by henry@utzoo.uucp (Henry Spencer):
> In article <16107@nswitgould.cs.uts.oz> jon_hogan-doran%713.600@fidogate.fido.oz (Jon Hogan-doran) writes:
>>... it said (something like this) that getc(fd)
>>returned an int value .. and yet later on he gave an example
>>(something like this):
>> 
>>char ch;
>>ch=getc(ttyd);
> 
> Barring unusual situations, his example is simply wrong.  getc does return
> an int.  The value will fit in a char except in one important case:  EOF.
> Unless you have reason to be *absolutely certain* that end-of-file will
> not occur when attempting to read that character, the result of getc should
> *never* be assigned to a char without first testing to see if it is equal
> to EOF.  That usually means assigning it to an int first, so you can test
> the value and then use it.

You should use int rather than char, but the EOF business will not
automatically screw up the program. It's implementation dependent.
The following will work fine on Sun's, etc., assuming only that the
input stream consists entirely of printable characters:

#include <stdio.h>

main()
{
  char ch;
  while((ch=getc(stdin))!= EOF)
    fputc(ch, stdout);
}

The reason this works is that on the Sun, chars are signed, printable
characters have positive values, and EOF is negative. But you still
should use int, if only to be morally correct.

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (10/18/89)

In article <1989Oct16.172249.18387@utzoo.uucp> henry@utzoo.uucp (Henry
Spencer) writes:
>Unless you have reason to be *absolutely certain* that end-of-file will
>not occur when attempting to read that character, the result of getc should
>*never* be assigned to a char without first testing to see if it is equal
>to EOF. 

Playing Devil's advocate, we bravely yet blithely break Henry Spencer's
every rule:

     char c;

     c = getc(stdin);           /* Oops! forgot to test for EOF! */
     do {
        if feof(stdin)
           break;               /* WHEW! */
        .. do stuff with c ..
        c = getc(stdin);
     } while (1);
--
To BLUNGE or not to BLUNGE;    | Rahul Dhesi, Cirrusl Logic Inc.
That is the question.          | <dhesi%cirrusl@oliveb.ATC.olivetti.com>

Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi
Do not use From: address for reply if it contains "sun".

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/19/89)

In article <8864@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>The reason this works is that on the Sun, chars are signed, printable
>characters have positive values, and EOF is negative. But you still
>should use int, if only to be morally correct.

It's not a matter of "morality", it's a matter of practicality.
Relying on an implementation quirk will get you into trouble when:
	- the implementation changes
	- the compiler is invoked with a switch that treats "char"
		as unsigned
	- the code is ported to a different implementation
It's especially foolish when it is just as easy to write the code
correctly as to write it in an implementation-dependent way.

cpcahil@virtech.UUCP (Conor P. Cahill) (10/21/89)

In article <991@cirrusl.UUCP>, dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
> Playing Devil's advocate, we bravely yet blithely break Henry Spencer's
> every rule:
>      char c;
>      c = getc(stdin);           /* Oops! forgot to test for EOF! */
>      do {
>         if feof(stdin)
>            break;               /* WHEW! */
>         .. do stuff with c ..
>         c = getc(stdin);
>      } while (1);

And the same code could have been done without the break, without the 
overhead of the feof() function call for every iteration of the loop
and (in my humble opinion) more readable as follows:

      int c;
      while( (c=getc(stdin)) != EOF);
      {
         .. do stuff with c ..
      }
	



-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

hascall@atanasoff.cs.iastate.edu (John Hascall) (10/21/89)

In article <1294> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
}In article <991>, dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
}> Playing Devil's advocate, we bravely yet blithely break Henry Spencer's
}> every rule:

 Rules?!  We don't need to steenk'n rules...

}>      char c;
}>      c = getc(stdin);           /* Oops! forgot to test for EOF! */
}>      do {
}>         if feof(stdin)
}>            break;               /* WHEW! */
}>         .. do stuff with c ..
}>         c = getc(stdin);
}>      } while (1);
 
}And the same code could have been done without the break, without the 
}overhead of the feof() function call for every iteration of the loop
}and (in my humble opinion) more readable as follows:
 
}      int c;
}      while( (c=getc(stdin)) != EOF);
}      {
}         .. do stuff with c ..
}      }

 Or you could use:

       char c;
       while (c = getc(stdin), !feof(stdin)) {
	  .. stuff with c ..
       }

 which lets you use "char c", doesn't have the break and (IMHO) is more
 readable than the above two.  The whole purpose of this was that there is
 some great advantage to be had by using "char c" over "int c", right? :-)

 I suppose one might want to do:

      char buf[BUFMAX];
      while (buf[i] = getc(stdin), !feof(stdin) && (++i < BUFMAX)) ...

              *** that's the beauty of C ... it makes it easy ***
	      *** to do the same thing umpteen different ways ***


John Hascall                                The opinions are mine, you say...
ISU Comp Center                             but if you'ld like them everyday...
Ames, IA  50011                             see misc.jobs.resumes today!
hascall@atanasoff.cs.iastate.edu            BURMA SHAVE

condict@cs.vu.nl (Michael Condict) (10/23/89)

In article <991@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>In article <1989Oct16.172249.18387@utzoo.uucp> henry@utzoo.uucp (Henry
>Spencer) writes:
>>Unless you have reason to be *absolutely certain* that end-of-file will
>>not occur when attempting to read that character, the result of getc should
>>*never* be assigned to a char without first testing to see if it is equal
>>to EOF. 
>
>Playing Devil's advocate, we bravely yet blithely break Henry Spencer's
>every rule:
>
>     char c;
>
>     c = getc(stdin);           /* Oops! forgot to test for EOF! */
>     do {
>        if feof(stdin)
>           break;               /* WHEW! */
>        .. do stuff with c ..
>        c = getc(stdin);
>     } while (1);

It is clear that this is a safe way to assign the result of getc to a char,
but why write it in such a distorted way?  Much simpler is:

	c = getc(stdin);
	while (!feof(stdin)) {
		.. do stuff with c ..
		c = getc(stdin);
	}

But this does points out the main disadvantage of the use of an eof predicate
over the use of in in-band EOF value:  As in Pascal, the natural way to
write every input loop is:

	Arbitrarily_complicated_stuff_that_does_some_input
	while (! feof(stdin)) {
		.. do stuff with input ..
		Arbitrarily_complicated_stuff_that_does_some_input
	}

You have to write two copies of the code that gets input, a maintainence
headache.  Of course, you can put this code in a function and write the
function call twice, but this can seem silly it it is just two lines of code.

This problem can be gotten around in C, using the ',' operator:

	while (c = getc(stdin), !feof(stdin)) {
		.. do stuff with c ..
	}

but there is no way around it in Pascal.

Michael Condict
Vrije University
Amsterdam

tps@chem.ucsd.edu (Tom Stockfisch) (10/24/89)

In article <3775@condict.cs.vu.nl> condict@cs.vu.nl (Michael Condict) writes:
>	Arbitrarily_complicated_stuff_that_does_some_input
>	while (! feof(stdin)) {
>		.. do stuff with input ..
>		Arbitrarily_complicated_stuff_that_does_some_input
>	}

Someone proposed a language extension which handles this very elegantly:

	do
	{
		c =	getc(stdin);
	} while (!feof(stdin))
	{
		.. do stuff with input ..
	}

where the second compound statement is executed only when the "while" test
succeeds.  When it fails, execution continues after the second compound
statement.  Until such time as this makes it into a compiler, I just
use
	
	for (;;)
	{
		c =	getc(stdin);
		if (feof(stdin))	/* LOOP TEST */
			break;
		.. do stuff with input ..
	}

I always mark the loop test with an eye-catching comment.  Structured
programmers please note that there still is only one entrance point
and one exit point.

>This problem can be gotten around in C, using the ',' operator:
>
>	while (c = getc(stdin), !feof(stdin)) {
>		.. do stuff with c ..
>	}

This doesn't always work:  for instance, if the first part is a statement.
On all compilers I work on, there is the additional requirement (the
standard not withstanding) that
all operands of the comma operator be non-void.
-- 

|| Tom Stockfisch, UCSD Chemistry	tps@chem.ucsd.edu

bph@buengc.BU.EDU (Blair P. Houghton) (10/25/89)

In article <585@chem.ucsd.EDU> tps@chem.ucsd.edu (Tom Stockfisch) writes:
>In article <3775@condict.cs.vu.nl> condict@cs.vu.nl (Michael Condict) writes:
>>This problem can be gotten around in C, using the ',' operator:
>>
>>	while (c = getc(stdin), !feof(stdin)) {
>>		.. do stuff with c ..
>>	}
>
>This doesn't always work:  for instance, if the first part is a statement.

	while ( ! getcandfeof(&c) ) {
		.. do stuff ..
	}

int getcandfeof( cptr )
char *cptr;
{
	*cptr = getc(stdin);
	return ( feof(stdin) );
}

Any number of statements can be stuffed into the function.
It's unfortunate that it adds yet more overhead, though.

>On all compilers I work on, there is the additional requirement (the
>standard not withstanding) that all operands of the comma operator be
>non-void.

What a lousy compiler.

				--Blair
				  "But I mean that in a nice
				   way, I really do."

Tom.Stockfisch@branch.FIDONET.ORG (Tom Stockfisch) (10/29/89)

--  
Tom Stockfisch via FidoNet node 1:369/11
UUCP: {attctc,<internet>!mthvax}!ankh,novavax!branch!Tom.Stockfisch