[comp.lang.c] learning C

baron@bnlux0.bnl.gov (ed baron) (04/01/89)

Maybe this isn't the best place to post this but it seemed reasonable.

I am trying to learn c out of a book that seems to be wrong on many
things, but anyway i can't seem to figure out how getchar() should
work. consider the following

char name [10];
int c;

for(;;)
{
puts("enter 9 to exit");
c = getchar();
if(c == 9)
break;
puts("enter name: ");
gets(name);
.
.
.
}

now getchar gets one character but not until it sees the terminator
(carriage return) but since it only gets one character and the
carriage return is one character if you enter 1<cr> say
the <cr> is passed to the next thing seeking input and so now
name is just <cr> i.e there is no opportunity to respond to the naame
prompt. then i tried using gets(c) in place of getchar c (andd
declaring c to be char) but that won't compile. what is the proper
way to do this? please respond via mail. thanks.

ed baron (baron@bnlux0.bnl.gov, baron@bnlux0.bitnet)

matthew@sunpix.UUCP ( Sun NCAA) (04/03/89)

In article <1091@bnlux0.bnl.gov>, baron@bnlux0.bnl.gov (ed baron) writes:
} Maybe this isn't the best place to post this but it seemed reasonable.
} 
} I am trying to learn c out of a book that seems to be wrong on many
} things, but anyway i can't seem to figure out how getchar() should
} work. consider the following
} 
} char name [10];
} int c;
} 
} for(;;)
} {
} puts("enter 9 to exit");
} c = getchar();
} if(c == 9)
} break;
} puts("enter name: ");
} gets(name);
} .
} .
} .
} }
} 
} now getchar gets one character but not until it sees the terminator
} (carriage return) but since it only gets one character and the
} carriage return is one character if you enter 1<cr> say
} the <cr> is passed to the next thing seeking input and so now
} name is just <cr> i.e there is no opportunity to respond to the naame
} prompt. then i tried using gets(c) in place of getchar c (andd
} declaring c to be char) but that won't compile. what is the proper
} way to do this? please respond via mail. thanks.
} 
} ed baron (baron@bnlux0.bnl.gov, baron@bnlux0.bitnet)


    I know your problem well.  What you are looking for is a 'getch()' or
'getche()' function in place of the 'getchar()' function.  Barring that try

c = getchar();
fflush(stdin);

    The variable 'c' will get the first character of input, and the remainder
of the line (plus the newline) will get flushed away.




-- 
Matthew Lee Stier                         |
Sun Microsystems ---  RTP, NC  27709-3447 |        "Wisconsin   Escapee"
uucp: { sun, mcnc!rti }!sunpix!matthew    |
phone: (919) 469-8300 fax: (919) 460-8355 |

dhesi@bsu-cs.UUCP (Rahul Dhesi) (04/04/89)

In article <584@greens.UUCP> matthew@sunpix.UUCP ( Sun NCAA) writes:
>c = getchar();
>fflush(stdin);
>
>The variable 'c' will get the first character of input, and the remainder
>of the line (plus the newline) will get flushed away.

Some time ago I noticed that people were assuming that fflush() would
flush pending input data from a file open for reading.  Apparently many
implementations of stdio do this.  I don't think portable code should
rely on it.

The Turbo C 1.0 manual says fflush() on a stream open for reading
flushes the contents of the buffer.  If the stream is line-buffered the
rest of the line will indeed be flushed.

However, the 4.3BSD documentation and my (slightly outdated) System V
Interface Definition both say only that fflush() works on streams
opened for writing.  Streams open for reading are not mentioned in this
context.

     /* portably read one char and ignore rest of line */
     c = getchar();
     while (!feof(stdin) && getchar() != '\n')
	;

I don't know what the ANSI standard says, but for now it probably
doesn't matter.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi
                    ARPA:  dhesi@bsu-cs.bsu.edu

ark@alice.UUCP (Andrew Koenig) (04/04/89)

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

>     I know your problem well.  What you are looking for is a 'getch()' or
> 'getche()' function in place of the 'getchar()' function.  Barring that try

> c = getchar();
> fflush(stdin);

