How to convert Infix notation to postfix notation

S

spinoza1111

What ev er. Any way, here is the next version of the parser under
discussion, with input from you and Bacarisse. Try to make
constructive comments only. Thanks.

// ***************************************************************
// *                                                             *
// * infix2PolishC   Infix to Polish notation using a grammar    *
// *                                                             *
// *                                                             *
// * This application converts infix to Polish notation using a  *
// * simple grammar and two different implementations. It also   *
// * contains testing and timing facilities. For more            *

Correction: at this writing the code contains testing facilities but
no timing facilities.
 
S

Seebs

Don't break your arm patting yourself on the back, Einstein. You
confuse knowledge and bias resulting from overspecialisation with
scientific knowledge.

No, I don't. But it's nice that you finally grant that even the allegedly
overspecialized people have justified true belief. :)
So you show them around to the guys at the office and these dweebs in
some corporation think I'm a nutter. Hey, two can play that game: the
tech reviewers at McGraw Hill probably think you are.

I doubt it.
Know, I don't think you have. Calling people "nutters" is 14 year old
argumentation.

Critics who treat "adult" as a term of approval, instead of as a
merely descriptive term, cannot be adults themselves. To be concerned
about being grown up, to admire the grown up because it is grown up,
to blush at the suspicion of being childish; these things are the
marks of childhood and adolescence.... When I was ten, I read fairy
tales in secret and would have been ashamed if I had been found doing
so. Now that I am fifty, I read them openly. When I became a man, I
put away childish things, including the fear of childishness and the
desire to be very grown up.
-- C. S. Lewis
As I have said,

You've said it, but *you were wrong*. I offered specific quotations and
citations to suport that.
he was using a model to illustrate
how things work for normal people as opposed to autistic twerps, and
expected them properly to see the essentials,

Then he is a shitty writer, because people who read his books have
consistently come away from them with a different understanding.

In particular, a CS author who is writing "for normal people as opposed
to autistic twerps" has clearly misunderstood the audience.
You're lying and I think you're going to end up in a court of law,

I doubt it, but I admit that it would amuse. Back when I had more free
time I used to sue junk faxers as a hobby.
since your document said that the 20 errors you listed, most of which
were bullshit

Only they weren't.
(and all of which were rejected by technical people at
McGraw Hill)

Only they weren't. No one at McGraw Hill was shown that list.
were the known errors,

Untrue, and I've already given you the exact quote from the page, unaltered
since some time in the 90s, showing that the page specifically states that
it is not a comprehensive or complete list.
and you have never shown us the
"hundreds" of other errors that you claimed, in a self-contradictory
way, were "also" in the book.

No, I haven't. So what? I am not obliged to show you everything that exists.
Again, you documented only 20 errors and have never, to my knowledge,
provided a longer list.

Doesn't matter. The errors don't have to be described to exist.
Of the errors you documented, some were
matters of opinion and interpretation, and others were trivia.

Even if we grant that, there remain others which are not matters of opinion,
not matters of interpretation, and not trivia. There are serious flaws
in the explanations offered, and your attempts to explain away some of them
have been hilariously inept.
Hard working, professional and collegial programmers, in a multivendor
environment such as the environment I worked at Bell-Northern
Research, when given code let us say that #includes file names in
upper case, that was developed on IBM or Microsoft platforms, simply
correct the code for case sensitivity.

And again: Let us remind you of your own example of the guy who has to
figure out someone else's code RIGHT NOW. He's trying to learn C. He hasn't
got time to spend his time correcting example code.

Perhaps more importantly: Errors like that in example code are evocative
of the clock which strikes thirteen. It isn't just that the thirteenth
stroke is wrong; it's that it gives you cause to doubt the others as well.

Once you know the book has plain and simple errors in it, you no longer
have a justified belief that the book is accurate on other issues; you have
to check everything it says, and cannot use it as a *reference*. The point
of a reference is to have already done the research. A book which requires
you to check every claim it makes is not a useful reference.
But autistic twerps and bullies instead sit on the code and when asked
where it is, say "oh, it's got hundreds of errors and I cannot work
with it boo hoo Mommy".
Huh.

I think you subconsciously replicate your on the job behavior patterns
here. I would not hire you nor would I recommend you for a programming
job.

I should hope not! I would be very worried if I received a recommendation
from you, and would assume I was doing something horribly wrong.

FWIW, in the real world, rather than the Nilgeverse, people who spot bugs
and fix them really quickly are generally considered pretty useful, but
you can have whatever laws of physics you want in your fantasy universe.
Who's "we?" A vanishingly small set of twerps,

Even if we were to grant this, it *doesn't matter*.

The fact remains that you have been given links to and citations to multiple
other criticisms not specifically rooted in or related to mine. Whether
you like the people who provided you the links is a pure non-sequitur.
Actually, the corporation preserves high school relationships in order
to disempower people.

Fascinating! But nonetheless, irrelevant, since I don't actually do
any of that. Go do the research; you've picked pretty much the least
plausible target around for your accusations, in this case.
You're lying.

Your inability to read English is not a deceptive act on my part.
Again, "C: The Complete Nonsense" only lists as
confirmed 20 errors while making reference to "hundreds" in a self-
contradictory fashion,

