How to convert Infix notation to postfix notation

S

Seebs

// parser for gramar:
// expr -> term { [+-] term }
// term -> factor { [*/] factor }
Again it looks like you stole this,

No it doesn't. There are multiple differences precisely because he's
expressing it in a wildly different way.
and again I forgive you, or ask
your forgiveness if I have accused you falsely. If you swiped it from
my grammar, you forgot to put an asterisk after the right curley
braces to indicate that there can be zero, one or more occurences of
the term or factor, preceded by its binary operator.

He didn't forget anything of the sort. He's using {} for optional
things, because he's using [] for character classes.
If you did not swipe it, then you may be using curley braces to
indicate zero one or more repetitions of the braced content; but this
would be your unique idiom, I've never seen it.

It's not particularly unique.
Also, the standard meaning of square brackets is that the bracketed
material is optional: but the binary operators you have bracketed are
most assuredly not optional as I think you know.

It's a Unixy idiom (now POSIXy) that [ab] means "either a or b" when referring
to individual characters. Found in both shell patterns/globs and regular
expressions.

I don't think anyone stole the notion of an expression being one or more
additive expressions separated by plus/minus signs, and an additive
expression being one or more multiplicitive expressions separated by
times and divide symbols.

-s
 
K

Kenny McCormack

If you're amazed by something, that's often a sign that you have a faulty
premise.

Hint: There is no "high table". I don't recognize peoples' names very
much, and I don't much care who's who.

As such, by your own admission, your remarks don't count for much.

You can't really follow the action unless/until you can remember the
players's names (i.e., keep track of the characters).
 
K

Kenny McCormack

... Wow, you're really committed to this idea that your social instincts
are the way everyone else in the world works, exactly.

Blah, blah, blah. Same old, same old...

Note: I wasn't talking about you at all here. This was actually history
prior to your arrival here, and involved other characters (Kiki & RH).

You seem to have a propensity for latching onto things that I say and
assuming that I'm talking about you. Not that I don't ever talk about
you, but not as often as you seem to think.
 
S

Seebs

As such, by your own admission, your remarks don't count for much.

Except of course they do... Because your central claim is that all us
"regs" are obsessed with status and persons.

So if we're not, you've lost on the merits.

In short, if I'm not qualified as a witness to testify to the falseness of
your claims, my lack of qualification is proof of the falseness of your
claims. Either way, you're wrong. The clique is your social instincts
misfiring in a textual medium, not a thing with external reality. Please
contact Rene Descartes and seek a full refund.

-s
 
S

Seebs

Note: I wasn't talking about you at all here. This was actually history
prior to your arrival here, and involved other characters (Kiki & RH).

Oh, of course! But you've not demonstrated that your hallucinations of
social realities are conected to the external world.
You seem to have a propensity for latching onto things that I say and
assuming that I'm talking about you. Not that I don't ever talk about
you, but not as often as you seem to think.

If there's "regulars" in comp.lang.c, I must be one of them, because I've
been around forever and people tend to listen to me, because I know C.

-s
 
K

Kenny McCormack

Except of course they do... Because your central claim is that all us
"regs" are obsessed with status and persons.

Except I never said any such thing.

(Rest of post snipped: the usual blah, blah, blah from Seebs)
 
S

Seebs

Except I never said any such thing.

Ahh, but you did. You have said that it's all really about status. To
everyone. That this is the "real world", etcetera.

If it's not, you're wrong.

-s
 
T

Tim Streater

Seebs said:
Oh, of course! But you've not demonstrated that your hallucinations of
social realities are conected to the external world.


If there's "regulars" in comp.lang.c, I must be one of them, because I've
been around forever and people tend to listen to me, because I know C.

I'm not only not, but have no interest in being one. I'm just here for
the beer. Spinny infested the PHP or as it might be JavaScript NG a
couple of years or so ago, and he indulged in the same name-calling,
bullying tactics, and soviet logic then as you see here. I recall
counting at one point (somehow) and finding we'd got to 800 posts or so
before he wandered off.

In any case I'd be unlikely to be "accepted" as what Mr McCormack refers
to as a "regular" as I haven't used C to any extent for 20 years and so
am in little position to comment on any C specifics.
 
T

Tim Streater

You were classed as a "reg wannabee". Sit up straight in your chair,
and pay attention!

Which part of "have no interest in being one" do you not understand?
 
K

Kenny McCormack

Tim Streater said:
I'm not only not, but have no interest in being one. I'm just here for
the beer. Spinny infested the PHP or as it might be JavaScript NG a
couple of years or so ago, and he indulged in the same name-calling,
bullying tactics, and soviet logic then as you see here. I recall
counting at one point (somehow) and finding we'd got to 800 posts or so
before he wandered off.