Why depend so intimately on the detailed behavior of the
C run-time library?  Not all implementations support
fflush(stdin).  The following is much more portable:

	c = getchar();
	if (c != '\n')
		while (getchar() != '\n')
			;
-- 
				--Andrew Koenig
				  ark@europa.att.com

guy@auspex.auspex.com (Guy Harris) (04/04/89)

>I don't know what the ANSI standard says, but for now it probably
>doesn't matter.

It says that the behavior is undefined if you do an "fflush" on an
read-only stream or a read/write stream in which the most recent
operation was not an input operation.  Translation: "fflush" doesn't
flush input, so the ANSI standard says nothing new - it says "it flushes
output, we make no claims about input", which reflects current practice
(S5R3's "fflush" appears to flush input, although it's not documented -
which is kind of obnoxious; either it's a useful feature, in which case
it should be documented and supported, or it's a useless one, in which
case it shouldn't have been put in; 4.3-tahoe's doesn't; Turbo C's is
documented as doing so and presumably does; etc..)

guy@auspex.auspex.com (Guy Harris) (04/04/89)

>    I know your problem well.  What you are looking for is a 'getch()' or
>'getche()' function in place of the 'getchar()' function.

Huh?  What would those functions do?  They're not in the ANSI C standad
nor are they in any UNIX C library.  If they're a PCism, note that
plenty of C programs have never programmed on a PC and, as such, may not
be familiar with them.

>Barring that try
>
>c = getchar();
>fflush(stdin);
>
>    The variable 'c' will get the first character of input, and the remainder
>of the line (plus the newline) will get flushed away.

Bad idea, as Rahul Dhesi has already pointed out:

	1) "fflush(stdin)" is not guaranteed to flush input on all
	   implementations;

	2) even if it does do so on your implementation, it may or may
	   not stop at the end of the line in all cases.

Much better to *read* the rest of the line, as in Rahul's posting.  Not
only is it portable, it's the right thing to do - flushing input is
generally an action taken on an error, not something you do as a matter
of course unless you want to make *sure* somebody hasn't typed something
ahead that they'll regret (cf. "rn", which does flush input for
precisely that reason).

chris@mimsy.UUCP (Chris Torek) (04/05/89)

In article <1384@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
>... flushing input is generally an action taken on an error, not
>something you do as a matter of course unless you want to make *sure*
>somebody hasn't typed something ahead that they'll regret (cf. "rn",
>which does flush input for precisely that reason).

... *and* which provides a flag (-T) to turn off this behaviour!  Some of
us find ignoring input obnoxious.  If you are going to do it, please
make sure there is a way to defeat it as well.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

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

In article <456@s5.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt) writes:
>OK, so how can I avoid following commonly available bad rules or
>mispractices in C programming? ... I am not satisfied with writing
>merely functional programs; I want them to be clear and clean and
>run everywhere. I want them to be easy to maintain and upgrade.
>Where can I turn to get the kind of advice ...?

Harbison & Steele is okay.  My personal favorite is Kernighan & Ritchie,
which teaches these things more by refusing to teach the contrary than
by making a lot of noise about it.  Plum Hall (1 Spruce Av, Cardiff NJ
08232, (609)927-3770) are probably the oldest firm specializing in C
instruction, and they publish some very good C programming texts that
go into more detail in these areas than K&R.  I have heard good reports
also about Lapin's book on portable C programming, but I haven't
reviewed it.

Many of the tricks of the trade have been explained by several
experienced C programmers in this newsgroup.  There is of course
also a lot of silliness, bad advice, and just plain noise here.
You need to evaluate the suggestions for yourself and develop a
notion of who the reliable sources are.

>Also: is there a logical exegesis of a fairly full subset of C? 
>For example, a set of proof rules in the literature somewhere?

Not so far as I know, although you might check an index to SIGPLAN
Notices.

A company called Metaware has produced a formal semantic specification
for one full dialect of C; their compiler is derived from it.

However, I'm rather skeptical of the practical value of such work
for the concerns that you have.

