[comp.lang.c] down

slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) (12/11/88)

PLEASE don't flame for posting too simple a question.  I think the following
SHOULD work, but will not even compile:
	while ( (c = getchar) != EOF)
		chcnt++ += (c == '\n');
The purpose is to count characters in a file.  Each time a newline is
encountered an additional character should be counted: when the file is
transferred, a newline is CR-LF combination.  A person I much respect for his C
knowledge told me that this would be too complex for a compiler.  I would
appreciate if some other people would express their opinion if the statement is
legal in C.  chcnt is a long int, c is a char.
Many thanks!
----
Stan Olejniczak           Internet:   slores%gables.span@umigw.miami.edu
University of Miami       UUCP:       {uunet!gould}!umbio!solejni
Miami, Florida, USA       Voice:      (305)-547-6005
My opinions cannot possibly represent the views of anyone else!

wald-david@CS.YALE.EDU (david wald) (12/11/88)

In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
>PLEASE don't flame for posting too simple a question.  I think the following
>SHOULD work, but will not even compile:
>       while ( (c = getchar) != EOF)
>               chcnt++ += (c == '\n');

Flame?  Us?  Never.

You can't assign to a ++ expression.


============================================================================
David Wald                                              wald-david@yale.UUCP
						       waldave@yalevm.bitnet
============================================================================

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/11/88)

In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
>	while ( (c = getchar) != EOF)
>		chcnt++ += (c == '\n');

The main problem is that getchar is a function-like macro, requiring
usage of a parenthesized argument list (containing no arguments), i.e.
	getchar()

The next problem is that the result of chcnt++ is not a modifiable
lvalue, so you cannot assign to it.  Split the statement into two
parts.

The final problem is that you say c is a char.  In that case it can
never compare equal to EOF on many systems.  getchar() returns an int,
not a char.

>... told me this would be too complex for a compiler.

Well, if it weren't for the other problems, I would say that any C
compiler that cannot handle expressions that complex is not worth
using.  Seriously!

matthew@sunpix.UUCP ( Sun NCAA) (12/12/88)

In article <gables.352@umigw.miami.edu>, slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
> PLEASE don't flame for posting too simple a question.  I think the following
> SHOULD work, but will not even compile:
> 	while ( (c = getchar) != EOF)
> 		chcnt++ += (c == '\n');
> The purpose is to count characters in a file.  Each time a newline is
> encountered an additional character should be counted: when the file is
> transferred, a newline is CR-LF combination.


I'm not sure about the validity of the construct 'chcnt++ += (c == '\n');', but
I'd write your program scrap as:

        while ( (c = getchar) != EOF)
            {
            if (c == '\n')
                chcnt++;
            chcnt++;
            }

(Before closing, there is one logic flaw in your scrap of code. '(c == '\n')'
does not have to evaluate to an integer 1. It must only be a non-zero value if
true.)

-- 
Matthew Lee Stier     (919) 469-8300|
Sun Microsystems ---  RTP, NC  27560|          "Wisconsin   Escapee"
uucp: {sun, rti}!sunpix!matthew     |