You were classed as a "reg wannabee". Sit up straight in your chair,
and pay attention!
In any case I'd be unlikely to be "accepted" as what Mr McCormack refers
to as a "regular" as I haven't used C to any extent for 20 years and so
am in little position to comment on any C specifics.

C skills are irrelevant. It's the ability to bully and name-call, and,
above all, as they used to say 300 or so years ago, Keep The Faith!
 
S

Seebs

Which suggests you are emotionally dead.

Or possibly just not obsessed with status and cliques to such an extent
that I invent them even when they don't exist?
It's as plane as that chip on
your shoulder that the "reg" high table exists.

Or, alternatively, that your social instincts aren't 100% reliable.
If YOU can not read the
order in the chaos then you need to take a break.

I can read order in chaos just fine -- quite well, even. What's even more
impressive, though, is that I can also recognize that sometimes my brain
guesses at a pattern and it turns out to be wrong, so I actually check
the results I get handed instead of treating every instinctive evaluation
as Revealed Truth. Works great.

-s
 
S

Seebs

Which part of "have no interest in being one" do you not understand?

I've argued with guys like this before. They genuinely can't accept
that other people are not solely driven by desire for high status. It's
incomprehensible to them. It's like trying to explain "conservation
of shared resources" to a spammer.

-s
 
S

Seebs

Obsessed? You worry to much. It's not at all an obsession. It's a mere
mention and amused study at times.

Really? 'cuz I've seen a ton of posts from you that talk about the topic,
and very few that don't seem related to it.
'Fraid they're pretty well tuned old son.

Pretty well tuned is not the same thing as 100% reliable. In particular,
if you have normally functional, or even fairly good, social instincts for
face-to-face communications, the usual state is that you're going to be
noticably less good at pure-text media -- and yet that you're going to *feel*
just as confident.
Good. Then off you go. There's a lot of history in c.l.c to help you
re-evaluate.

I've rechecked it a couple of times, and you're still imposing a social
interpretation that does not appear to model any external reality.

The mere fact that you're dismissive and confident but have not presented
concrete evidence supports my conclusion, thus far.

-s
 
S

Seebs

1) No one said "all other people"

You don't have to say it. When you have repeatedly evaluated other
people as acting a given way despite clear evidence to the contrary, and
have never been seen to evaluate people as acting differently, that's
pretty solid.
2) No one said "solely by status"

Yeah, but if it's your one-size-fits-all model of everything, it might
as well be -- especially when you apply it to people for whom status
is not a meaningful word.
All in all an pretty epic FAIL since you are assuming things of others
which have no basis in reality in order to deliver your not so killer
judgements.

Boy, you sure are mad about that. You continue to talk about this
exclusive clique and use a lot of emotionally-laden words that clearly
communicate jealousy, but you never, ever, provide any kind of specific
evidence supporting your claim -- you just handwave it to obviousness.
That's what we call an *instinct* -- and social instincts on plain text
are worth less than the paper they're printed on.

When you can make an actual argument, go ahead.
You are however clearly in love with yourself and so are very well
qualified for a seat at the reg high table.

And again, you interpret my behavior according to your instincts, not mine.

-s
 
K

Kenny McCormack

Which part of "have no interest in being one" do you not understand?

What part of "I don't believe you", aka, "I hear you calling, but you
can't come in", aka (and less charitably), "you're lying".

The regs (and the wannabees of various stripes) lie all the time.
It is so amusing to watch.
 
B

Ben Bacarisse

spinoza1111 said:
This post contains the promised C code version of the infix to Polish
notation convertor.

Seebs as commented on the code in detail, so I'll just add that you
need more work on some error cases. Despite a lot of unnecessary
counting of parentheses, cases like "1)" and "(((0))))" are silently
ignored.

Also, I think it would be better to try to detect all input that can't
be converted. For example, "&" gives an error, but "1&2" does not.

In order to be positive, I'll stick my neck out and post my solution.
No one has posted the classic operator priority parsing algorithm, so
this solution is new in the thread. The code is simpler than the code
you get from turning grammar rules directly into paring functions,
although the benefit is certainly borderline for expressions with only
two priorities. I've added an extra, high priority, operator (^) to
illustrate the algorithm's generality.

All the work heavy is done in one function (convert_operators in the
code below) that parses sequences of terms whose length is determined
by the priority of the operators that are seen. If these are
determined from a run-time table, you get the advantage of being able
to add and remove operators as well as changing the operator
precedences as the parser runs.

Most of the code is scaffolding and includes an expanding character
buffer to hold the growing output string. C99 features are used in a
couple of places.

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/*
* This type, and the two str_ functions, provide an expanding
* character buffer to take the growing output string.
*/

typedef struct string string;

void str_add(string *s, char c);
const char *str_string(string *s);

static bool convert_term(const char **s, string *out);
static bool convert_operators(const char **s, int precedence, string *out);
static bool convert_expression(const char **s, string *out);

