There were other problems.
Itemise them. NOW. Otherwise you're again making a small number of
errors into a full scale trashing as you did with Schildt.
Release 4 of the infix2Polish conversion program is attached to this
reply. All of your concerns, including the small H issue, have been
addressed, and you have been credited in the Change Record. From now
on, I want you to economically report problems as they arise or
contribute your own code to this discussion. When I want anything
more, I'll beat it out of you.
This really isn't a power/generality question. It's a design tradeoff,
and different companies have made different choices.
Man, you just blew out another milspec irony meter. That quote is awesome
coming from someone who uses "As I have said" as a way to introduce claims
for which he's never presented any kind of support other than his own
assertions.
If you by your own repetition force me to repeat then yes indeed, your
own reputation is being damaged by this online discussion. But please
note that you are the aggressor as you were with Herb. He chose not to
respond. I choose to, and in so doing I repeat what you've told me
about your learning disorder and the fact that you don't seem to have
either academic qualifications or real programming experience.
If you do not like this, then confine yourself in the future to actual
technical points.
Here is version 4 of infix2Polish.
// ***************************************************************
// * *
// * infix2PolishC Infix to Polish notation using a grammar *
// * *
// * *
// * This application converts infix to Polish notation using a *
// * simple grammar. *
// * *
// * *
// * 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 *
// * *
// * 11 04 09 Nilges Version 3 *
// * 1. Predetermine malloc using *
// * infix length times two *
// * 2. Detab code for posting *
// * 3. Free polish expression after *
// * displaying it in testcase() *
// * as noticed by Seebs and *
// * recommended by Schildt *
// * 4. Display purpose of code on *
// * entry *
// * 5. Option to specify malloc *
// * request on command line for *
// * Polish expression (primarily *
// * to test storage usage) *
// * *
// * 11 06 09 Nilges Version 4 *
// * Seebs 1. Fix upper case in #include *
// * 2. Comment corrections *
// * 3. Bug: intMaxPolishLength not *
// * assigned when malloc specified*
// * on command line *
// * 4. Renamed string2UnsignedInt to *
// * string2Int *
// * 5. Use macros to better format *
// * about info *
// * 6. Command line malloc is now a *
// * maximum request allowable *
// * 7. Bug: invalid malloc request *
// * caused zero to be used without*
// * error indication. *
// * 8. Changed str2Int to return err *
// * when nonnumeric characters *
// * appear *
// * *
// * I S S U E S ----------------------------------------------- *
// * DATE POSTER DESCRIPTION AND RESOLUTION *
// * -------- --------- --------------------------------- *
// * Nilges Version 5 plan *
// * Seebach 1. Random expressions *
// * Gene 2. Alternative versions from *
// * Anon Seebach, Gene, anon *
// * 3. Add timing facilities *
// * 4. String handling centralized *
// * 5. Display command line syntax *
// * 6. Command line options *
// * 6.1 /T terse output *
// * 6.2 /? display help info: *
// * exit *
// * 6.3 /S <seed> seed the random*
// * # generator *
// * 6.4 /M <max> define max *
// * malloc request *
// * 7. Prescan the infix expression *
// * *
// ***************************************************************
#include <stdio.h> // May help Heathfield
#include <stdlib.h>
// ***** Macros **************************************************
// --- Pass over white space
#define SKIP_WHITE_SPACE(s, i, e) \
{ for(; (i) <= (e) && (s)[(i)] == ' '; (i)++ ); }
// --- Return maximum value
#define MAX(x, y) ((x) > (y) ? (x) : (y))
// --- Return minimum value
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define SHOW_ABOUT_INFO \
{ \
printf("This application converts infix to Polish "); \
printf("notation using a simple grammar-based approach. "); \
printf("Its command line syntax is: infix2PolishC "); \
printf("[ mallocMax ]"); \
}
// ***** Function index ******************************************
#define ADDFACTOR \
int addFactor(char *strInfix, \
char *strPolish, \
int *intPtrIndex, \
int intEnd, \
int intMaxPolishLength)
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, \
int intMaxPolishLength)
EXPRESSION;
#define FINDCHARS \
int findChars(char *strInstring, \
char *strFind, \
int intStartIndex)
FINDCHARS;
#define INFIX2POLISH \
int infix2Polish(char *strInfix, \
char *strPolish, \
int intMaxPolishLength)
INFIX2POLISH;
#define MAIN \
int main(int intArgCount, \
char *strArgs[])
MAIN;
#define MULFACTOR \
int mulFactor(char *strInfix, \
char *strPolish, \
int *intPtrIndex, \
int intEnd, \
int intMaxPolishLength)
MULFACTOR;
#define STRING2INT \
int string2Int(char *strInstring)
STRING2INT;
#define STRINGAPPENDCHAR \
int stringAppendChar(char *strString, \
char chrNew, \
int intMaxLength, \
int intSpaceBefore)
STRINGAPPENDCHAR;
#define STRINGLENGTH \
int stringLength(char *strInstring)
STRINGLENGTH;
#define TESTCASE \
void testCase(char *strInfix, \
char *strExpected, \
int intMallocMax)
TESTCASE;
#define TESTER \
void tester(int intMallocMax)
TESTER;
// ***** Functions ***********************************************
// ---------------------------------------------------------------
// Command line handler
//
// int main(int intArgCount, char **strArgs)
//
MAIN
{
int intMallocMax = -1;
SHOW_ABOUT_INFO;
if (intArgCount > 1)
if ((intMallocMax = string2Int(strArgs[1])) < 0)
{
printf("%sInvalid malloc request %s\n", intMallocMax);
return;
}
tester(intMallocMax);
printf("\n\nTesting complete: check output for correctness");
return;
}
// ---------------------------------------------------------------
// Parse add factor
//
// int addFactor(char *strInfix,
// char *strPolish,
// int *intPtrIndex,
// int intEnd,
// int intMaxPolishLength)
//
// addFactor = mulFactor [ *|/ mulFactor ]
//
ADDFACTOR
{
char chrMulOp = ' ';
int intStartIndex = 0;
if (!mulFactor(strInfix,
strPolish,
intPtrIndex,
intEnd,
intMaxPolishLength))
{
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,
intMaxPolishLength))
return errorHandlerSyntax
(*intPtrIndex,
"Mul/div op not followed by mulFactor",
strInfix);
if (!stringAppendChar(strPolish,
chrMulOp,
intMaxPolishLength,
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,
// int intMaxPolishLength)
//
EXPRESSION
{ /* expression = addFactor [ +|- addFactor ] */
char chrAddOp = ' ';
int intStartIndex = 0;
if (!addFactor(strInfix,
strPolish,
intPtrIndex,
intEnd,
intMaxPolishLength))
{
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,
intMaxPolishLength))
return errorHandlerSyntax
(*intPtrIndex,
"Add/sub op not followed by addFactor",
strInfix);
stringAppendChar(strPolish,
chrAddOp,
intMaxPolishLength,
1);
}
return -1;
}
// ---------------------------------------------------------------
// Find one of a set of alternative characters
//
// int findChars(char *strInstring,
// char *strFind,
// int intStartIndex)
//
FINDCHARS
{
int intIndex1 = intStartIndex;
int intIndex2 = 0;
for (; strInstring[intIndex1] != '\0'; intIndex1++)
for (intIndex2 = 0;
strFind[intIndex2] != '\0';
intIndex2++)
if (strInstring[intIndex1] == strFind[intIndex2])
return intIndex1;
return intIndex1;
}
// ---------------------------------------------------------------
// Convert infix to Polish
//
// int infix2Polish(char *strInfix,
// char *strPolish,
// int intMaxPolishLength)
//
INFIX2POLISH
{
int intIndex = 0;
int intLength = stringLength(strInfix);
strPolish[0] = '\0';
if (!expression(strInfix,
strPolish,
&intIndex,
intLength - 1,
intMaxPolishLength))
{
errorHandler("Error");
return 0;
}
return -1;
}
// ---------------------------------------------------------------
// Parse multiplication factor
//
// int mulFactor(char *strInfix,
// char *strPolish,
// int *intPtrIndex,
// int intEnd,
// int intMaxPolishLength)
//
// 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,
intMaxPolishLength,
1);
}
intIndexStart = *intPtrIndex;
intSpaceBefore = -1;
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;
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,
intMaxPolishLength))
return errorHandlerSyntax
(intInner,
"Expression doesn't appear in parentheses",
strInfix);
return -1;
}
return 0;
}
// ---------------------------------------------------------------
// Convert string to an unsigned integer
//
// int string2Int(char *strInstring)
//
//
STRING2INT
{
int intIndex1 = 0;
int intValue = 0;
for (; strInstring[intIndex1] != '\0'; intIndex1++)
{
if (strInstring[intIndex1] < '0'
||
strInstring[intIndex1] > '9') return -1;
intValue = intValue * 10
+
strInstring[intIndex1] - (int)'0';
}
return intValue;
}
// ---------------------------------------------------------------
// Append character to string
//
// int stringAppendChar(char *strInstring,
// char chrNew,
// int intMaxLength,
// int intSpaceBefore)
//
STRINGAPPENDCHAR
{
int intLength = stringLength(strString);
int intSpaceBeforeInEffect =
intSpaceBefore
&&
intLength > 0
&&
strString[intLength - 1] != ' ';
if (intLength
intMaxLength - (intSpaceBeforeInEffect ? 2 : 1))
{
errorHandler
("Cannot append character(s): insufficient storage");
return 0;
}
if (intSpaceBeforeInEffect)
{
strString[intLength++] = ' ';
}
strString[intLength] = chrNew;
strString[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,
// int intMallocMax)
//
TESTCASE
{
char *strPolish;
int intMaxPolishLength = stringLength(strInfix) << 1;
int intReq = MAX(intMaxPolishLength + 1, 10);
if (intMallocMax >= 0)
{
intReq = MIN(intMallocMax, intReq);
intMaxPolishLength = intReq - 1;
}
printf("\n\nConverting \"%s\": expect \"%s\"",
strInfix,
strExpected);
strPolish = (char *)malloc(intReq);
if (strPolish == 0)
errorHandler("Can't get storage");
printf("\n\"%s\"\n",
(infix2Polish(strInfix,
strPolish,
intMaxPolishLength)
?
strPolish
:
"Conversion failed"));
free(strPolish); // cf. Schildt, C: the Complete Reference
}
// ---------------------------------------------------------------
// Tester
//
// void tester()
//
TESTER
{
testCase("1", "1", intMallocMax);
testCase("1+1", "1 1 +", intMallocMax);
testCase("(10+613)*a", "10 613 + a *", intMallocMax);
testCase(")", "Error", intMallocMax);
testCase("1)", "Error", intMallocMax);
testCase("(((1))))", "Error", intMallocMax);
testCase("10 113 + a *", "Error", intMallocMax);
testCase("(10 + 113) * a", "10 113 + a *", intMallocMax);
testCase(" ( 10 + 113 ) * a ", "10 113 + a *", intMallocMax);
testCase("(", "Error", intMallocMax);
testCase("((((2", "Error", intMallocMax);
testCase("////2", "Error", intMallocMax);
testCase("", "Error", intMallocMax);
testCase("()", "Error", intMallocMax);
testCase("(((5))", "Error", intMallocMax);
testCase("(((5)))", "5", intMallocMax);
testCase("((5))", "5", intMallocMax);
testCase("5", "5", intMallocMax);
testCase("((10+(113-(2+((((((2/(4+3)))))))+2+2))))*a", "10 113 2 2
4 3 + / + 2 + 2 + - + a *", intMallocMax);
testCase("a", "a", intMallocMax);
testCase(" a + b ", "a b +", intMallocMax);
testCase(" a + b ", "Malloc bound failure", 5);
}