[net.micro.att] Why doesn't this work?

ken@birtch.UUCP (Ken B) (03/21/86)

We have a 3B2/300, and I wrote this program to help debug our spooler problem
(another story), why doesn't it work?  It never read's an EOF from stdin,
and continues to dump 'nulls' to stdout.  (Note: I'm just learning 'c',
so please no flames on programming style, or lack of it)

All the program does is number each line it reads from stdin.

--------- code follows ---------
#include <stdio.h>

main()
{
	int i=1;
	char c;

	c=getchar();
	if (c!=EOF)
		printf("%d     ",i++);
	while (c!=EOF) {
		putchar(c);
		if (c=='\n') {
			c=getchar();
			if (c!=EOF)
				printf("%d     ",i++);
		}
		else c=getchar();
	}
	putchar(EOF);
}
------ end of code ------

The system is running Sys V un*x, if that helps.  The program works, except
that it never stops running. I am forced to interrupt it, which writes the
data out, with alot of nulls on the 'last line'.  Am I doing something wrong?

This exact program works correctly on our Pyramid 90x, so I know its not just
my program.

If anyone out there has some ideas on why it doesn't ever read an EOF, I'd
be very grateful to know why.

Note: how I use it is:

ls -la /bin | number > outputfile
     or
ls -la /bin | number

Niether method works correctly (i.e. stops executing)

Thank you,

Ken Brown
-- 
	uucp:  ...{!glacier!oliveb,!ihnp4!trwrb} !felix!birtch!ken

These ramblings are my own, and are surely not those of my employer.

steve@jplgodo.UUCP (Steve Schlaifer x3171 156/224) (03/21/86)

In article <276@birtch.UUCP>, ken@birtch.UUCP (Ken B) writes:
> We have a 3B2/300, and I wrote this program to help debug our spooler problem
> (another story), why doesn't it work?  It never read's an EOF from stdin,
> and continues to dump 'nulls' to stdout.  
..................code deleted..........................
> 	char c;
> 
> 	c=getchar();
> 	if (c!=EOF)
............... remaining code deleted .................
> 
> This exact program works correctly on our Pyramid 90x, so I know its not just
> my program.

The getchar function is of type int; EOF is defined in stdio to have the value
-1.  When you say c=getchar(); and encounter an end of file, the value -1 from
getchar is converted to \377 when it is stored in c.  When c is later compared
to EOF, the value of c is converted to int and then the comparison is done.
This is all true no matter which machine you are running on.

I suspect the 3B2 uses unsigned char's and the Pyramid uses signed char's.
When \377 is converted to int on the 3B2, it becomes +127; on the Pyramid, it
becomes -1.  Obviously, +127 is not equal to -1 so c can never be equal to EOF
on the 3B2.  On the Pyramid, the sign extension done when a char is converted
into an int makes everything work out fine.  An easy fix for this type of
problem is to declare c as an int rather than a char.

-- 

...smeagol\			Steve Schlaifer
......wlbr->!jplgodo!steve	Advance Projects Group, Jet Propulsion Labs
....group3/			4800 Oak Grove Drive, M/S 156/204
				Pasadena, California, 91109
					+1 818 354 3171

jsdy@hadron.UUCP (03/22/86)

In article <276@birtch.UUCP> ken@birtch.UUCP (Ken B) writes:
>We have a 3B2/300, and I wrote this program to help debug our spooler problem
>(another story), why doesn't it work?  It never read's an EOF from stdin,
>#include <stdio.h>
>main()
>{
>	int i=1;
>	char c;
>	c=getchar();
>	if (c!=EOF)

I'm not sure why this dumps NULs:  are you sure they are not DELs?
Anyway, I'd bet dollars to donuts (of which I have none) that the
3B2 does not sign-extend when converting from chars to ints.  The
return value of getchar is an int!  Therefore 'c' should be an int.
You see, EOF is supposed to be an int that is out-of-band for a
character.

Perhaps the 3B2 EOF is something with a high bit set and the low
byte 0?

If you want to avoid using fgets:
	while (fgets(bigbuf, sizeof(bigbuf), stdin) != NULL)
		printf("%d:\t%s", i++, bigbuf);
try this:
	register int i = 1;
	register int c;

	/* Number each line. */
	while ((c = getchar()) != EOF) {
		/* The number. */
		printf("%d:\t%c", i++, c);
		/* The line. */
		while ((c = getchar()) != EOF) {
			putchar(c);
			if (c == NL)
				break;
		}
		/* If you want to keep from extra passes: */
		if (feof(stdin))
			break;
	}
	return(0);	/* Always return a value to the environment. */
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}

gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/24/86)

In article <276@birtch.UUCP> ken@birtch.UUCP (Ken B) writes:
>	char c;
>
>	c=getchar();
>	if (c!=EOF)

getchar() returns an (int), not a (char).  EOF is an (int).
You're throwing away some of the bits returned by getchar(),
which happens not to matter in this case except when an EOF
is returned.

>This exact program works correctly on our Pyramid 90x,
>so I know its not just my program.

Oh, yes it is.  The Pyramid presumably treats (char) as
(signed char), while the 3B2 treats (char) as (unsigned char).
Therefore the pyramid will propagate the sign of the 8-bit subset
of the getchar() result that you stashed into c, whereas the 3B2
will not propagate the sign.  You have a machine-dependent bug.
Didn't "lint" catch this?

ken@birtch.UUCP (Ken B) (03/24/86)

	Thank you to all of you that supplied me with the help (to my
problem on the 3b2 not EOF-ing)

	99% said the problem was the variable 'c' was defined as a
'char' and it should have been an 'int'.  I changed it so, and it worked.

	Also, thanks to some of you for pointing out that the final
'putchar (EOF)' is not needed, and in fact, is not at all what I should
have done. (it introduces one more character to the file that ought not
to be there)

Again, many thanks,

Ken Brown
-- 
	uucp:  ...{!glacier!oliveb,!ihnp4!trwrb} !felix!birtch!ken

These ramblings are my own, and are surely not those of my employer.

throopw@dg_rtp.UUCP (Wayne Throop) (03/30/86)

> getchar() returns an (int), not a (char).  EOF is an (int).
> You're throwing away some of the bits returned by getchar(),
> [...etc,etc...]
> Didn't "lint" catch this?

What, you didn't try it?  Why not? :-)    Anyhow, feeding this

        #include <stdio.h>

        void main(){
            char c;
            while( (c = getchar()) != EOF )
                ;
        }

to SysV lint gives

        warning: nonportable character comparison

Myself, I'd druther see lint complain whenever the types fed to an
assignment don't match exactly, rather than allow "implicit casts", but
the fact that quoted characters are of type int kind of spoils this idea
for C, I suspect.
-- 
Wayne Throop at Data General, RTP, NC
<the-known-world>!mcnc!rti-sel!dg_rtp!throopw

dab@myrias.UUCP (Danny Boulet) (03/30/86)

something to say first...

The problem is that getchar returns an int (not a char).  I've never used
either of the machines that you mention but my guess is that the Pyramid
does sign extension on char to int conversions and the 3B2 doesn't.  Since
EOF is an integer (-1), the value 0xff gets assigned to your variable 'c'.
When you compare this character with EOF (-1) on a machine that does sign
extension, you get -1 vs -1.  On a machine that doesn't do sign extension,
you get 255 vs -1.

The solution is simple - declare 'c' as an int instead of as a char.