How to convert Infix notation to postfix notation

N

Nick Keighley

good grief

looks pretty straightforward C to me. It's clearer than yours.


one idea would be to make you tester() function silent. Only print
something if the test fails. This will also mean your timeing tests
are testing the algorithm rather than the i/o.

This doesn't qualify as anything like theft or great thinking. For
fun, I wrote the code in about 5 minutes after the OP posted (based onhttp://groups.google.com/group/comp.lang.c/msg/fe772c9d6a28fdc4), but
refrained from posting it because it was probably homework for the
OP.  This is a standard example or homework assignment for just about
any undergrad course that covers recursive descent parsing.

I don't see the words "recursive descent parsing" in the OP
 
N

Nick Keighley

[...] I think you messed up the grammar [...]
expr -> term { [+-] term }
doesn't parse 1+1+1.
The curly braces are BNF for zero or more repeats.  This translates to
the while loop.  I can't see an error.

OK, I can deal with that. Thanks for the clarification. I don't recall
that notation being used by my teacher of compiler design in grad
school but it's been some time.

to pick a nit it's not BNF, that is the original notation defined by
Backus and Naur, but Extended BNF (EBNF). It's quite common. The C
standard uses it.
 
B

Ben Bacarisse

spinoza1111 said:
But I think you messed up the grammar...but not the code.
expr -> term { [+-] term }
doesn't parse 1+1+1.

The {} is a very common notation.  I agree that [+-] is not usual, but were
you at all puzzled by what the notation meant?  It is obviously
borrowed from regular expressions.

OK, that's correct: [+-] is "the set of characters including plus and
minus" where one character is chosen from the set. But I shouldn't
have to do the work of expressing things clearly on your behalf in
English.

Nor should regular expression notation be mixed into BNF unless
absolutely necessary.

Most extended grammar notations use very similar nation to that used
in regular expressions. I don't see a problem with that.
But in neither notation do curley braces imply iteration and as far as
I can see you need iteration to parse 1+1+1. What am I missing, dear
Ben?

That {} denotes repetition in all the forms of EBNF that I have seen.
They both look wrong (and note that unlike some of the thugs and
twerps here I don't infer your global ignorance). Period ordinarily
means end of string (which is needed as I have said when you do not
lookahead to balance parentheses)....not iteration.

In Wirth's version of EBNF (note the E) . ends the production. ()s
indicate grouping and | alternation (as in most regular expression
syntax) and {} repetition zero or more times.
The second is in particular absurd. If by | you mean BNF or, then
you're saying that an expr may start with a plus sign. If you add
unary minus it may but I do not believe this was your intent.

No, I missed the term that starts each alternation:

expr = term | term { "+" , term } | term { "-" , term } ;

Where () can't be used to group and alternation, the alternatives get
more complex. The point being that in both Wirth's EBNF and in plain
EBNF {} means repetition.
I think
you either have a private BNF notation, Bacarisse Normal Form, or you
don't know how to use BNF at all.

Here is the correct BNF as far as I can tell:

expr := addFactor
expr := addFactor ( [+-] addFactor ) *

You keep saying BNF but all these are extended notations. BNF used
As a favor to you I use the square bracket set notation and instead of
square brackets for optional sequence I've split the production into
two parts, using round parentheses to group and asterisk to iterate.

Your notation -- specifically adding * after an optional item -- is
not common. I've not seen it in any text. Some EBNFs do use * but as
a operator applied to any element. Applying it to something optional
is redundant.

<snip>
 
B

Ben Bacarisse

Seebs said:
A lot of people are not aware that time_t is not required to be only 32
bits.

No, or that time_t does not have to be an integer; does not have to
count seconds; and does not have to use a fixed base time of 1st Jan
1970.

Of course, given common usage and other standards like POSIX, a wider
integer time_t is the simplest solution:

$ cat time.c
#include <stdio.h>
#include <time.h>
#include <limits.h>

int main(void)
{
printf("Clock good for another %.0f million years\n",
difftime(LLONG_MAX, time(0)) / (365.0 * 1e6 * 24 * 60 * 60));
return 0;
}
$ ./time
Clock good for another 292471 million years
 
D

Dik T. Winter

> But in neither notation do curley braces imply iteration and as far as
> I can see you need iteration to parse 1+1+1. What am I missing, dear
> Ben?

In that case you see wrong.
....
> They both look wrong (and note that unlike some of the thugs and
> twerps here I don't infer your global ignorance).

From the revised report on Pascal:
<set> ::= [ <expression> {, <expression>} ] | []
or
<case label list> ::= <case label> {, <case label>}

And from the introduction:
"If a sequence of constructs to be repeated consists of more than
one element, it is enclosed by the meta-brackets { and } which
imply a repetition of 0 or more times."

[ Niklaus Wirth, The Programming Language Pascal (Revised Report),
ETH Zurich, November 1972.]
 
S

spinoza1111

spinoza1111 said:
<snip>
But I think you messed up the grammar...but not the code.
expr -> term { [+-] term }
doesn't parse 1+1+1.
The {} is a very common notation.  I agree that [+-] is not usual, but were
you at all puzzled by what the notation meant?  It is obviously
borrowed from regular expressions.
OK, that's correct: [+-] is "the set of characters including plus and
minus" where one character is chosen from the set. But I shouldn't
have to do the work of expressing things clearly on your behalf in
English.
Nor should regular expression notation be mixed into BNF unless
absolutely necessary.

Most extended grammar notations use very similar nation to that used
in regular expressions.  I don't see a problem with that.
But in neither notation do curley braces imply iteration and as far as
I can see you need iteration to parse 1+1+1. What am I missing, dear
Ben?

That {} denotes repetition in all the forms of EBNF that I have seen.
They both look wrong (and note that unlike some of the thugs and
twerps here I don't infer your global ignorance). Period ordinarily
means end of string (which is needed as I have said when you do not
lookahead to balance parentheses)....not iteration.

In Wirth's version of EBNF (note the E) . ends the production.  ()s
indicate grouping and | alternation (as in most regular expression
syntax) and {} repetition zero or more times.
The second is in particular absurd. If by | you mean BNF or, then
you're saying that an expr may start with a plus sign. If you add
unary minus it may but I do not believe this was your intent.

No, I missed the term that starts each alternation:

  expr = term | term { "+" , term } | term { "-" , term } ;

Where () can't be used to group and alternation, the alternatives get
more complex.  The point being that in both Wirth's EBNF and in plain
EBNF {} means repetition.
I think
you either have a private BNF notation, Bacarisse Normal Form, or you
don't know how to use BNF at all.
Here is the correct BNF as far as I can tell:
expr := addFactor
expr := addFactor ( [+-] addFactor ) *

You keep saying BNF but all these are extended notations.  BNF used
As a favor to you I use the square bracket set notation and instead of
square brackets for optional sequence I've split the production into
two parts, using round parentheses to group and asterisk to iterate.

Your notation -- specifically adding * after an optional item -- is
not common.  I've not seen it in any text.  Some EBNFs do use * but as
a operator applied to any element.  Applying it to something optional
is redundant.

<snip>

Here is the latest C version, based on my grammar. The issues you
raised have been fixed, and documentation has been added. The code
list is followed by the output.

The code list tabbing may be incorrect.


// ***************************************************************
// * *
// * 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 *
// * information, see the readme.TXT file in this project. *
// * *
// * *
// * C H A N G E R E C O R D --------------------------------- *
// * DATE PROGRAMMER DESCRIPTION OF CHANGE *
// * -------- --------- --------------------------------- *
// * 11 01 09 Nilges Version 1 *
// * *
// * 11 03 09 Nilges Version 2 *
// * ANON 1. Commenting added DONE *
// * 2. Routine index added with *
// * forward definitions DONE *
// * 3. Expected/actual cleanup DONE *
// * 4. Bug? Seems to convert Polish *
// * expression to value of first *
// * token without complaint *
// * FIXED *
// * 5. Minor bug: extra spaces in *
// * polish expression FIXED *
// * 6. Bugs as found by anon *
// * 8.1 1) FIXED *
// * 8.2 (((1)))) FIXED *
// * 7. Predetermine malloc using *
// * number of symbols other than *
// * parentheses and white space *
// * *
// * I S S U E S ----------------------------------------------- *
// * DATE POSTER DESCRIPTION AND RESOLUTION *
// * -------- --------- --------------------------------- *
// * 11 03 09 Nilges Version 3 plan *
// * 1. Random expressions *
// * 2. Integrate in GUI with C sharp,*
// * versions from Gene & anon *
// * 3. Predetermine malloc using *
// * number of symbols other than *
// * parentheses and white space *
// * *
// ***************************************************************

#include <stdio.H>
#include <stdlib.H>

// ***** Constants ***********************************************
#define MAX_POLISH_LENGTH 100
#define ABOUT_INFO \
"This application converts infix to Polish notation using a simple
grammar and two different implementations. It also contains testing
and timing facilities."

// ***** Macros **************************************************

// --- Pass over white space
#define SKIP_WHITE_SPACE(s, i, e) \
{ for(; (i) <= (e) && (s)[(i)] == ' '; (i)++ ); }

// ***** Function index ******************************************
#define ADDFACTOR \
int addFactor(char *strInfix, \
char *strPolish, \
int *intPtrIndex, \
int intEnd)
ADDFACTOR;
#define ERRORHANDLER \
int errorHandler(char *strMessage)
ERRORHANDLER;
#define ERRORHANDLERSYNTAX \
int errorHandlerSyntax(int intIndex, \
char *strMessage, \
char *strInfix)
ERRORHANDLERSYNTAX;
#define EXPRESSION \
int expression(char *strInfix, \
char *strPolish, \
int *intPtrIndex, \
int intEnd)
EXPRESSION;
#define INFIX2POLISH \
char *infix2Polish(char *strInfix)
INFIX2POLISH;
#define MAIN \
int main(int intArgCount, char **strArgs)
MAIN;
#define MULFACTOR \
int mulFactor(char *strInfix, \
char *strPolish, \
int *intPtrIndex, \
int intEnd)
MULFACTOR;
#define STRINGAPPENDCHAR \
int stringAppendChar(char *strInstring, \
char chrNew, \
int intMaxLength, \
int intSpaceBefore)
STRINGAPPENDCHAR;
#define STRINGLENGTH \
int stringLength(char *strInstring)
STRINGLENGTH;
#define TESTCASE \
void testCase(char *strInfix, char *strExpected)
TESTCASE;
#define TESTER \
void tester()
TESTER;

// ***** Functions ***********************************************

// ---------------------------------------------------------------
// Command line handler
//
// int main(int intArgCount, char **strArgs)
//
MAIN
{
tester();
return;
}

// ---------------------------------------------------------------
// Parse add factor
//
// int addFactor(char *strInfix,
// char *strPolish,
// int *intPtrIndex,
// int intEnd)
//
// addFactor = mulFactor [ *|/ mulFactor ]
//
ADDFACTOR
{
char chrMulOp = ' ';
int intStartIndex = 0;
if (!mulFactor(strInfix, strPolish, intPtrIndex, intEnd))
{
errorHandlerSyntax(*intPtrIndex,
"mulFactor not found",
strInfix);
return 0;
}
if (*intPtrIndex > intEnd) return -1;
intStartIndex = *intPtrIndex;
while (1)
{
SKIP_WHITE_SPACE(strInfix, (*intPtrIndex), intEnd)
if (*intPtrIndex > intEnd) break;
if ((chrMulOp = strInfix[*intPtrIndex]) != '*'
&&
chrMulOp != '/')
return -1;
(*intPtrIndex)++;
if (*intPtrIndex > intEnd
||
!mulFactor(strInfix,
strPolish,
intPtrIndex,
intEnd))
return errorHandlerSyntax
(*intPtrIndex,
"Mul/div op not followed by mulFactor",
strInfix);
if (!stringAppendChar(strPolish,
chrMulOp,
MAX_POLISH_LENGTH,
1)) return 0;
}
return -1;
}

// ---------------------------------------------------------------
// Error handler
//
// int errorHandler(char *strMessage)
//
ERRORHANDLER
{
printf("\n%s\n", strMessage); return 0;
}

// ---------------------------------------------------------------
// Syntax error handler
//
// int errorHandlerSyntax(int intIndex,
// char *strMessage,
// char *strInfix)
//
ERRORHANDLERSYNTAX
{
int intIndex1 = 0;
printf("\nError at character %d: %s\n",
intIndex,
strMessage);
printf("%s\n", strInfix);
for (intIndex1 = 0; intIndex1 < intIndex; intIndex1++)
printf(" ");
printf("$");
return 0;
}

// ---------------------------------------------------------------
// Parse expression
//
// int expression(char *strInfix,
// char *strPolish,
// int *intPtrIndex,
// int intEnd)
//
EXPRESSION
{ /* expression = addFactor [ +|- addFactor ] */
char chrAddOp = ' ';
int intStartIndex = 0;
if (!addFactor(strInfix, strPolish, intPtrIndex, intEnd))
{
errorHandlerSyntax(*intPtrIndex,
"addFactor not found",
strInfix);
return 0;
}
intStartIndex = *intPtrIndex;
while (1)
{
SKIP_WHITE_SPACE(strInfix, (*intPtrIndex), intEnd)
if (*intPtrIndex > intEnd) break;
if ((chrAddOp = strInfix[*intPtrIndex]) != '+'
&&
chrAddOp != '-')
return
errorHandlerSyntax
(*intPtrIndex,
"Unrecognizable char found instead of add op",
strInfix);
(*intPtrIndex)++;
if (*intPtrIndex > intEnd
||
!addFactor(strInfix,
strPolish,
intPtrIndex,
intEnd))
return errorHandlerSyntax
(*intPtrIndex,
"Add/sub op not followed by addFactor",
strInfix);
stringAppendChar(strPolish,
chrAddOp,
MAX_POLISH_LENGTH,
1);
}
return -1;
}

// ---------------------------------------------------------------
// Convert infix to Polish
//
// char *infix2Polish(char *strInfix)
//
INFIX2POLISH
{
int intIndex = 0;
char *strPolish = malloc(MAX_POLISH_LENGTH);
if (strPolish == 0)
errorHandler("Can't get storage");
strPolish[0] = '\0';
if (!expression(strInfix,
strPolish,
&intIndex,
stringLength(strInfix) - 1))
{
errorHandler("Can't parse expression");
return "";
}
return strPolish;
}

// ---------------------------------------------------------------
// Parse multiplication factor
//
// int mulFactor(char *strInfix,
// char *strPolish,
// int *intPtrIndex,
// int intEnd)
//
// mulFactor = LETTER | NUMBER | '(' expression ')'
//
MULFACTOR
{ int intIndexStart = 0;
int intLevel = 0;
char chrNext = ' ';
int intInner = 0;
int intSpaceBefore = 0;
SKIP_WHITE_SPACE(strInfix, (*intPtrIndex), intEnd)
if (*intPtrIndex > intEnd)
return errorHandlerSyntax(*intPtrIndex,
"mulFactor unavailable",
strInfix);
chrNext = strInfix[*intPtrIndex];
if (chrNext >= 'a' && chrNext <= 'z')
{
(*intPtrIndex)++;
return stringAppendChar(strPolish,
chrNext,
MAX_POLISH_LENGTH,
1);
}
intIndexStart = *intPtrIndex;
intSpaceBefore = -1;
while(*intPtrIndex <= intEnd
&&
(chrNext = strInfix[*intPtrIndex]) >= '0'
&&
chrNext <= '9')
{
if (!stringAppendChar(strPolish,
chrNext,
MAX_POLISH_LENGTH,
intSpaceBefore))
return 0;
intSpaceBefore = 0;
(*intPtrIndex)++;
}
if (*intPtrIndex > intIndexStart)
return -1;
if (chrNext == '(')
{
intLevel = 1;
(*intPtrIndex)++;
intInner = *intPtrIndex;
while (intLevel > 0 && *intPtrIndex <= intEnd)
{
if ((chrNext = strInfix[(*intPtrIndex)++]) == '(')
{
intLevel++;
}
else
{
if (chrNext == ')')
{
intLevel--;
}
}
}
if (intLevel != 0)
return errorHandlerSyntax
(*intPtrIndex,
"Unbalanced left parenthesis",
strInfix);
if (!expression(strInfix,
strPolish,
&intInner,
*intPtrIndex - 2))
return errorHandlerSyntax
(intInner,
"Expression doesn't appear in parentheses",
strInfix);
return -1;
}
return 0;
}

// ---------------------------------------------------------------
// Append character to string
//
// int stringAppendChar(char *strInstring,
// char chrNew,
// int intMaxLength,
// int intSpaceBefore)
//
STRINGAPPENDCHAR
{
int intLength = stringLength(strInstring);
int intSpaceBeforeInEffect =
intSpaceBefore
&&
intLength > 0
&&
strInstring[intLength - 1] != ' ';
if (intLength
>=
intMaxLength - (intSpaceBeforeInEffect ? 2 : 1))
{
errorHandler
("Cannot append character(s): string too long");
return 0;
}
if (intSpaceBeforeInEffect)
{
strInstring[intLength++] = ' ';
}
strInstring[intLength] = chrNew;
strInstring[intLength + 1] = '\0';
return -1;
}

// ---------------------------------------------------------------
// Return string length
//
// int stringLength(char *strInstring)
//
STRINGLENGTH
{
int intIndex1;
for (intIndex1 = 0;
strInstring[intIndex1] != '\0';
intIndex1++) { }
return intIndex1;
}

// ---------------------------------------------------------------
// Test case
//
// void testCase(char *strInfix, char *strExpected)
//
TESTCASE
{
printf("\n\nConverting \"%s\": expect \"%s\"",
strInfix,
strExpected);
printf("\n\"%s\"\n",
infix2Polish(strInfix));
}

// ---------------------------------------------------------------
// Tester
//
// void tester()
//
TESTER
{
testCase("(10+613)*a", "10 613 + a *");
testCase(")", "Error");
testCase("1)", "Error");
testCase("(((1))))", "Error");
testCase("10 113 + a *", "Error");
testCase("(10 + 113) * a", "10 113 + a *");
testCase(" ( 10 + 113 ) * a ", "10 113 + a *");
testCase("(", "Error");
testCase("((((2", "Error");
testCase("////2", "Error");
testCase("", "Error");
testCase("()", "Error");
testCase("(((5))", "Error");
testCase("(((5)))", "5");
testCase("((5))", "5");
testCase("5", "5");
testCase("((10+(113-(2+((((((2/(4+3)))))))+2+2))))*a", "10 113 2 2 4
3 + / + 2 + 2 + - + a *");
testCase("1+1", "1 1 +");
testCase("a", "a");
testCase(" a + b ", "a b +");
}





Converting "(10+613)*a": expect "10 613 + a *"
"10 613 + a *"


Converting ")": expect "Error"
Error at character 0: mulFactor not found
)
$
Error at character 0: addFactor not found
)
$
Can't parse expression

""


Converting "1)": expect "Error"
Error at character 1: Unrecognizable char found instead of add op
1)
$
Can't parse expression

""


Converting "(((1))))": expect "Error"
Error at character 7: Unrecognizable char found instead of add op
(((1))))
$
Can't parse expression

""


Converting "10 113 + a *": expect "Error"
Error at character 3: Unrecognizable char found instead of add op
10 113 + a *
$
Can't parse expression

""


Converting "(10 + 113) * a": expect "10 113 + a *"
"10 113 + a *"


Converting " ( 10 + 113 ) * a ": expect "10 113 + a *"
"10 113 + a *"


Converting "(": expect "Error"
Error at character 1: Unbalanced left parenthesis
(
$
Error at character 1: mulFactor not found
(
$
Error at character 1: addFactor not found
(
$
Can't parse expression

""


Converting "((((2": expect "Error"
Error at character 5: Unbalanced left parenthesis
((((2
$
Error at character 5: mulFactor not found
((((2
$
Error at character 5: addFactor not found
((((2
$
Can't parse expression

""


Converting "////2": expect "Error"
Error at character 0: mulFactor not found
////2
$
Error at character 0: addFactor not found
////2
$
Can't parse expression

""


Converting "": expect "Error"
Error at character 0: mulFactor unavailable

$
Error at character 0: mulFactor not found

$
Error at character 0: addFactor not found

$
Can't parse expression

""


Converting "()": expect "Error"
Error at character 1: mulFactor unavailable
()
$
Error at character 1: mulFactor not found
()
$
Error at character 1: addFactor not found
()
$
Error at character 1: Expression doesn't appear in parentheses
()
$
Error at character 2: mulFactor not found
()
$
Error at character 2: addFactor not found
()
$
Can't parse expression

""


Converting "(((5))": expect "Error"
Error at character 6: Unbalanced left parenthesis
(((5))
$
Error at character 6: mulFactor not found
(((5))
$
Error at character 6: addFactor not found
(((5))
$
Can't parse expression

""


Converting "(((5)))": expect "5"
"5"


Converting "((5))": expect "5"
"5"


Converting "5": expect "5"
"5"


Converting "((10+(113-(2+((((((2/(4+3)))))))+2+2))))*a": expect "10
113 2 2 4 3 + / + 2 + 2 + - + a *"
"10 113 2 2 4 3 + / + 2 + 2 + - + a *"


Converting "1+1": expect "1 1 +"
"1 1 +"


Converting "a": expect "a"
"a"


Converting " a + b ": expect "a b +"
"a b +"
 
S

spinoza1111

spinoza1111 said:
<snip>
But I think you messed up the grammar...but not the code.
expr -> term { [+-] term }
doesn't parse 1+1+1.
The {} is a very common notation.  I agree that [+-] is not usual, but were
you at all puzzled by what the notation meant?  It is obviously
borrowed from regular expressions.
OK, that's correct: [+-] is "the set of characters including plus and
minus" where one character is chosen from the set. But I shouldn't
have to do the work of expressing things clearly on your behalf in
English.
Nor should regular expression notation be mixed into BNF unless
absolutely necessary.

Most extended grammar notations use very similar nation to that used
in regular expressions.  I don't see a problem with that.

Fair enough.
That {} denotes repetition in all the forms of EBNF that I have seen.
OK.


In Wirth's version of EBNF (note the E) . ends the production.  ()s
indicate grouping and | alternation (as in most regular expression
syntax) and {} repetition zero or more times.

Does the period in Wirth-EBNF mean "the symbol we use to represent end
of file explicitly"?
No, I missed the term that starts each alternation:

  expr = term | term { "+" , term } | term { "-" , term } ;

Thanks for clarification.
Where () can't be used to group and alternation, the alternatives get
more complex.  The point being that in both Wirth's EBNF and in plain
EBNF {} means repetition.

I withdraw that statement. You are in fact current on more notations
than I.
Here is the correct BNF as far as I can tell:
expr := addFactor
expr := addFactor ( [+-] addFactor ) *

You keep saying BNF but all these are extended notations.  BNF used
<>s and ::= and has no shorthand for optional or repeated elements.

OK, it's my BNF, and it's less standard than yours. Your point is
conceded.
Your notation -- specifically adding * after an optional item -- is
not common.  I've not seen it in any text.  Some EBNFs do use * but as
a operator applied to any element.  Applying it to something optional
is redundant.

That is correct.
 
S

spinoza1111

good grief

You snipped the other alternative, which was "great minds think
alike".
looks pretty straightforward C to me. It's clearer than yours.

I really wish people would qualify "clarity" and relativise it to
their perception. Like Seebach, you use the word "clarity" here. His
code is more to your taste: I can deal with that. But not "clearer"
except for a reader who prefers a terse style.
Yup.

one idea would be to make you tester() function silent. Only print
something if the test fails. This will also mean your timeing tests
are testing the algorithm rather than the i/o.

....not if the test material is a constant...
I don't see the words "recursive descent parsing" in the OP

I don't think the professor taught him RDP. That would be material
introduced in a compiler course.
 
S

spinoza1111

Richard, either participate in the discussion (examining the code and
reporting bugs or pissing and moaning about style if you must) or just
leave the room.
 
S

spinoza1111

Which part of the C standard do you believe links C to the year 2038?

Date precision. Ever wonder why spam is dated 2038? Did the standards
fix this problem?
 
B

Ben Bacarisse

In Wirth's version of EBNF (note the E) . ends the production.  ()s
indicate grouping and | alternation (as in most regular expression
syntax) and {} repetition zero or more times.

Does the period in Wirth-EBNF mean "the symbol we use to represent end
of file explicitly"?[/QUOTE]

No, it denotes the end of the grammar rule. It is meta-syntax.

<snip>
 
B

Ben Bacarisse

spinoza1111 said:
Date precision. Ever wonder why spam is dated 2038? Did the standards
fix this problem?

I am sure you can see this does not answer the question. Chris
McDonald was asking specifically about C. You seem to think there is
a problem with C's date/time functions.
 
S

Seebs

I really wish people would qualify "clarity" and relativise it to
their perception. Like Seebach, you use the word "clarity" here. His
code is more to your taste: I can deal with that. But not "clearer"
except for a reader who prefers a terse style.

This is not entirely accurate. There are measurable traits such as the
time it takes people to read code, or the reliability with which they
read it. Your version of this had a lot more fluff between the code
and the reader.

-s
 
S

Seebs

Date precision.

Uh, well, no.
Ever wonder why spam is dated 2038? Did the standards
fix this problem?

The standard never had this problem. Individual implementors have chosen
different ways of representing dates; it's up to them to decide which
representation they want. POSIX does specify a representation in seconds
since Jan 1 1970 UTC, but does not specify a particular limit on the size
of the object used to store that value.

-s
 
S

spinoza1111


Hmm, didn't see your comments. If you contribute a bug report or good
suggestion for change, I shall incorporate it.
Don't capitalize the "H" -- while it may happen to work on your system,
it means the code won't compile on others.  Even an easily-fixed compile
error makes people likely to discount your code.

Got it. Thanks.
This always returns the same value, why does it have a return value at
all?

I do this all the time in C Sharp, because when I call the error
handler I am usually preparing to return from any caller with a
Boolean value, and my practice, in C Sharp, is to always return true
or false from any method that does not otherwise return a value. Saves
a lot of bullshit and enables optimization, in my understanding.
If this is for an error message, why isn't it using stderr for its output?

Because there is no meaningful distinction anymore between stderr and
stdout, and the disctinction is legacy.
The double-\n thing is a bit unusual; normally a convention is adopted
where messages should either end with (normally) or start with (less
often) a newline, rather than providing two.  In particular, if there are
two consecutive error messages for some reason, this would produce a blank
line between them.
Yes. I like white space.
It would seem much more useful to implement this function using ... arguments
and the underlying vfprintf() to allow formatted messages to be displayed..
If I were writing a function to this effect, I'd probably do:

        void
        errorHandler(char *msg, ...) {
                va_list ap;
                va_start(ap, fmt);
                vfprintf(stderr, fmt, ap);
                va_end(ap);
        }

I don't see the worth of this at this time, but I may be missing
something.
You prefix the variable's name with a type.  While that certainly CAN be
a reasonable thing, it's important to ensure that the type used is a real
abstract type, not merely a language type -- language types are already
type checked.

Do you mean my use of Hungarian here?
You're using Systems Hungarian here, which is crap.  Don't.  Apps Hungarian
is what Simonyi proposed and demonstrated to be useful.  Systems Hungarian
isn't useful, and leads to bugs later.

This is not my experience, especially with modern editors. It doesn't
cause bugs unless it is not maintained. What part of strong typing
don't you understand?
This is a useless message.  It doesn't tell the user what the character
IS, nor does it give the user any feedback as to the nature of the message.
And, again, suggest that you implement format arguments.

The most recent version prints the infix expression and puts a dollar
sign under the error point, so your point is taken. The strMessage
gives the "feedback".
int stringLength(char *strInstring)
{
   int intIndex1;
   for (intIndex1 = 0;
            strInstring[intIndex1] != '\0';
            intIndex1++) { }
   return intIndex1;
}

Why the **** did you even write this?  

Because string.h is fucking fucked.
strlen() exists for a reason.

I don't choose to include libraries unnecessarily when I can write a
little code for the limited amount of functionality that I need.
And just for extra credit:  This name is reserved for use exclusively
by the implementation, since it starts with "str" followed by a lowercase
letter.  In practice it's likely harmless in modern systems because
names are usually case-sensitive, and the standard doesn't define library
functions with camelCase.

But it's still stupid.

In your view. In my view, the "library" approach of C is horseshit
because you get a Lot Of Useless Crap for one little function that you
need.
int stringAppendChar(char *strInstring,
                                    char chrNew,
                                    int intMaxLength)
{
   int intLength = stringLength(strInstring);
   if (intLength >= intMaxLength - 1)
   {
           errorHandler
                   ("Cannot append character: string too long");
           return 0;
   }
   strInstring[intLength] = chrNew;
   strInstring[intLength + 1] = '\0';
   return -1;
}

int
stringAppendChar(char *s, char c, size_t max) {
        char *end = strchr(s, '\0');
        if (end - s < max) {
                *end++ = c;
                *end = '\0';
                return end - s;
        } else {
                return -1;
        }

}

Note that I've changed the sense of the return value.  This is because
by convention -1 indicates a failure.  Returning the actual length,
rather than a meaningless value, gives the caller some additional
information.

No, -1 is the truest true value. My understanding (let me know if it's
changed since 1991), zero is falseness whereas nonzero is truthiness.
Well, -1, on twos-complement systems, which despite your nonsense in
C: The Complete Nonsense are dominant, is the number least like zero
since it's all ones and isn't that a kiss my ass?

Note that I've preserved the probable-bug, which is that if you have an
array of 15 characters, and you call this function with the limit 15 on
an array containing 14 non-zero characters and a null byte,
it'll write the 16th character of the 15-character array.  That's almost
always a bad choice.

Making sure that the only string I allocate and append to, the Polish
string, is on my to do. I was worried about screwing that up, but I
malloc'd 100 bytes for the Polish string, and none of my test cases
approach that length.

The next version (not the one I posted this evening, Nov 3 in China
time) will malloc n characters for the Polish, where n is the number
of characters in the infix less the number of parentheses and blanks.
This will break the string append if I didn't do it right, and I shall
in all probability incorporate this observation.
I've omitted the ridiculous error message call, for reasons which shall
become apparent.

So it's ridiculous to give a humane error message? Explain.
This is just plain horrid.  The layout is surreal, and the logic
opaque.

The layout is the result of tabs being converted to blanks. Tomorrow I
shall resubmit the detabbed code.
I think you mean:

int appendPolish(char *strPolish, char chrNext)
{
  if (*strPolish == ' ' || *strPolish == '\0')
    return -1;
  ... wait, this doesn't even make sense.

}

This function aborts if the FIRST character of strPolish is a space or
a null, but then appends characters off at the end of strPolish.  This
makes no sense.  You'll have to put in some kind of explanatory comment
to justify that.
This code has been rewritten, so your point may be correct, but it's
moot.
There's also the fact that calling stringAppendChar three times in a row
is stupid.  Figure out how many characters are left, and if there's enough
room for three, append all three at once.  Appending one or two of them
is not useful.

Point taken. The code was rewritten. Great minds think alike. You too.
This is a crappy error message.  The problem has nothing at all to do with
mulFactor.  It has to do with you having, apparently, run out of room
or something.  So say so; give a message like "string too long".

Study the code a little more thoroughly. While this particular test
may have changed in my Nov 3 version, it was necessary in this version
because mulFactor in all versions must needs incorporate the functions
of a scanner (including testing end of input). If input has been
exhausted, we have entered mulFactor expecting a multiply factor and
there is none.
This is the point where you should be calling a different function that
handles parenthesized expressions, IMHO.


Ugh.

Seems like this would be a great time to refactor this more sanely.  In
particular, you're having the higher-level code (mulfactor) try to guess
the range of the substring.

Yes, I said it looks ahead.
If it didn't it would be dead.

In this code, mulFactor integrates scanning and parsing and is
lowlevel. As I have said elsewhere, it might be better to avoid this
lookahead by making "end of input" a grammar category, but this "ugly"
code is elegant in context, since I wanted to keep the program short;
it seemed overkill to write a lexical scanner for mulFactor to call.
What happens when someone asks you to support strings?  

At that point, I factor. Premature factorization especially for you
bums is in my experience a waste of time.
Then suddenly
mulfactor() has to be smart enough to find the end of:
        (a + ")")

and you're making a ton of work.  Wrong.  When you see the (, pass it off
to the function which tries to find an expression followed by a trailing ),
and have the expression parser hand what it found so far back up when it
sees the ) -- at which point the parens function finds its trailing ) and is
happy.

"The function which tries to find an expression followed by a
trailing )"? Give me a break. That's not a grammar category and
writing such a function is asking for trouble.

It's not necessarily ugly to "read ahead": cf the 2nd ed. of the
Dragon Book, p 78. Also, see Nilges' "Build Your Own Goddamn .Net
Language and Goddamn Compiler" for a discussion of the need for
lookahead in processing unary minus and right parentheses. I worked
through these issues several years ago in VB, and if you care to
comment on my approaches, buy my book. Of course, if you do a hatchet
job on the book, I'll be on your case like a fly on shit...save where
you are right in any important way, in which case I will help you
write your critique and get your errata into Apress' Web site.

Reading ahead steps outside the formal grammar paradigm, but think of
it as having an "oracle": this metaphor was used in an old MacDonald
Elsevier "Monograph in Computer Science": the one, in fact, on
compiler development. It's like using a lex symbol to represent end of
input.
Sure enough, you did what I thought you'd do.  You allocate MAX_POLISH_LENGTH
characters, but then, you use MAX_POLISH_LENGTH as the cap you pass to
strAppendChar, meaning that if your Polish string contains MAX_POLISH_LENGTH-1
characters, you will end up writing one past the end of the array.

Point taken. I was suspicious of the code myself since I have
encountered that problem before. It's an artifact of the unsafe design
of the Infantile Disorder in which I am coding. My plan was to address
it when I got around to doing an EXACT malloc of n bytes, where n is
the number of nonparentheses and nonblanks in the infix string plus
one for the Stupid Nul Byte.
It turns out that the fencepost conventions people use in C are there for
a good reason.
   if (strPolish == 0)
           errorHandler("Can't get storage");
   strPolish[0] = '\0';

Since errorHandler doesn't exit in any way, you're still going to segfault
(or whatever) when you reach this line.

Thanks for pointing this out. Probably should return.
Oh, that's great.  You are now returning pointers from this function which
MAY OR MAY NOT be the results of malloc(), so you can't free them safely.

Very good point.
This should be:
        strPolish[0] = '\0';
        return strPolish;
Excellent. You should turn pro.
Because infix2Polish allocates memory, but you never free the results, this
is a memory leak.

Don't be a silly bastard. It's not a memory leak since I return to main
() (I was tempted to return void just to piss you off but Microsoft C
sets me up with int main()). Now you're making silly comments just to
pad your anti-resume. Shape up.

Nonetheless, I like the idea of having a free for every malloc, since
there's this cool computer author that recommends doing this, and it
makes eminent sense.

{Chortle)

Therefore I shall fix this.
Renaming the args to main, not useful.  Declaring them when you're not using
them, also not useful.

I prefer that all things use my naming style, thank you. And they are
for later use.
return without a value in function not returning void

Okay, I will concede one point:  You would actually be better off reading
Schildt's books than muddling along without.  You'd be even better off reading
a better C book, but really, any port in a storm.

Bite my crank.

But thanks for your observations. Not as good as Bacarisse but at
least you jumped in and got to work, unlike your friend Heathfield,
who's trashed so many people that he's afraid to make a mistake.

Furthermore, thanks to your help and my own coding and testing, I am
ramping back up quickly in C and shall shortly, if I persist, run
rings around you. This is because Princeton was right when they
refused to conduct classes at uni level in C, and had a mere Roosevelt
graduate (me) teach C. A programming language is easy to learn: it's
the science and effective style that's difficult...the latter so much
so, that most programmers' opinions on style are worthless (your views
on Hungarian being an example).

However, C is also a waste of spirit in an expense of shame. I am also
an artist and a teacher, and instead of focusing on nonsense problems
that wouldn't exist if C had been designed not misbegotten I could be
preparing classes or painting pictures. Instead I am muttering over
runes from the Dark Ages and the process is making me crabby. I am
having to restrain myself from kicking small animals.

Nonetheless I shall persist for now, in order to demonstrate that two
propositions are true. One is that I'm smarter than you. The other is
that we can work together to find bugs in each others' code because
nobody is too smart to make stupid mistakes, a lesson which if you
learn well will, I hope, cause you to withdraw The Vicious Tirade.
 
S

Seebs

On Nov 3, 2:39 am, Seebs <[email protected]> wrote:
I do this all the time in C Sharp, because when I call the error
handler I am usually preparing to return from any caller with a
Boolean value, and my practice, in C Sharp, is to always return true
or false from any method that does not otherwise return a value. Saves
a lot of bullshit and enables optimization, in my understanding.

Be interesting to know how it "enables optimization".
Because there is no meaningful distinction anymore between stderr and
stdout, and the disctinction is legacy.

Simply untrue -- there's a ton of systems out there which maintain the
distinction clearly. Again, if you're posting code that might some day
be used or tried by other people, doing things right matters even if it
doesn't have a discernable effect on your system. There is a difference
there, even if it doesn't affect your personal desktop.
Yes. I like white space.

Blank lines used for emphasis are useful, blank lines which flood the display
with blank lines just disrupt the reader's flow.
I don't see the worth of this at this time, but I may be missing
something.

Consider the option of writing messages like:

errorHandler("syntax error: Got '%c', was expecting an operator.", s);

Basically, anything that makes it convenient and easy to give more
specific feedback.
Do you mean my use of Hungarian here?

There are two kinds of Hungarian. The kind that is actually in some way
beneficial, which denotes abstract types, and the kind which denotes compiler
types and is demonstrably harmful. You used the latter kind.
This is not my experience, especially with modern editors. It doesn't
cause bugs unless it is not maintained. What part of strong typing
don't you understand?

I understand strong typing just fine. That's why systems hungarian is stupid;
it's not actually adding any data.

Apps Hungarian would be to, say, indicate whether something is a distance
or an index or whatever -- all things which could be stored in an int,
but which are not interchangeable sorts. Systems Hungarian is useless,
because it just replicates stuff the compiler can already check.

Interestingly, Simonyi has come out pretty strongly against the Systems
Hungarian thing -- and given that he's the originator of Hungarian notation,
I thin kthat's pretty damning.
Because string.h is fucking fucked.

No, it isn't.
I don't choose to include libraries unnecessarily when I can write a
little code for the limited amount of functionality that I need.

When the library is part of the core language, that attitude is stupid.
You can't outperform the library writers, and every line of code you
spend reinventing the wheel is wasted.
In your view. In my view, the "library" approach of C is horseshit
because you get a Lot Of Useless Crap for one little function that you
need.

Maybe, except *you already got it*. You've already paid the cost, might as
well use the stuff.
No, -1 is the truest true value.

It may be, but it's also used widely as an out-of-band error indicator.
My understanding (let me know if it's
changed since 1991), zero is falseness whereas nonzero is truthiness.
Well, -1, on twos-complement systems, which despite your nonsense in
C: The Complete Nonsense are dominant, is the number least like zero
since it's all ones and isn't that a kiss my ass?

Actually, it's not, because no one cares about the bit representation; we
just care whether the number it represents communicates clearly to the
user.
Making sure that the only string I allocate and append to, the Polish
string, is on my to do. I was worried about screwing that up, but I
malloc'd 100 bytes for the Polish string, and none of my test cases
approach that length.

Which is to say, it does indeed turn out that you got it wrong.

This is the other reason to use the library -- the library functions
handle their boundaries correctly, in general.
So it's ridiculous to give a humane error message? Explain.

It's not a useful message in context.
Study the code a little more thoroughly. While this particular test
may have changed in my Nov 3 version, it was necessary in this version
because mulFactor in all versions must needs incorporate the functions
of a scanner (including testing end of input). If input has been
exhausted, we have entered mulFactor expecting a multiply factor and
there is none.

But the user doesn't care about "mulFactor". The user wants to know
"we reached the end of the string while expecting more input". The internal
details like "mulFactor" are not part of the user's knowledge of what
the program is doing, and shouldn't have to be.
Yes, I said it looks ahead.
If it didn't it would be dead.

Looking ahead like that, though, means that that function has to handle
all sorts of hypothetical future special cases -- which is silly. Just
have the parser recurse and tell you how far it got.
At that point, I factor. Premature factorization especially for you
bums is in my experience a waste of time.

I'm a big fan of handling at least the common cases up front.
It's not necessarily ugly to "read ahead": cf the 2nd ed. of the
Dragon Book, p 78. Also, see Nilges' "Build Your Own Goddamn .Net
Language and Goddamn Compiler" for a discussion of the need for
lookahead in processing unary minus and right parentheses. I worked
through these issues several years ago in VB, and if you care to
comment on my approaches, buy my book. Of course, if you do a hatchet
job on the book, I'll be on your case like a fly on shit...save where
you are right in any important way, in which case I will help you
write your critique and get your errata into Apress' Web site.

You need some lookahead, but a single token of lookahead should do for
most of the stuff we care about. Scanning through the string of characters
is a bad way to do lookahead.
Point taken. I was suspicious of the code myself since I have
encountered that problem before. It's an artifact of the unsafe design
of the Infantile Disorder in which I am coding.

Except it's not. It's easy to get right, and thousands of people do.
You just have to be aware of it.
This should be:
        strPolish[0] = '\0';
        return strPolish;
Excellent. You should turn pro.
:)

Don't be a silly bastard. It's not a memory leak since I return to main
() (I was tempted to return void just to piss you off but Microsoft C
sets me up with int main()). Now you're making silly comments just to
pad your anti-resume. Shape up.

There is a historical quirk, likely no longer relevant: On some DOS/Windows
implementations, long ago, failing to free malloc'd memory before exiting
resulted in the memory being lost until the next reboot.
But thanks for your observations. Not as good as Bacarisse but at
least you jumped in and got to work, unlike your friend Heathfield,
who's trashed so many people that he's afraid to make a mistake.

Heathfield is not afraid to make mistakes, he just doesn't very often.
He was making a point -- which is that if you want people reviewing code,
running it through a picky compiler is a great starting point.
Furthermore, thanks to your help and my own coding and testing, I am
ramping back up quickly in C and shall shortly, if I persist, run
rings around you.

Good luck with that.
Nonetheless I shall persist for now, in order to demonstrate that two
propositions are true. One is that I'm smarter than you.

I doubt it. It's not theoretically impossible, but it would certainly
surprise me.
The other is
that we can work together to find bugs in each others' code because
nobody is too smart to make stupid mistakes, a lesson which if you
learn well will, I hope, cause you to withdraw The Vicious Tirade.

Not really. People do, indeed, make stupid mistakes. The question is
whether they then try to correct them...

-s
 
K

Keith Thompson

Seebs said:
Uh, well, no.


The standard never had this problem. Individual implementors have chosen
different ways of representing dates; it's up to them to decide which
representation they want. POSIX does specify a representation in seconds
since Jan 1 1970 UTC, but does not specify a particular limit on the size
of the object used to store that value.

All correct.

On the other hand, if I understand the history correctly, the first
implementations to provide time_t defined it as a signed 32-bit
integer type measuring seconds since 1970-01-01. The standard
came along later and established looser requirements that were
consistent with the existing implementations, but also allowed for
other representations (such as using a 64-bit integer, choosing an
epoch other than 1970-01-01, choosing a resolution other than one
second, and so forth). The POSIX requirements are tighter than
the ISO C requirements, but they still allow for 64-bit integers.
(And I suspect there were a few 64-bit time_t implementations before
either standard came along.)

The standards didn't fix the problem, but they certainly allowed
for it to be fixed.
 
C

Chris McDonald

Date precision. Ever wonder why spam is dated 2038? Did the standards
fix this problem?


You've missed the point (again); answered in other people's replies.

Standards permit those evil blooksucking compiler and library
developers to avoid the problem.
 
S

spinoza1111

Be interesting to know how it "enables optimization".

Bone up on compiler optimization and tail recursion. I'm not gonna
explain it to you. Do you own Sethi Aho et al 2nd ed.?
Simply untrue -- there's a ton of systems out there which maintain the
distinction clearly.  Again, if you're posting code that might some day
be used or tried by other people, doing things right matters even if it
doesn't have a discernable effect on your system.  There is a difference
there, even if it doesn't affect your personal desktop.

Don't even presume to lecture me, kiddo. Your consideration for others
is on display in your treatment of Schildt.
Blank lines used for emphasis are useful, blank lines which flood the display
with blank lines just disrupt the reader's flow.

You have a disturbing tendency to lapse into sloppy English and
corporatese whenever you want to stop thinking, and when this harms
other people, it needs to stop. What on earth is "the reader's flow?"
Menstrual?
I don't see the worth of this at this time, but I may be missing
something.

Consider the option of writing messages like:

  errorHandler("syntax error: Got '%c', was expecting an operator.", s);

Basically, anything that makes it convenient and easy to give more
specific feedback.


Haven't you run the latest edition? It does this visually on any
monospace window by putting a dollar sign under the point at which the
error is discovered...although now that I think of it, it's probably a
mistake on my part to assume monospace output.

I don't think, however, that it makes sense to overengineer this
issue, in part because what rilly needs change is the fact that
recursive descent implemented simply produces too many "nested" error
messages and is bad at error recovery.
There are two kinds of Hungarian.  The kind that is actually in some way
beneficial, which denotes abstract types, and the kind which denotes compiler
types and is demonstrably harmful.  You used the latter kind.


I understand strong typing just fine.  That's why systems hungarian is stupid;
it's not actually adding any data.

No, it's organizing material for easy retrieval in a modern editor
with intellisense.

Apps Hungarian would be to, say, indicate whether something is a distance
or an index or whatever -- all things which could be stored in an int,
but which are not interchangeable sorts.  Systems Hungarian is useless,
because it just replicates stuff the compiler can already check.

Interestingly, Simonyi has come out pretty strongly against the Systems
Hungarian thing -- and given that he's the originator of Hungarian notation,
I thin kthat's pretty damning.

He's not the originator. "Systems Hungarian" was already in use in IBM
when he was still in Hungary helping to destroy socialism as a punk
kid who needed a kick in the ass. It is in fact mentioned in a book by
Richard Diebold published in 1962.
No, it isn't.


When the library is part of the core language, that attitude is stupid.
You can't outperform the library writers, and every line of code you
spend reinventing the wheel is wasted.

Actually, for trivial algorithms, I can.
Maybe, except *you already got it*.  You've already paid the cost, might as
well use the stuff.

I didn't pay a dime for Microsoft C++ Express.
It may be, but it's also used widely as an out-of-band error indicator.

Yes. The confusion is here created not by me, however, but by C's lack
of a boolean type.
Actually, it's not, because no one cares about the bit representation; we
just care whether the number it represents communicates clearly to the
user.

This is childish. "I care about all sorts of useless shit like what
main() returns but not about interpersonal decency, nor elegance I
didn't invent". You see, C lacks Boolean values, and -1 is more
visible than 1: more readable: more elegant, and, in a twos complement
system, it uses the literary technique of "evocation", for it evokes
in the intelligent code reader a vision of all ones (and it's more
visible at what we used to call core dump time, and what is now The
Time of Blue Screen of Death). Useful beauty. In your comments

Nonsense prevails, modesty fails: all this useless beauty (Elvis
Costello)
Which is to say, it does indeed turn out that you got it wrong.

Not in any substantive way. My goal was to get something coded and see
how you behave in a structured walkthrough where owing to the written
nature of the medium, we can exclude noncontributing thugs like
Heathfield. Right now, I am not impressed, but I think you have
potential that Heathfield lacks.

This is the other reason to use the library -- the library functions
handle their boundaries correctly, in general.


It's not a useful message in context.

Words, my lord: words words words. But that's not the problem. "In
context" is meaningless corporatese.
But the user doesn't care about "mulFactor".  The user wants to know

The "user" (sigh). Sloppy English: because in a structured walkthrough
users have no place, no more than managers. You invoke "the user" as a
deus ex machina: a Lacanian phallus. But literally, that's the person
who as you say needs to be innocent of the details!
"we reached the end of the string while expecting more input".  The internal
details like "mulFactor" are not part of the user's knowledge of what

If you'd learn how to write properly, which you can't, you'd here
express this as an assertion which should always be true. My program
satisfies that assertion. Rather than quarreling about whether some
"user" (some abstract thug with money and a loud mouth) can see it, I
need to use informal or formal argumentation to prove that "there is
no input, that is not completely examined by my code, such that each
byte is scanned" (X strong) or "there is no valid input where this is
untrue" (weak X: implied by strong X).

I will provide a short informal argument to this effect in comments, a
fix to the library case problem, a new malloc scheme that will avoid
the probable bug you found, and detabbed properly formatted source by
Tue eve China time. I believe these are the only real problems you
found (that weren't corrected in the latest version I posted), and
once again as in the case of Schildt you have a disturbing tendency to
pad your attacks with opinion and trivia.
the program is doing, and shouldn't have to be.


Looking ahead like that, though, means that that function has to handle
all sorts of hypothetical future special cases -- which is silly.  Just
have the parser recurse and tell you how far it got.

Nonsense. It looks ahead for one reason alone. Again, on the related
issue of one-character lookahead cf Aho/Sethi et al. 2nd ed. p 78.
Drop the issue, you're just making a big deal out of it to show off.
I'm a big fan of handling at least the common cases up front.


You need some lookahead, but a single token of lookahead should do for
most of the stuff we care about.  Scanning through the string of characters
is a bad way to do lookahead.

Says who? I refer you to Nilges 2004. He recommends it.

Seriously, saying dully "ooo dat is a bad way to do wookahead" doesn't
make what you say true. Stick to what you're good at, which strangely
is C, not programming.
Point taken. I was suspicious of the code myself since I have
encountered that problem before. It's an artifact of the unsafe design
of the Infantile Disorder in which I am coding.

Except it's not.  It's easy to get right, and thousands of people do.
You just have to be aware of it.
This should be:
        strPolish[0] = '\0';
        return strPolish;
Excellent. You should turn pro.
:)

Don't be a silly bastard. It's not a memory leak since I return to main
() (I was tempted to return void just to piss you off but Microsoft C
sets me up with int main()). Now you're making silly comments just to
pad your anti-resume. Shape up.

There is a historical quirk, likely no longer relevant:  On some DOS/Windows
implementations, long ago, failing to free malloc'd memory before exiting
resulted in the memory being lost until the next reboot.

Fascinating. But useless.
Heathfield is not afraid to make mistakes, he just doesn't very often.

That's because he doesn't code. He in fact here emulates the very
worst sort of manager who sits back and destroys people in meetings
for taking risks, proposing solutions, and coding. He makes me sick,
and I want him out of here.
He was making a point -- which is that if you want people reviewing code,
running it through a picky compiler is a great starting point.


Good luck with that.


I doubt it.  It's not theoretically impossible, but it would certainly
surprise me.


Not really.  People do, indeed, make stupid mistakes.  The question is
whether they then try to correct them...

I don't know what you mean. Where I agree it's a stupid mistake, I
don't "try" to correct it, I just correct it. Your corporatese on the
other hand implies that the person being objectified by the language
will recognize something with the ugly name of a "behavior pattern"
which they will then, in the debased language of Human Resources, "try
to correct", where the expectation, of course, is that he or she
(having been found wanting in a secret Calvinism: a society haunted by
predestination) will fail but "we" will have done our best.

I am here, however, for your insights on code, not for any wisdom I
see in you.
 
S

spinoza1111

In

spinoza1111wrote:

<polite stuff reluctantly snipped despite its rarity value>

It's rare because when people make genuine technical remarks I respond
professionally.

Few genuine technical remarks are made here. Ben Bacarisse is by far
the best source of solid technical feedback. Seebach is just barely
acceptable since unlike Ben he doesn't organize his thoughts well and
proceeds sequentially just identifying nits. You're not even in the
running and you need to leave this discussion.
 

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,207
Latest member
HelenaCani

Latest Threads

Top