static char next(const char **s);
static bool expect(const char **s, char c);
static bool missing(const char *what, char where);


/*
* The grammar is largely specified by this function that determines
* if a token (in this case a single character) is an operator and,
* if so, what precedence it has.
*/

static int precedence_of(char op)
{
static const char *op_table[] = { "+-", "*/", "^", NULL };
if (op != '\0')
for (int i = 0; op_table; i++)
if (strchr(op_table, op))
return i;
return -1; /* not a operator */
}

bool infix_to_postfix(const char *s, string *out)
{
return convert_expression(&s, out) && expect(&s, '\0');
}

static bool convert_expression(const char **s, string *out)
{
return convert_term(s, out) && convert_operators(s, 0, out);
}

static bool convert_operators(const char **s, int precedence, string *out)
{
char op;
int prec, right_prec;
while ((prec = precedence_of(op = next(s))) >= precedence) {
*s += 1;
if (convert_term(s, out))
while ((right_prec = precedence_of(next(s))) > prec) {
if (!convert_operators(s, right_prec, out))
return false;
}
else return false;
str_add(out, op);
str_add(out, ' ');
}
return true;
}

static bool convert_term(const char **s, string *out)
{
unsigned char c = next(s);
if (isalpha(c)) {
str_add(out, c);
str_add(out, ' ');
*s += 1;
return true;
}
else if (isdigit(c)) {
while (isdigit((unsigned char)**s))
str_add(out, *(*s)++);
str_add(out, ' ');
return true;
}
else if (c == '(') {
*s += 1;
return convert_expression(s, out) && expect(s, ')');
}
else return missing("Term", c);
}

static char next(const char **s)
{
while (isspace((unsigned char)**s)) *s += 1;
return **s;
}

static bool missing(const char *what, char where)
{
fprintf(stderr, "%s expected where %s found.\n", what,
where ? (char []){where, 0} : "end of input");
return false;
}

static bool expect(const char **s, char c)
{
if (next(s) != c)
return missing(c ? (char []){c, 0} : "end of input", **s);
*s += 1;
return true;
}


/*
* An implementation of an expanding character buffer.
*/

struct string {
size_t capacity, size;
char *string;
};

void str_add(string *s, char c)
{
if (s->size >= s->capacity) {
size_t new_cap = s->capacity * 3 / 2 + 8;
char *new_s = realloc(s->string, new_cap);
if (!new_s) {
fprintf(stderr, "String add: out of memory\n");
exit(EXIT_FAILURE);
}
s->string = new_s;
s->capacity = new_cap;
}
s->string[s->size++] = c;
}

const char *str_string(string *s)
{
str_add(s, '\0');
return s->string;
}


int main(int argc, char *argv[])
{
bool result = true;
while (--argc > 0) {
string postfix = {0};
if (infix_to_postfix(*++argv, &postfix))
printf("%s\n", str_string(&postfix));
else result = false;
free(postfix.string);
}
return result ? EXIT_SUCCESS : EXIT_FAILURE;
}
 
S

Seebs

What part of "I don't believe you", aka, "I hear you calling, but you
can't come in", aka (and less charitably), "you're lying".

Of course this is your first theory. Hmm.
The regs (and the wannabees of various stripes) lie all the time.

As a general rule, your view of other people is informed primarily
by your experience of yourself.

Most people don't lie very often. The exceptions, though, have the
interesting trait that they think everyone else does it too -- especially
people they dislike.

Now, you might conclude that, since I've concluded that you're a liar,
I'm one of the people who assumes that people he dislikes are liars, but
this is not so. I don't like Jacob very much, but I don't have
any reason to believe him to be a liar. There are also some liars I like,
although not many.

Again: You are not the only human ever to exist. Other humans not only
exist, but are different from you.

-s
 
S

Seebs

typedef struct string string;

I don't like the name "string" for this. The term "string" is pretty
well defined in C, and I think this has real potential to confuse
readers in a larger program.
void str_add(string *s, char c);

It seems like you might want to support adding strings, not just
characters. I think I'd have gone for

str_append(string *s, char *fmt, ...)

.... and yes, between this and a couple of my other posts, you could reasonably
infer that my first pass at implementing a fibbonacci generator in C
would look like "int fib(int n, char *fmt, ...)".

(I exaggerate, very slightly, for humorous effect.)

And again, I don't like "str" here because (although you avoided the
implementation namespace), it still seems to me that "str*" carries the
implication that it operates on a null-terminated-char-*.
const char *str_string(string *s);

Hmm. Imagine that we'd named the type "buffer". I'd probably call
this buffertostr() or possibly bufferdata().
static int precedence_of(char op)
{
static const char *op_table[] = { "+-", "*/", "^", NULL };
if (op != '\0')
for (int i = 0; op_table; i++)
if (strchr(op_table, op))
return i;
return -1; /* not a operator */
}