Because it is beyond your capacity to read things posted as links, I've
already quoted for you the exact text. Of course, since you're apparently
unable to read the ends of long posts, perhaps you missed it.

The following is a partial list of the errors I am aware
of, sorted by page number. I am not including everything;
just many of them.

Pretty unambiguous.
and it is the source, as far asI have
determined, for all the claims about C: The Complete Reference.

And again, you've been pointed at others. Your inability to determine
things, when given specific names and citations, is not anyone else's
problem.
This would be "Schildt is better for Microsoft platforms".

While perhaps true, it's not relevant unless the book claims to be only
for those platforms.
Note that
you could have expressed it this way, but instead you preferred to air
your ignorance about Microsoft platforms.

Don't be stupider than you have to be.
For example, you seem
unaware that at the time, file identifiers were case insensitive.

I'm quite aware of it. I have been all along. I don't consider it
relevant at all. (In particular, you seem unaware that header names
are not necessarily file names or identifiers; it is perfectly permissible
for a compiler to have no physical files with names even remotely similar
to "stdio.h", but rather, to simply perform particular operations internally
upon seeing a request for the standard headers.)
This is just wrong. In fact, you need to know ranges of data in the
design phase. Failure to do so causes common bugs.

Ranges of data aren't the same thing as system types.
Neither, thank God, since after 1980, a new generation of self-serving
twerps entered programming.

Huh. So why is there a book about computers with your name on it? I guess
it's probably pretty bad if it was written by someone who is neither a
programmer nor a technical writer.
What is YOUR job title and company, please?

I work at Wind River Systems, in the Linux group, my boss is Jeff Honig.
While I have every confidence that he will find your communications just
as entertaining as I do, I think he's usually busier than I am, so try
not to flood him too much. If you do wish to send complaints, please
cc me on them for lulz.

FWIW, I do compiler stuff; we don't actually do our own compiler/libc
maintenance, that's contracted out to Code Sourcery (who are, for what
it's worth, SERIOUSLY awesome folks). I'm the guy who gets bug reports
about the compiler and determines whether the compiler is right or wrong.
I'm also one of the default "we can't figure this out, we need someone else
to look at it and find the bug" people, and one of the preferred code
reviewers if you need something to work the first time you check it in. :)

-s
 
S

Seebs

(READER NOTE: There is actual content about C in this one, just for variety.)

This is
of course that
(1) Functions must be defined before use (an idiot language feature
since it is an artifact of the thrilling days of yesteryear when
storage was limited, and programs were on paper tape and could not,
conveniently, be read more than once)

You're gonna have to work harder on learning the terminology if you want
to discuss C and not just be laughed at.

Functions must be *declared* before use. The thing with a function body
is a definition, the one without a function body is a declaration, also
called a prototype.

You also don't understand the intent or purpose of the feature. You're
unlikely to even if it's explained, because you seem to have attained
a nearly supernatural level of willful blindness to even the most trivial
facts, but we have other readers.

Q: Why doesn't C just read the whole file to find a function's definition?

A: Because prototypes would be needed anyway.

C is designed to support genuinely modular code -- you can build a program
which incorporates functionality that was previously compiled. That means
that you can, on nearly all implementations, build a program which includes
pieces of code for which you have *no source code*. The solution adopted
in early C was to allow declarations of external functions which are used
to generate code to call those functions even if no definition for that
function exists in source code. In C89, this feature was extended (based
in part, as I recall, on the C++ prototype feature) to include "prototypes"
which provide declarations of the arguments, not just the return types,
of the function.

Prototypes are primarily used to address the fairly common case where the
function being called is defined in a separate "translation unit" (in most
cases, this means "source file", but there are technical differences).