ok@quintus.uucp (Richard A. O'Keefe) (12/12/88)

In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
>	while ( (c = getchar) != EOF)
>		chcnt++ += (c == '\n');

No way is this too complex for a compiler.  It is just plain illegal.
chcnt is a 'long' _variable_ (L-value), but chcnt++ is a 'long' _number_
(R-value).  The first time round, chcnt would be 0, then chcnt++ increments
chcnt to 1 and evaluates to 0.  What would "0 += (c == '\n') mean?

Try
	chcnt++, chcnt += c=='\n';

Better still would be to use a for loop:
	for (chcnt = 0; (c = getchar()) != EOF; chcnt++) {
	    if (c == '\n') chcnt++;
	}
or
	for (chcnt = 0; (c = getchar()) != EOF; chcnt += c == '\n' ? 2 : 1)
	    ;

(Was that really (c = getchar), or was it (c = getchar())?  If the former,
that's wrong too.)

hls@rwthbs.UUCP (H.L. Stahl) (12/12/88)

In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
>PLEASE don't flame for posting too simple a question.  I think the following
>SHOULD work, but will not even compile:
>	while ( (c = getchar) != EOF)
>		chcnt++ += (c == '\n');
>... this would be too complex for a compiler. ...

The answer is quite simple: "+=" is an assignment operator, on it's left side
are only "lvalue"s allowed. But "chcnt++" is an expression with the result
"1 + previous_value(chcnt)", and you cannot assign anything to an expression,
even in C ...

I hope this helps!

Hans-Ludwig Stahl

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/13/88)

In article <349@greens.UUCP> matthew@sunpix.UUCP ( Sun NCAA) writes:
-(Before closing, there is one logic flaw in your scrap of code. '(c == '\n')'
-does not have to evaluate to an integer 1. It must only be a non-zero value if
-true.)

False.  Relational expressions produce integer result 0 or 1, only.

rkl1@hound.UUCP (K.LAUX) (12/13/88)

In article <45370@yale-celray.yale.UUCP>, wald-david@CS.YALE.EDU (david wald) writes:
> In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
> >PLEASE don't flame for posting too simple a question.  I think the following
> >SHOULD work, but will not even compile:
> >       while ( (c = getchar) != EOF)
> >               chcnt++ += (c == '\n');
> 
> Flame?  Us?  Never.
> 
> You can't assign to a ++ expression.
> 

	Of course you can!  For example, a simple string copy function:

copy_string (from, to)
char *from;
char *to;
{
	while (*to++ = *from++)
		;
}

--rkl

bamford@ihlpf.ATT.COM (Harold E. Bamford) (12/13/88)

In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
>PLEASE don't flame for posting too simple a question.  I think the following
>SHOULD work, but will not even compile:
>	while ( (c = getchar) != EOF)
>		chcnt++ += (c == '\n');

Without a list of the error messages from the compiler, I can only
guess, but the first thing that strikes me is that "getchar" should
probably be written as "getchar()" as it is a macro.  In my stdio.h,
it is listed as:
	#define getchar()	getc(stdin)

Please, no flames about anything.  Nobody cares.

				Harold Bamford

fransvo@htsa (Frans van Otten) (12/13/88)

In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
>	while ( (c = getchar) != EOF)
>		chcnt++ += (c == '\n');

Why is  chcnt += 1 + (c == '\n')  too complex for you ? Besides,
it won't work. Try getchar().
-- 
                         Frans van Otten
                         Algemene Hogeschool Amsterdam
			 Technische en Maritieme Faculteit
                         fransvo@htsa.uucp

ark@alice.UUCP (Andrew Koenig) (12/13/88)

In article <349@greens.UUCP>, matthew@sunpix.UUCP ( Sun NCAA) writes:

> (Before closing, there is one logic flaw in your scrap of code. '(c == '\n')'
> does not have to evaluate to an integer 1. It must only be a non-zero value if
> true.)

Nope.  The value of (c == '\n') must be 1 or 0.
-- 
				--Andrew Koenig
				  ark@europa.att.com

wald-david@CS.YALE.EDU (david wald) (12/13/88)

In article <9142@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
>>      while ( (c = getchar) != EOF)
>>              chcnt++ += (c == '\n');
...
>The final problem is that you say c is a char.  In that case it can
>never compare equal to EOF on many systems.  getchar() returns an int,
>not a char.

Doesn't the expression (c = getchar()) have type (int) regardless of the
type of c?  Or will c being a char really prevent this comparison?


============================================================================
David Wald                                              wald-david@yale.UUCP
						       waldave@yalevm.bitnet
============================================================================

wald-david@CS.YALE.EDU (david wald) (12/13/88)

In article <843@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>
>       for (chcnt = 0; (c = getchar()) != EOF; chcnt += c == '\n' ? 2 : 1)
>           ;

Urgh.  Yes, it's not *too* unreadable, yes it's correct, but if you're
going to do it like that, why bother eliminating the while loop:

while ((c = getchar()) != EOF)
    chcnt += (c == '\n' ? 2 : 1);


And, precedence rules be damned, I'd put in the parentheses.

============================================================================
David Wald                                              wald-david@yale.UUCP
						       waldave@yalevm.bitnet
============================================================================

ok@quintus.uucp (Richard A. O'Keefe) (12/13/88)

In article <349@greens.UUCP> matthew@sunpix.UUCP ( Sun NCAA) writes:
>Before closing, there is one logic flaw in your scrap of code. '(c == '\n')'
>does not have to evaluate to an integer 1.  It must only be a non-zero value
>if true.

Wrong.  All comparisons must return 0 or 1.  No other result is legal in C.

moore%cdr.utah.edu@wasatch.UUCP (Tim Moore) (12/13/88)

In article <2803@hound.UUCP> rkl1@hound.UUCP (K.LAUX) writes:
>In article <45370@yale-celray.yale.UUCP>, wald-david@CS.YALE.EDU (david wald) writes:

>> You can't assign to a ++ expression.
>	Of course you can!  For example, a simple string copy function:
>copy_string (from, to)
>char *from;
>char *to;
>{
>	while (*to++ = *from++)
>		;
                ^
                |
*to is an lvalue. Therefore you can assign to it. Now, the precedence
of ++ is higher than *, so the pointer contained in (to) is incremented,
but the value of *to++ is still the lvalue that *to represents. That's
why the the idiom above works; you're not really assigning to a ++
expression, but to an lvalue. (Well, OK, you are, but you get the idea.)

The original message contained:
	chcnt++ += (c == '\n');

          ^
          |
        chcnt is an lvalue here, alright, but the result of chcnt++ is
the integer residing in chcnt because "When postfix++ is applied to an
lvalue the result is the value of the object referred to by the
lvalue"(K&R 1st ed., pg 187), which can not be assigned to. This
commandment applies to the *to++ case to(!). to is an lvalue, so to++
evaluates to the pointer that resides in to, which is not an lvalue.
The * operator turns the pointer into an lvalue, so assignment can proceed.


			-Tim Moore
	4560 M.E.B.		   internet:moore@cs.utah.edu
	University of Utah	   ABUSENET:{ut-sally,hplabs}!utah-cs!moore
	Salt Lake City, UT 84112

ok@quintus.uucp (Richard A. O'Keefe) (12/13/88)

In article <45476@yale-celray.yale.UUCP> wald-david@CS.YALE.EDU (david wald) writes:
>In article <843@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>>       for (chcnt = 0; (c = getchar()) != EOF; chcnt += c == '\n' ? 2 : 1)
>>           ;
>
>Urgh.  Yes, it's not *too* unreadable, yes it's correct, but if you're
>going to do it like that, why bother eliminating the while loop:

But I *didn't* eliminate any "while" loop.  I started again from scratch
and observed that the point of the loop is to maintain chcnt, and a "for"
loop was the appropriate structure.

In fact, the way I would be inclined to do this is a wee bit more general:
	char chlen[256];

	for (c = sizeof chlen; --c >= 0; )
	    chlen[c] = 1;
	chlen['\n'] = 2;

	for (chcnt = 0; (c = getchar()) != EOF; chcnt += chlen[c])
	    ;

The advantage of this is that you can also add
	chlen['\r'] = 0;
so that the same result will be obtained from a file which already has
CRLF pairs as from one which has single LFs.

randy@halcdc.UUCP (randy orrison) (12/14/88)

In article <2803@hound.UUCP> rkl1@hound.UUCP (K.LAUX) writes:
|> You can't assign to a ++ expression.
|> 
|
|	Of course you can!  For example, a simple string copy function:
|
|	while (*to++ = *from++) ;

Except that you're not assigning to a ++ expression in this example.
The ++ expression is a pointer, and you're assigning to what the
pointer points to.  You couldn't assign to 'to++' if you wanted to.
The statement still stands (as well it should):

	You can't assign to a ++ expression.

		-randy
-- 
Randy Orrison - Control Data in the Hills of Arden	randy@halcdc.uucp
aka randy@{ux.acss.umn.edu, umnacvx.bitnet, cctb.mn.org, umn-cs.uucp}
	C:	The Alpha and Omega of the Zen of Programming.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/14/88)

In article <45472@yale-celray.yale.UUCP> wald-david@CS.YALE.EDU (david wald) writes:
>Doesn't the expression (c = getchar()) have type (int) regardless of the
>type of c?  Or will c being a char really prevent this comparison?

Doesn't matter; the important point is that wedging the int value
returned by getchar() through a char knothole loses information.

guy@auspex.UUCP (Guy Harris) (12/14/88)

>Doesn't the expression (c = getchar()) have type (int) regardless of the
>type of c?  Or will c being a char really prevent this comparison?

From K&R Second Edition (based on some particular d of the dpANS); K&R
First edition says much the same thing:

	A7.17 Assignment Expressions

	   ...The type of an assignment expression is that of its left
	operand, and the value is the value stored in the left operand
	after the assignment has taken place.

So no, the expression has the same type as "c", which is type "char",
not "int", and it has the value that was stored in "c".  If "getchar()"
returned EOF, and EOF is -1 (as it is on most, if not all, UNIX
implementations of C) on an 8-bit-byte two's complement machine the
value '\377' is stored in "c".  When the comparision with EOF is done,
the "char" value of the expression is converted to "int"; if "char"s are
unsigned, the '\377' is converted to 255, which is definitely not equal
to -1 (EOF).... 

furlani@broadway.UUCP (John L. Furlani) (12/14/88)

In article <2803@hound.UUCP>, rkl1@hound.UUCP (K.LAUX) writes:
> In article <45370@yale-celray.yale.UUCP>, wald-david@CS.YALE.EDU (david wald) writes:
> > 
> > You can't assign to a ++ expression.
> > 
> 
> 	Of course you can!  For example, a simple string copy function:
> 
> copy_string (from, to)
> char *from;
> char *to;
> {
> 	while (*to++ = *from++)
> 		;
> }
> 

Take another look.
You aren't assigning anything to the ++ expression.
Oops.
You are assigning something to what is contained in the pointers. 
The *pointers* are being incremented.
David Wald was correct, you can't assign to a ++ expression.
Try it and watch what happens.


____________
Disclaimer:  "If anyone else was responsible,
                       it had to have been me, and myself"
John L. Furlani 
The University of South Carolina, Columbia SC
(...!uunet!ncrlnk!ncrcae!broadway!furlani)

mat@mole-end.UUCP (Mark A Terribile) (12/14/88)

> > >...  I think the following SHOULD work, but will not even compile:
> > >...            chcnt++ += (c == '\n');
> > 
> > You can't assign to a ++ expression.
> 	Of course you can!  For example, a simple string copy function:
>	...   	while (*to++ = *from++) ...

Harrumph!

	*to++ = ...

associates as

	( *(to++) ) = ...

If I may quote K&R (Appendix A, section 7.2):

		The unary * operator means _indirection_: the expression
		must be a pointer, and the result is an lvalue referring to
							^^^^^^
		the object to which the expression points.

That's altogether different from

	( to++ ) = ...

Again quoting K&R (same section):

		When postfix ++ is applied to an lvalue, the result is the
		value of the object referred to by the lvalue.  After the
		result is noted, the object is incremented ...

Note carefully: ``the result is the value of the object referred to''
				    ^^^^^
That's value (or rvalue), NOT lvalue.


Please excuse my dogmatic voice, but this is getting silly.

(This man's opinions are his own.)
From mole-end				Mark Terribile
-- 
(This man's opinions are his own.)
From mole-end				Mark Terribile

knudsen@ihlpl.ATT.COM (Knudsen) (12/15/88)

In article <349@greens.UUCP>, matthew@sunpix.UUCP ( Sun NCAA) writes:
> (Before closing, there is one logic flaw in your scrap of code. '(c == '\n')'
> does not have to evaluate to an integer 1. It must only be a non-zero value if
> true.)

Hey!  Didn't we just finish the perennial discussion of whether C
uses integer 1 for TRUE boolean expressions, or just some
non-zero value?  The conclusion was (and was the last time)
that Boolean expressions, when required to cough up a value
(as opposed to just switching control in IF statements)
do indeed return exactly 1 for TRUE.

In fact, Moses K. and Jesus R. said so.
-- 
Mike Knudsen  Bell Labs(AT&T)   att!ihlpl!knudsen
"Lawyers are like nuclear bombs and PClones.  Nobody likes them,
but the other guy's got one, so I better get one too."

grogers@sushi.uucp (Geoffrey Rogers) (12/17/88)

In article <gables.352@umigw.miami.edu> slores%gables.span@umigw.miami.edu (Stanislaw L. Olejniczak) writes:
>		chcnt++ += (c == '\n');

The above statement is not legal in C. The reason why it is not legal is
because 'chcnt++' is consider to be a expression and you can not have
a expression of the form "expression asignment_operator expression".

Geoffrey C. Rogers
CONVEX

jeremy@acadch.UUCP (Jeremy Tammik) (12/20/88)

I think you're simply missing the '()' for the getchar function/macro.

Regards       
-Jeremy
{uunet|sun}!acad!acadch!jeremy