That's pretty.
static bool convert_expression(const char **s, string *out)
{
return convert_term(s, out) && convert_operators(s, 0, out);
}

I'm a little put off by the magic of convert_operators apparently implying
converting the following term.
if (convert_term(s, out))
while ((right_prec = precedence_of(next(s))) > prec) {
if (!convert_operators(s, right_prec, out))
return false;
}
else return false;

I'd prefer {} on the if because the contents are more than a single line,
making this a tad confusing.
void str_add(string *s, char c)
{
if (s->size >= s->capacity) {
size_t new_cap = s->capacity * 3 / 2 + 8;

This is perfectly reasonable, but should probably be commented.

Overall, not bad at all, which is to say, certainly better than I'd have
done.

-s
 
B

Ben Bacarisse

Seebs said:
I don't like the name "string" for this. The term "string" is pretty
well defined in C, and I think this has real potential to confuse
readers in a larger program.

I dithered about that. In the end, since it is used only on this
program, the name was just about OK.
It seems like you might want to support adding strings, not just
characters. I think I'd have gone for

str_append(string *s, char *fmt, ...)

In the big version of my buffer code, I do have that but I cut out all
but the two functions actually used.

I'm a little put off by the magic of convert_operators apparently implying
converting the following term.

Is there a neat way to write it in C that is clearer?
I'd prefer {} on the if because the contents are more than a single line,
making this a tad confusing.

I have a background in teaching and have often wrestled with getting
fragments of code to fit on one OHP slide. As a result, I have an
unnatural urge to bracket minimally, but I agree that it is not
obviously the best way to do things.
This is perfectly reasonable, but should probably be commented.

Yup, but if I commented it, I'd have to justify the 3/2 factor! I do
that for hysterical raisins, more than anything else. If I thought
about it, I'd just double the capacity. The +8 (as I am sure you
spotted) is just a hack to avoid having to treat the initial zero as a
special case. The "code for clarity" version is probably:

size_t new_cap = s->capacity ? 2 * s->capacity : 8;

Hmm... I think I'll go change that right now.
Overall, not bad at all, which is to say, certainly better than I'd have
done.

Thanks. And thanks for looking it over.
 
S

spinoza1111

i have a string as (a+b)+8-(c/d) in Infix form.
how can i convert it to postfix form using C language,,,????
I suppose that if this is homework, the due date has passed.
// Convert ;-separated infix expressions on stdin to postfix on
stdout.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
// error handler
void die(char *msg)
{
  fprintf(stderr, "\ndie: %s\n", msg);
  exit(1);
}
// scanner
int lookahead;
int peek() { return lookahead; }
int peek_is(char *set)
{
  return strchr(set, peek()) != NULL;
}
void advance(void)
{
  do lookahead = getchar(); while (isspace(lookahead));
}
// parser for gramar:
// expr -> term { [+-] term }
// term -> factor { [*/] factor }
// factor -> ALNUM | "(" expr ")"
void term(void);
void factor(void);
void expr(void)
{
  term();
  while (peek_is("+-")) {
    int op = peek();
    advance();
    term();
    printf("%c", op);
  }
}
void term(void)
{
  factor();
  while (peek_is("*/")) {
    int op = peek();
    advance();
    factor();
    printf("%c", op);
  }
}
void factor(void)
{
  if (isalnum(peek())) {
    int literal = peek();
    advance();
    printf("%c", literal);
  }
  else if (peek() == '(') {
    advance();
    expr();
    if (!peek_is(")")) die("expected )");
    advance();
  }
  else
    die("expected factor");
}
// user interface
int main(void)
{
  advance();
  do {
    expr();
    if (!peek_is(";")) die("expected ;");
    printf("\n");
    advance();
  } while (peek() != EOF);
  return 0;
}- Hide quoted text -
- Show quoted text -
Thanks for this. Looks like you stole my approach, but I find that
most gratifying if true, and an indication that "great minds think
alike" if not. Your contribution at a minimum is to show just how
gnomic and terse one can be in C. It would not be appropriate to
credit me since it is a common and solid algorithm that has been
around for years.
Hope you don't mind, but I'm going to copy this code and incorporate
it in what will not be a three way test: of my C Sharp version, my C
version and your gnomic C. I want to add more testing (using a random
generator in C Sharp), a GUI and timing comparisions and shall report
back.- Hide quoted text -

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.  The
gramamr with minor variations is in at least a dozen complier design
textbooks including ASU. Usually it's given in left-recursive form,
and then the author or student go through the L-rec removal, left-
factoring, and BNF conversion.  RPN generation is a trivial example of
attribute evaluation.- Hide quoted text -

That's correct. It's as I said standard operating procedure.
Nonetheless I am interested in your use of C as I relearn C.
 

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
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top