At the time, it made sense to allow compilers to continue to, at least in
principle, be able to operate in a single pass. While that's less crucial
now perhaps than it used to be (as most modern optimizers end up needing
to work with everything in memory for a while), it's still considered a
plus for vendors targeting smaller systems. (In a fit of irony, Microsoft
systems were one of the targets that benefitted a lot from this, but of
course, they're not important.)

Since prototypes are already needed, and well-defined, the language just
expects you to provide them whenever you call a function before its
definition.
(2) Fixing this problem (which is an iinsult to the intelligence)

In normal English, "an insult to the intelligence" isn't supposed to be
a precise synonym for "which is reasonable for reasons I don't understand",
but I guess I've gotten used to your diaect.
in the ordinary way means coding the declaration twice.

Or using functions only after their definition.
If you know a better way to fix the problem, what is it?

The canonical solution is, in fact, to declare the function once and
define it once, usually with the declaration in a header if it's going
to be used by or seen by other translation units.
My way gives a nice little overview and is reasonably easy to
maintain.

The regular way is pretty easy to maintain if your prototypes don't change
too often, and if they change too often, they're changing too often.

-s
 
S

Seebs

Nilges: ok, then, truthiness should be as unlike falsiness as
possible. Therefore -1.

If things could be ONLY true or false, this would be persuasive.

In fact, many things have out-of-band values. By long-standing convention,
negative numbers are used for out-of-band values, such as error conditions.
Functions often return a non-negative number to indicate a result, and
negative number on failure. That convention is sufficiently widespread
to reach the level of "driving on the correct side of the road" for most
purposes, and using a negative number for anything but an error or abnormal
return is more confusing than not.
No, C does NOT have Booleans, since safe C means using as little crap
as possible and I don't get Booleans when I do so.

C does have boolean operators, though, and they yield 0 for false and
1 for true.
No, I won't. Autistics need Mommy to make things all neat. Men don't.

If you're human, then you'll have that problem. Conventions exist because
human brains work well with them, autistic or otherwise.
I would never drive on a road designed by you, so the point is moot.

No one said anything about a road designed by me. This is a really stupid
response to a fundamental point about the nature of standard practices and
conventions. There is no objective reason for which people drive on the
right or left side of the road; both are perfectly viable. But there is
an objective reason that, in any given country, there is usually a very firm
policy about which side of the road you drive on *in that country*.

-s
 
S

spinoza1111

(READER NOTE:  There is actual content about C in this one, just for variety.)



You're gonna have to work harder on learning the terminology if you want
to discuss C and not just be laughed at.

This is your anxiety. You're anxious to avoid being laughed at as you
were when you were young, because unlike me, in all probability, you
did not stand up to the bully and fight like a man, which is what we
did in 1964. You need to grow up, and read Habermas: enlightened
discussions between MEN avoid as much as possible "terminology", which
is a modern form of the Hebrew "shibboleth", the use of pronunciation
in the Old Testament to tell friend from foe.

Functions must be *declared* before use.  The thing with a function body
is a definition, the one without a function body is a declaration, also
called a prototype.

You also don't understand the intent or purpose of the feature.  You're
unlikely to even if it's explained, because you seem to have attained
a nearly supernatural level of willful blindness to even the most trivial
facts, but we have other readers.

This is just silly. I have told you to restrict yourself to C because
you don't understand programming. When you tell me things I already
know, you're wasting my time.
Q:  Why doesn't C just read the whole file to find a function's definition?

A:  Because prototypes would be needed anyway.

C is designed to support genuinely modular code -- you can build a program

OK, this is better, but I'm afraid you're wasting my time nonetheless,
because 50% of the effort here is needed to preserve legacy, and the
answer is: eliminate C.
which incorporates functionality that was previously compiled.  That means
that you can, on nearly all implementations, build a program which includes
pieces of code for which you have *no source code*.  The solution adopted
in early C was to allow declarations of external functions which are used
to generate code to call those functions even if no definition for that
function exists in source code.  In C89, this feature was extended (based
in part, as I recall, on the C++ prototype feature) to include "prototypes"
which provide declarations of the arguments, not just the return types,
of the function.

Prototypes are primarily used to address the fairly common case where the
function being called is defined in a separate "translation unit" (in most
cases, this means "source file", but there are technical differences).

At the time, it made sense to allow compilers to continue to, at least in
principle, be able to operate in a single pass.  While that's less crucial
now perhaps than it used to be (as most modern optimizers end up needing
to work with everything in memory for a while), it's still considered a
plus for vendors targeting smaller systems.  (In a fit of irony, Microsoft
systems were one of the targets that benefitted a lot from this, but of
course, they're not important.)

Since prototypes are already needed, and well-defined, the language just
expects you to provide them whenever you call a function before its
definition.

All of this legacy nonsense has one solution: OO.
In normal English, "an insult to the intelligence" isn't supposed to be
a precise synonym for "which is reasonable for reasons I don't understand",
but I guess I've gotten used to your diaect.


Or using functions only after their definition.


The canonical solution is, in fact, to declare the function once and
define it once, usually with the declaration in a header if it's going
to be used by or seen by other translation units.

Yes indeed.

However, the distinction between declaration and definition, like
sequence points, is not a reputable construct. It's a patch which
corrects the blunders and limitations of the past.

It's asking for trouble to have an intermediate level of definition. A
code resource is either available or else it isn't.

I see it in my GUI: in C Sharp, I can click only on the definition,
and on C I have the choice of def and decl which is a stupid and
confusing waste of time...but as you say necessary...because C is
fucked up.

You need to actually learn a radically different programming language.
Your uncritical "expertise" in mistakes doesn't impress me.
 
C

Chris McDonald

spinoza1111 said:
This is just silly. I have told you to restrict yourself to C because
you don't understand programming. When you tell me things I already
know, you're wasting my time.


Spinny, you come here asking for some feedback on your code, you are
provided with some and, seemingly because you don't like being corrected
when you make errors, you state that people are wasting your time?

Can you see anything wrong with this description of the facts?

Can you see that some may consider you to be wasting our time?

If you don't like C, then that's fine; no-one is holding a gun to your
head to use it, and you have no chance of stopping its use throughout
the world.

Why do you persist with your dross?
 
S

Seebs

This is your anxiety.

No, it's not.
You're anxious to avoid being laughed at as you
were when you were young,

No, I'm not.

You spend hours preening over how I'm an "autistic twerp", but you don't
actually do even the most basic research.

Hint: I don't actually care whether people laugh at me. I think it's
amusing.
because unlike me, in all probability, you
did not stand up to the bully and fight like a man,

.... lolwut?
which is what we
did in 1964.

I'm glad for you, I guess?
This is just silly. I have told you to restrict yourself to C because
you don't understand programming.

This is about C, but...
When you tell me things I already
know, you're wasting my time.

That might be true. However, you've made it pretty clear that it is
not reasonable to assume that you know much of ANYTHING, and that much of
what you think you know is just plain wrong. So rather than assuming
you knew what prototypes were, I told you. Rather than assuming that you
already knew that you have a nearly supernatural level of willful blindness
to even the most trivial facts, I mentioned it.
OK, this is better, but I'm afraid you're wasting my time nonetheless,
because 50% of the effort here is needed to preserve legacy, and the
answer is: eliminate C.

Not until we've got a replacement.

When you can suggest a better language for kernels, you go right ahead
and do that.
All of this legacy nonsense has one solution: OO.

That's not actually a solution to the problem at hand, nor does it address
some of the primary cases where people are using C for new development.
However, the distinction between declaration and definition, like
sequence points, is not a reputable construct.

You keep making all these random assertions, but you never seem to get
around to actually supporting them.
It's a patch which
corrects the blunders and limitations of the past.

And the present, and the forseeable future, because they actually turn out
to be useful. There's substantial benefit to many people in being able to
use a declaration plus an already-compiled hunk of external code, so it's
going to be supported.
It's asking for trouble to have an intermediate level of definition. A
code resource is either available or else it isn't.

Untrue. Source is not binary.
You need to actually learn a radically different programming language.
Your uncritical "expertise" in mistakes doesn't impress me.

Hmm. How about shell, lua, perl, php, Ruby, awk, Objective-C, and Java?
(I'm probably forgetting a couple, I can't actually list all the languages
in which I can muddle through stuff.)

I'm not super excellent at any of those, although I'm pretty good at shell,
and certainly competent in lua and perl. I'm not including C++, as the
language has changed far too much since I was last any good at it. The
others I can do tolerably in, although I'm hardly expert at any but
maybe shell.

-s
 
S

Seebs

Try to make constructive comments only. Thanks.

Every comment I've made has been constructive... Assuming you actually want
to be effective at using C. If all you want to do is bitch about how
it's not the way you would have done it, I can't help so much.
// ***************************************************************

You should use /*...*/ comments for large comment blocks, the // feature
is really intended for one-line commments.
#include <stdio.H>
#include <stdlib.H>

You already caught these.
// ***** Constants ***********************************************
#define ABOUT_INFO \
"This application converts infix to Polish notation using a simple
grammar-based approach."

This seems unlikely to be frequently used. In its presentation on Usenet,
this has been wrapped, but there's on general guarantee that you can embed
newlines in string literals portably. I can't tell whether the original
was wrapped, though.
// --- Pass over white space
#define SKIP_WHITE_SPACE(s, i, e) \
{ for(; (i) <= (e) && (s)[(i)] == ' '; (i)++ ); }

This seems unnecessary. You can do this with a while loop, for one
thing, for another, strspn() already exists.
// ***** Function index ******************************************
#define ADDFACTOR \
int addFactor(char *strInfix, \
char *strPolish, \
int *intPtrIndex, \
int intEnd, \
int intMaxPolishLength)
ADDFACTOR;

As commented elsewhere, this doesn't buy you very much.
// ---------------------------------------------------------------
// Command line handler
//
// int main(int intArgCount, char **strArgs)

Right here, you instantly dispelled any possibility of a gain occurring
from the #defines above, because you're duplicating the text anyway.
MAIN
{
int intMalloc = -1;
printf("%s\n\n", ABOUT_INFO);

Printing this unconditionally seems unfriendly.
if (intArgCount > 1)
if ((intMalloc = string2UnsignedInt(strArgs[1])) < 0)

Let's see.

1. The name "string2UnsignedInt" is reserved for the implementation,
so you shouldn't be using a function named that.
2. If it doesn't actually return an unsigned int, it is misleadingly
and poorly named.
3. If it does, the conversion will be undefined if someone enters
a value outside the signed range.
4. And any time you have "unsigned" and a comparison with < 0 on the
same line, you're just ASKING for trouble, even if it all works now.

Needs a value.
if (*intPtrIndex > intEnd) return -1;

I'm just going to pick this particular point to ask:

In general, do you intend this test to be ">" or ">="?
ERRORHANDLERSYNTAX
{
int intIndex1 = 0;

This name is gratuitously verbose.

Have you ever seen a mathematician write "let realEpsilon1 be an arbitrarily
small value, we will now calcualet realDelta1 as a function of realEpsilon1?"

No?

There's a reason for that.

While there's a lot to be said for longer (and presumably clearer) names
in many cases, the loop iterators i, j, k are effective idioms, and failure
to use them makes it much easier to make common mistakes.
printf("\nError at character %d: %s\n",
intIndex,
strMessage);
printf("%s\n", strInfix);
for (intIndex1 = 0; intIndex1 < intIndex; intIndex1++)
printf(" ");
printf("$");

I'd probably do:
printf("%*s$\n", intIndex, "");
// ---------------------------------------------------------------
// Find one of a set of alternative characters

Again, you really ought to just be using the standard string library, since
it works just great and already exists.
while(*intPtrIndex <= intEnd
&&
(chrNext = strInfix[*intPtrIndex]) >= '0'
&&
chrNext <= '9')
{
if (!stringAppendChar(strPolish,
chrNext,
intMaxPolishLength,
intSpaceBefore))
return 0;
intSpaceBefore = 0;
(*intPtrIndex)++;
}
if (*intPtrIndex > intIndexStart)
return -1;

It seems like it might make a tiny bit more sense to use <ctype.h>, and
write this something like
if (isdigit(strInfix[*intPtrIndex])) {
/* parse integer, then... */
return -1;
}

If only there were some handy integer-parsing code just lying around.
(BTW, for extra credit, figure out how to support negative integers...)
// ---------------------------------------------------------------
// Convert string to an unsigned integer
//
// int string2UnsignedInt(char *strInstring)
//
//
STRING2UNSIGNEDINT
{
int intIndex1 = 0;
int intValue = 0;
for (; strInstring[intIndex1] != '\0'; intIndex1++)
{
if (strInstring[intIndex1] < '0'
||
strInstring[intIndex1] > '9') break;
intValue = intValue * 10
+
strInstring[intIndex1] - (int)'0';
}
return intValue;
}

No checks for overflow, and the cast on '0' is unneeded. In C++, it would
be of type char, so we could imagine you not being aware of the default
promotion rules, but in C, it's an int already, so the cast's useless.

This sort of thing is normally written using pointer notation, but even
more importantly, this sort of thing was already written much more carefully
and completely.
STRINGAPPENDCHAR
{
int intLength = stringLength(strString);
int intSpaceBeforeInEffect =
intSpaceBefore
&&
intLength > 0
&&
strString[intLength - 1] != ' ';

Interesting feature, and not a bad idea. I'm not sure it's really
necessary, because it seems like it'd be easy enough to set a protocol
up for when you add the spaces, but it's not awful.
{
errorHandler
("Cannot append character(s): insufficient storage");
return 0;
}

This is the kind of thing where it might be really nice for errorHandler
to be able to display formatted messages, because:

"Cannot append character '%c': insufficient storage", chrNew

would be a better message.
// ---------------------------------------------------------------
// Return string length

Still not useful.
char *strPolish;
int intMaxPolishLength = 0;
int intReq = intMalloc > 0
?
intMalloc
:
MAX((intMaxPolishLength
=
stringLength(strInfix) << 1)
+
1,
10);

Normally, people are pretty careful not to have side effects in a
macro that they know is likely to evaluate one of its arguments more than
once.

What is intMaxPolishLength if intMalloc igreater than zero? It was
initialized to zero, and it only gets updated in the other branch of
the intReq initializaiton, so I think it's still zero, no?
printf("\n\nConverting \"%s\": expect \"%s\"",
strInfix,
strExpected);
strPolish = (char *)malloc(intReq);

Cast not needed.
printf("\n\"%s\"\n",
(infix2Polish(strInfix,
strPolish,
intMaxPolishLength)

You use intMaxPolishLength, but the allocated space in strPolish is
intReq.
?
strPolish
:
"Conversion failed"));

I wouldn't usually put ?: here.
free(strPolish); // cf. Schildt, C: the Complete Reference

Hah.

The test cases look pretty good.

-s
 
S

Seebs

Clearly not. He's been told about them, and *still* hasn't fixed them.

He followed up to this post to comment on them, so I count that as
"caught".
He's trying to avoid duplication, presumably because he doesn't
realise the compiler will warn him if an inconsistency arises between
declaration and definition.

That or because it's annoying to duplicate things. I'm not a huge fan
of the declaration/definition thing, I just think it's less annoying
to me than many of the alternatives.

-s
 
S

Seebs

By attempting to ridicule Keith Thompson's name, you just lost the
right to complain when people ridicule yours. (This is not the first
time that you have attempted to ridicule people's names.)

In his defense, he actually did a semi-competent job of it; he picked a
name which has been established previously to be viewed as offensive.
Reflect on this, when people call you "Spinny" and your nonsense
"nilgewater".

I didn't really even mean "Spinny" to be derisive. He's touchy about
his actual last name, I don't feel that I'm quite on a first-name basis
with him, "spinoza1111" is capitalized wrong for a proper name and
in any event obnoxious to type or pronounce, and Spinoza he's not.

So I picked something clearly-related but not intrinsically offensive that
I know of.

-s
 
N

Nick Keighley

I think you mean

#define TRUE (-1)

when would my version break?

And if I saw that, I'd still wonder why the author used -1 rather
than 1.

true, but at least I'd know what his intent was
My own favorite way to define a Boolean type in C (if <stdbool.h>
isn't available) is

    typedef enum { false=0, true=1 } bool;

where the "=0" and "=1" are superfluous, but nice to have for
emphasis.

long ago I used a compiler that used to issue warnings for code that
used this sort of bool

bool b = true;

if (b)
thingy();

But as long as you maintain the habit of *never* comparing for
equality to true or false, you can probably use any non-zero value you
like for true.

I have a bunch of code that explicitly test for TRUE (I didn't write
it!)

:-(
 
T

Tim Streater

Nick Keighley said:
a usually rack mounted computer, usually placed in an air conditioned
room. Google for instance has rooms full of 'em. All large businesses
have tons of em too that do everything from tracking inventory to
issuing invoices to printing the wage checks. The world has been
running on this stuff since about 1960.

Here's a typical server:

http://www1.euro.dell.com/uk/en/business/Servers/rack_optimized/ct.aspx?r
efid=rack_optimized&s=bsd&cs=ukbsdt1

(not that I'm endorsing Dell, particularly. But I did manage to drop a
Dell server (twice) while trying to install it in a rack with awkward
access, and it ran fine).

It's no different from your desktop except that:

It'll be noisier.
Prolly have several disks in it.
Prolly more than one power supply so it can receive different AC feeds
from the building's UPS.
It's a shape designed to be rack-mounted. In a 47 rack-unit (RU) high
(about 2200mm) rack, you can get 47 of them if they are 1RU high.
 
S

Seebs

when would my version break?

Well.

In *sane* code, never.

But consider:

#include <stdio.h>
#define NICK_TRUE -1
#define KEITH_TRUE (-1)

int main(void) {
int a[] = { 1, 2, 3 };
int *p = &a[1];
printf("Nick: %d\n", NICK_TRUE[p]);
printf("Keith: %d\n", KEITH_TRUE[p]);
return 0;
}

This yields:

Nick: -3
Keith: 1

The only things I can find which bind more tightly than the unary -
are (), [], ->, and .

So I suspect this won't come up much.

But. In *theory*, it is possible for the lack of () to mean that
the - binds to a longer expression.

It's certainly a good habit.
I have a bunch of code that explicitly test for TRUE (I didn't write
it!)

Back when clcm was young, there was a Bad Style Contest.

The winner:

#define FALSE 10
#define TRUE 11

.... or words to that effect.

-s
 
N

Nick Keighley


Grow up. Most platforms are Microsoft.
Absolute rubbish. [...] MS is a tiny drop in a rather large puddle.
I keep hearing all this. But since the 80's, most of the computers
I've been able to buy have come with a MS operating system. Most of
the rest have been Macs.

The computers you have been able to buy are not necessarily a
representative smaple of all computers

I didn't buy my last computer from either of those places (or other
high street shop)
My point-of-view is that of a hobbyist programmer. But even when I worked
for a (very small) company we were buying PCs with DOS or Windows, since
that was most of our clients had or could easily buy. I can't remember where
they were from, they just appeared.

(This has come up before and I understand some hobbyists do have esoteric
systems of various kinds.)

there's nothing wrong with confining yourself to Window's based
computers. What is wrong is to extrapolate your experience to the
entire world.

Actually I've little idea what a server is.

a usually rack mounted computer, usually placed in an air conditioned
room. Google for instance has rooms full of 'em. All large businesses
have tons of em too that do everything from tracking inventory to
issuing invoices to printing the wage checks. The world has been
running on this stuff since about 1960.

I'd imagine it's some machine accessed across a network.
usually

I would call it specialised,

so its a specialised computer. Why isn't it a computer? If you can
program it in C it's definitely a computer!

although the way the
internet works is blurring some of the distinctions.

I don't see why
(I started in computing using timesharing terminals connected to a single
large computer. A few years later with no job I drifted into hardware and
started using simple microprocessor computers that were 100% personal and
hands-on.

Great! Finally we could get away from monster computers, operating systems,
logins, passwords, quotas, booking of terminals... but 25 years on and we're
drifting back in that same direction, and in spades...)

the monster computers never went away they just changed names. There's
nothing stopping you from going back to a personnel computer. Just
pull out the network connection and turn off the password protection.
I don't recall having to book a terminal recently.

3 versions of Windows and 5 of Linux, and you think it's not specialised?..

I suggest you look up "specialised" in a dictionary.

All I'm saying is that my world is dominated by computers running MS
products

but your world isn't The World

and I don't think that's an uncommon situation. (Not all of us are
lucky to have been given cool jobs developing for all these other systems
that are always mentioned.)

but you are aware they exist

If I had to write a utility, let's say in C, to be sent to half a dozen
people I know, then if I compile it for x86-32 under Windows, I know they
will be able to run it. Compiled for anything else, they won't.

great. I'd do the same for friends and family.
 
S

spinoza1111

Clearly not. He's been told about them, and *still* hasn't fixed them.

Corporatese: the incompetent manager pretends to be the disapproving
Parent. You're not my boss and you never will be. Nor would I hire
you. So don't waste my time.

I don't want nits from either of you nitwits, Richard and Peter. I
want real problem reports. I don't have to conform to your standards,
because your standards are dysfunctional.

I think what bothers you clowns is that working a few hours on my
commute, I can craft a solution that works (with commonsense clerical
changes on your system) in a language I don't like and which I haven't
used for almost twenty years, whereas you could not do this, not in a
million years, in an unfamiliar language. I'd dare ya to do the
problem in C Sharp: you can get C Sharp free. But you won't try
because you're incompetent.
 
S

spinoza1111

Try to make constructive comments only. Thanks.

Every comment I've made has been constructive... Assuming you actually want
to be effective at using C.  If all you want to do is bitch about how
it's not the way you would have done it, I can't help so much.
// ***************************************************************

You should use /*...*/ comments for large comment blocks, the // feature
is really intended for one-line commments.
#include <stdio.H>
#include <stdlib.H>

You already caught these.
// ***** Constants ***********************************************
#define ABOUT_INFO \
"This application converts infix to Polish notation using a simple
grammar-based approach."

This seems unlikely to be frequently used.  In its presentation on Usenet,
this has been wrapped, but there's on general guarantee that you can embed
newlines in string literals portably.  I can't tell whether the original
was wrapped, though.
// --- Pass over white space
#define SKIP_WHITE_SPACE(s, i, e) \
    { for(; (i) <= (e) && (s)[(i)] == ' '; (i)++ ); }

This seems unnecessary.  You can do this with a while loop, for one
thing, for another, strspn() already exists.
// ***** Function index ******************************************
#define ADDFACTOR \
        int addFactor(char *strInfix, \
                      char *strPolish, \
                      int *intPtrIndex, \
                      int intEnd, \
                      int intMaxPolishLength)
ADDFACTOR;

As commented elsewhere, this doesn't buy you very much.
// ---------------------------------------------------------------
// Command line handler
//
// int main(int intArgCount, char **strArgs)

Right here, you instantly dispelled any possibility of a gain occurring
from the #defines above, because you're duplicating the text anyway.
MAIN
{
    int intMalloc = -1;
    printf("%s\n\n", ABOUT_INFO);

Printing this unconditionally seems unfriendly.
    if (intArgCount > 1)
        if ((intMalloc = string2UnsignedInt(strArgs[1])) < 0)

Let's see.

1.  The name "string2UnsignedInt" is reserved for the implementation,
so you shouldn't be using a function named that.
2.  If it doesn't actually return an unsigned int, it is misleadingly
and poorly named.
3.  If it does, the conversion will be undefined if someone enters
a value outside the signed range.
4.  And any time you have "unsigned" and a comparison with < 0 on the
same line, you're just ASKING for trouble, even if it all works now.
    return;

Needs a value.
    if (*intPtrIndex > intEnd) return -1;

I'm just going to pick this particular point to ask:

In general, do you intend this test to be ">" or ">="?
ERRORHANDLERSYNTAX
{
    int intIndex1 = 0;

This name is gratuitously verbose.

Have you ever seen a mathematician write "let realEpsilon1 be an arbitrarily
small value, we will now calcualet realDelta1 as a function of realEpsilon1?"

No?

There's a reason for that.

While there's a lot to be said for longer (and presumably clearer) names
in many cases, the loop iterators i, j, k are effective idioms, and failure
to use them makes it much easier to make common mistakes.
    printf("\nError at character %d: %s\n",
           intIndex,
           strMessage);
    printf("%s\n", strInfix);
    for (intIndex1 = 0; intIndex1 < intIndex; intIndex1++)
        printf(" ");
    printf("$");

I'd probably do:
        printf("%*s$\n", intIndex, "");
// ---------------------------------------------------------------
// Find one of a set of alternative characters

Again, you really ought to just be using the standard string library, since
it works just great and already exists.




    while(*intPtrIndex <= intEnd
          &&
          (chrNext = strInfix[*intPtrIndex]) >= '0'
          &&
          chrNext <= '9')
    {
        if (!stringAppendChar(strPolish,
                              chrNext,
                              intMaxPolishLength,
                              intSpaceBefore))
            return 0;
        intSpaceBefore = 0;
        (*intPtrIndex)++;
    }
    if (*intPtrIndex > intIndexStart)
        return -1;

It seems like it might make a tiny bit more sense to use <ctype.h>, and
write this something like
        if (isdigit(strInfix[*intPtrIndex])) {
          /* parse integer, then... */
          return -1;
        }

If only there were some handy integer-parsing code just lying around.
(BTW, for extra credit, figure out how to support negative integers...)




// ---------------------------------------------------------------
// Convert string to an unsigned integer
//
//      int string2UnsignedInt(char *strInstring)
//
//
STRING2UNSIGNEDINT
{
    int intIndex1 = 0;
    int intValue = 0;
    for (; strInstring[intIndex1] != '\0'; intIndex1++)
    {
        if (strInstring[intIndex1] < '0'
            ||
            strInstring[intIndex1] > '9') break;
        intValue = intValue * 10
                   +
                   strInstring[intIndex1] - (int)'0';
    }
    return intValue;
}

No checks for overflow, and the cast on '0' is unneeded.  In C++, it would
be of type char, so we could imagine you not being aware of the default
promotion rules, but in C, it's an int already, so the cast's useless.

This sort of thing is normally written using pointer notation, but even
more importantly, this sort of thing was already written much more carefully
and completely.
STRINGAPPENDCHAR
{
    int intLength = stringLength(strString);
    int intSpaceBeforeInEffect =
        intSpaceBefore
        &&
        intLength > 0
        &&
        strString[intLength - 1] != ' ';

Interesting feature, and not a bad idea.  I'm not sure it's really
necessary, because it seems like it'd be easy enough to set a protocol
up for when you add the spaces, but it's not awful.
    {
        errorHandler
            ("Cannot append character(s): insufficient storage");
        return 0;
    }

This is the kind of thing where it might be really nice for errorHandler
to be able to display formatted messages, because:

"Cannot append character '%c': insufficient storage", chrNew

would be a better message.
// ---------------------------------------------------------------
// Return string length

Still not useful.
    char *strPolish;
    int intMaxPolishLength = 0;
    int intReq = intMalloc > 0
                 ?
                 intMalloc
                 :
                 MAX((intMaxPolishLength
                      =
                      stringLength(strInfix) << 1)
                     +
                     1,
                     10);

Normally, people are pretty careful not to have side effects in a
macro that they know is likely to evaluate one of its arguments more than
once.

What is intMaxPolishLength if intMalloc igreater than zero?  It was
initialized to zero, and it only gets updated in the other branch of
the intReq initializaiton, so I think it's still zero, no?
    printf("\n\nConverting \"%s\": expect \"%s\"",
           strInfix,
           strExpected);
    strPolish = (char *)malloc(intReq);

Cast not needed.
    printf("\n\"%s\"\n",
           (infix2Polish(strInfix,
                         strPolish,
                         intMaxPolishLength)

You use intMaxPolishLength, but the allocated space in strPolish is
intReq.

Looks like a bug. Will follow up.
 
S

spinoza1111

Corporatese: the incompetent manager pretends to be the disapproving
Parent. You're not my boss and you never will be. Nor would I hire
you. So don't waste my time.

I don't want nits from either of you nitwits, Richard and Peter. I
want real problem reports. I don't have to conform to your standards,
because your standards are dysfunctional.

I think what bothers you clowns is that working a few hours on my
commute, I can craft a solution that works (with commonsense clerical
changes on your system) in a language I don't like and which I haven't
used for almost twenty years, whereas you could not do this, not in a
million years, in an unfamiliar language. I'd dare ya to do the
problem in C Sharp: you can get C Sharp free. But you won't try
because you're incompetent.








- Show quoted text -

And spare me the argument "duh, dis is a c programming newsgroup." I
tutor in constitutional law, and I note that Ian Loveland's textbok in
British constututional law, as well as Dicey's Introduction to the
Study of the Law of the Constitution, spend quite a lot of time in
COMPARATIVE theory.

Loveland STARTS with the American constitution. Dicey illuminates the
British constitution by giving a great deal of information about
*droit administratif* in French constitutions, because "droit
administratif* for Dicey is precisely missing in British law because
of rule of law, which *droit administratif* overthrows for a "raison
d'etat".

The problem with programmers: they overfocus of necessity on bug
finding and language details which makes them almost to a man narrow
and nasty low fellows, unable to see that you don't know C unless you
know at least five other languages.
 
B

bartc

You're gonna have to work harder on learning the terminology if you want
to discuss C and not just be laughed at.

Functions must be *declared* before use. The thing with a function body
is a definition, the one without a function body is a declaration, also
called a prototype. ....
Q: Why doesn't C just read the whole file to find a function's
definition?

A: Because prototypes would be needed anyway.

He has a point actually. There's no real need these days for function
prototypes, for functions which are defined in the same file at least.

(I have a language design of my own which does exactly that, eliminates most
prototypes, even for functions in separate modules. So it's not impossible.)
Prototypes are primarily used to address the fairly common case where the
function being called is defined in a separate "translation unit" (in most
cases, this means "source file", but there are technical differences).

(I fixed that by having an 'import' statement. Then a header file containing
exports of that other module (created automatically when it's compiled), is
included. But that only works well when the other module is an independent
library; when dependent functions are split arbitrarily across modules then
it gets messy)
At the time, it made sense to allow compilers to continue to, at least in
principle, be able to operate in a single pass. While that's less crucial
now perhaps than it used to be (as most modern optimizers end up needing
to work with everything in memory for a while), it's still considered a
plus for vendors targeting smaller systems. (In a fit of irony, Microsoft
systems were one of the targets that benefitted a lot from this, but of
course, they're not important.)

How many development computers these days are only capable of running a
single-pass compiler?
Or using functions only after their definition.


The canonical solution is, in fact, to declare the function once and
define it once, usually with the declaration in a header if it's going
to be used by or seen by other translation units.


The regular way is pretty easy to maintain if your prototypes don't change
too often, and if they change too often, they're changing too often.

The problem is having to maintain something defined in two different places:
the declaration, and the definition, which must match.

Anyway, aren't IDEs/programming editors now sophisticated enough to take
care of creating prototype declarations?
 
W

Willem

bartc wrote:
) )> Q: Why doesn't C just read the whole file to find a function's
)> definition?
)>
)> A: Because prototypes would be needed anyway.

I don't really follow that logic.
At the moment, prototypes are usually written *twice*.
The header of the function definition doubles as a prototype declaration.

) He has a point actually. There's no real need these days for function
) prototypes, for functions which are defined in the same file at least.
)
) (I have a language design of my own which does exactly that, eliminates most
) prototypes, even for functions in separate modules. So it's not impossible.)

I think it should be quite easy to incorporate into the C standard:

- An extra pass is added to the translation, which 'gathers all prototypes'.
(Or some other way to remove the requirement that functions are declared
before use.)

- A new '#import' directive is recognized which scans the given (.c) file
for all function declarations.

Like this, existing code should still work, but you can then also have code
where you remove all declarations that aren't definitions, and then simply
#import all the .c files from which you're calling functions.

Like so:

a.c:

#import "b.c"

int foo(char *x, char *y)
{
debug(x);
debug(y);
}

b.c:

#import "a.c"

int main(char **argv, int argc)
{
foo(argv[1], argv[2]);
return 0;
}

int debug(char *d)
{
printf("DEBUG: '%s'\n", d);
}




SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
K

Kenny McCormack

I hypothesize that the intent is to allow both a declaration and a
definition to use the same code.

I agree that it's pretty odd, though.

Not motivated by status at all, are you??

Nope, nope, nope..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,079
Messages
2,570,574
Members
47,205
Latest member
ElwoodDurh

Latest Threads

Top