>I have for years been complaining about the difficulty of unbound
>pointers in this regard, but I am perhaps out of date. (Did the 
>ANSI standardization affect this problem? I'm pretty sure it
>didn't, but I cannot give an authoritative reference.)

Tell me what the problem IS, and perhaps I can answer.  Remember
that C's emphasis is less academic and more practical than most
programming languages.  Just because a clean theoretical model
wouldn't fully cover all valid uses of pointers in C doesn't
mean that there is necessarily a practical problem with its
pointer facility.

>There have been graduate courses for years where every jot and tittle
>of PL/I or Algol 68 are thrashed out in agonizing detail. Anyone
>ever done this for C? 

Gee, I certainly hope not.  That's not a topic worthy of being made
into a graduate course.

>... I just want to know where can I get the straight dope on C short
>of the standard itself, (if possible).

The Standard defines the language, and it's relatively readable
(in fact, using English could be considered a deficiency); the
accompanying Rationale document helps one understand why some
things were specified the way they were.  (Most of the rest are
understandable as directly reflecting the committee's charter.)
The book "Standard C" by P.J. Plauger and Jim Brodie (Microsoft
Press, 16011 NE 36th Way, Box 97017, Redmond WA 98073-9717), ISBN
1-55615-158-6, constitutes a very thorough description of Standard
C, probably the closest you're going to find to an "exegesis".

Keep in mind that Standard C is a recent development, and there are
numerous compilers still in use that support some old-fashioned C
dialect unstead of Standard C.  Therefore, for practical purposes
you ought to consider the impact of older C environments when you
develop software that might be ported to them.  With any luck,
this will be a rather minor consideration after a couple more years.

mcdonald@uxe.cso.uiuc.edu (10/25/89)

From the well-known jlg:

>However, my _POINT_ was that, if the short circuit nature of these
>operators is valuable, then there might also be other contexts where
>user control of expression evaluation order might _ALSO_ be valuable!
>C doesn't provide such other mechanisms - WHY NOT?!?!?!?

Ummm- the user always has control of evaluation order in && and ||
constructs. And any other place too, by use of temporary variables.
I thought this flame war was  over the inability of the compiler
to optimize evaluation order in && and || constructs.

jlg@lanl.gov (Jim Giles) (10/25/89)

From article <225800228@uxe.cso.uiuc.edu>, by mcdonald@uxe.cso.uiuc.edu:
> Ummm- the user always has control of evaluation order in && and ||
> constructs. And any other place too, by use of temporary variables.
> I thought this flame war was  over the inability of the compiler
> to optimize evaluation order in && and || constructs.

This _discussion_ is about whether C has _efficient_ means of forcing
evaluation order in _several_ contexts (the first was the order of
argument evaluation in a function call).  Temporary variables are
_not_ an efficient solution (unless they are optimized out - something
C compilers are rarely clever enough to do).  Temporary variables also
have a negative impact on readibility (by diffusing the 'locality' of
specific operations).

Now a "flame war" would be an exchange with no technical content in which
the participants used phrases like "you're an ignorant @#$#%@ who doesn't
know his #$@ from a $#@%$!!".  I have tried, at least, to keep above
that level (so far anyway).

ok@cs.mu.oz.au (Richard O'Keefe) (10/25/89)

In article <14117@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> This _discussion_ is about whether C has _efficient_ means of forcing
> evaluation order in _several_ contexts (the first was the order of
> argument evaluation in a function call).

It is impossible to conduct such a discussion.  A language may have
complex or concise or clear or confusing or direct or indirect means
of expressing something, but efficiency is a property of implementations,
not of languages.

>  Temporary variables are
> _not_ an efficient solution (unless they are optimized out - something
> C compilers are rarely clever enough to do).

This is confusing two levels:  languages and implementations.
Heck, "a := a+1" should be efficiently implemented, but I know of one Ada
compiler for the NS32000 that generates 8 instructions for it (not a
commercial product; it was reported in SP&E 1987; they hadn't put the
peephole optimiser in yet).  If C compilers X, Y, and Z don't optimise
out temporary variables, complain about compilers X, Y, and Z, not about
C.  If the vendors of compilers X, Y, and Z independently explain that
the optimisation is hard because of property P of the language, complain
then abou property P of the language.

> Temporary variables also
> have a negative impact on readibility (by diffusing the 'locality' of
> specific operations).

Well, that depends.  To start with, temporary variables have the great
merit of being a familiar means.  That's how you force argument
evaluation order in Algol 60, Pascal, Ada, Fortran (66, 77, 8X), Modula,
Lisp, Simula 67, ...  The technique also has the merit of making the
order of evaluation obvious.  There is a further point that if expression
E1 has to be evaluated before expression E2, it makes it a whole lot
simpler to explain in the comments *why* E1 has to be evaluated before
E2 if you have names for the results.

Finally, I was taught years and years ago that a complicated expression
should be broken up into medium-sized pieces (such as could be given
meaningful names) *to make it more readable*.

mcdonald@uxe.cso.uiuc.edu (10/25/89)

>The C standard has been through 3 public reviews and is presently facing
>a class-action suit.  It is still not an official standard.  This does
>not qualify as "a reality" in my book.

Class action suit? This sounds interesting. Let's hear more. 
Flames to comp.lang.c.national.enquirer.

jlg@lanl.gov (Jim Giles) (10/26/89)

From article <2523@munnari.oz.au>, by ok@cs.mu.oz.au (Richard O'Keefe):
> Well, that depends.  To start with, temporary variables have the great
> merit of being a familiar means.  That's how you force argument
> evaluation order in Algol 60, Pascal, Ada, Fortran (66, 77, 8X), Modula,
> Lisp, Simula 67, ... 

Most of those languages also have _other_ means of forcing evaluation
order in useful contexts.  For example, all of the above mentioned 
languages allow the user to prohibit optimization of expressions
involving associative operators - using parenthesis.  The C argument
that parenthesis should be used _only_ for legibility always seemed
rather silly (especially in a language which otherwise makes so few
concessions for legibility).

ok@cs.mu.oz.au (Richard O'Keefe) (10/26/89)

In article <14124@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
: From article <2523@munnari.oz.au>, by ok@cs.mu.oz.au (Richard O'Keefe):
: > Well, that depends.  To start with, temporary variables have the great
: > merit of being a familiar means.  That's how you force argument
: > evaluation order in Algol 60, Pascal, Ada, Fortran (66, 77, 8X), Modula,
: > Lisp, Simula 67, ... 
: 
: Most of those languages also have _other_ means of forcing evaluation
: order in useful contexts.  For example, all of the above mentioned 
: languages allow the user to prohibit optimization of expressions
: involving associative operators - using parentheses.  The C argument
: that parentheses should be used _only_ for legibility always seemed
: rather silly 

Working backwards:
 - last time I heard about the ANSI draft it *did* require that
   parentheses be respected a la Fortran
 - I've never heard of any "C argument that parentheses should be used
   only for legibility".  On the contrary, the C argument was that
   parentheses had to be used so heavily in macros to protect against
   context that it was better they should have only syntactic force
 - Lisp is one of "the above mentioned languages" and it most certainly
   does NOT allow the user to prohibit expression optimisation using
   parentheses (parentheses make lists!)
 - there seems to be a confusion between association and order of
   elaboration.  In reading this thread, whenever Giles has written about
   "argument evaluation order" I had assumed that he was talking about
   things like
	in f(x) + g(x), is f() called then g(), or g() called then f()?
   What made me think this was the discussion of the order of evaluation
   of arguments to functions.
   Parentheses in Algol, Fortran, Pascal, Ada, and the rest have NO
   relevance to that question.  What parentheses force is association:
	(A + B) + C
   must be calculated as
	add A, B giving temp
	add temp, C giving result
   However, the values of A, B, and C may be calculated in any order.
   This is relevant when it comes to function calls.  Consider
	( P(X) .AND. Q(X) ) .AND. R(X)
   in Fortran.  It is legal for a Fortran compiler to generate code
   equivalent to
	t1 = q(x);
	t2 = r(x);
	t3 = p(x);
	result = (t3 & t1) & t2
   The parentheses control the order in which the values of the leaves of
   the expression tree are combined, but not the order in which the values
   of those leaves are obtained.