What does this mean? Please help!

In my Book it says:

It talks about the expr function in the code.

"You could also analyze an arithmetic expression using a recursive function. If you think about the definition of an expression slightly differently, you could specify it as being either a term, or a term followed by an expression. The definition here is recursive (i.e., the defi nition involves the item being
defined), and this approach is very common in defining programming language structures. This definition provides just as much flexibility as the fi rst, but using it as the base concept, you could arrive at a recursive version of expr() instead of using a loop as you did in the implementation of expr(). You might want to try this alternative approach as an exercise after you have completed the
first version."

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// EX6_10.cpp
// A program to implement a calculator

#include <iostream>                   // For stream input/output
#include <cctype>                     // For the isdigit() function
using std::cin;
using std::cout;
using std::cerr;
using std::endl;

void eatspaces(char* str);            // Function to eliminate blanks
double expr(char* str);               // Function evaluating an expression
double term(char* str, int& index);   // Function analyzing a term
double number(char* str, int& index); // Function to recognize a number

const int MAX(80);                    // Maximum expression length, 
                                      // including '\0'
int main()
{
   char buffer[MAX] = {0};    // Input area for expression to be evaluated

   cout << endl
        << "Welcome to your friendly calculator."
        << endl
        << "Enter an expression, or an empty line to quit."
        << endl;

   for(;;)
   {
      cin.getline(buffer, sizeof buffer);   // Read an input line
      eatspaces(buffer);                    // Remove blanks from input

      if(!buffer[0])                        // Empty line ends calculator
         return 0;
      try
      {
        cout << "\t= " << expr(buffer)      // Output value of expression
             << endl << endl;
      }
      catch( const char* pEx)
      {
        cerr << pEx << endl;
        cerr << "Ending program." << endl;
        return 1;
      }
   }
}


// Function to eliminate spaces from a string
void eatspaces(char* str)
{
   int i(0);                              // 'Copy to' index to string
   int j(0);                              // 'Copy from' index to string

   while((*(str + i) = *(str + j++)) != '\0')  // Loop while character
                                               // copied is not \0
      if(*(str + i) != ' ')                    // Increment i as long as
         i++;                                  // character is not a space
   return;
}

// Function to evaluate an arithmetic expression
double expr(char* str)
{
  double value(0.0);                   // Store result here
  int index(0);                        // Keeps track of current character position

  value = term(str, index);            // Get first term

  for(;;)                              // Indefinite loop, all exits inside
  {
    switch(*(str + index++))           // Choose action based on current character
    {
      case '\0':                       // We're at the end of the string
         return value;                 // so return what we have got

      case '+':                        // + found so add in the
         value += term(str, index);    // next term
         break;

      case '-':                        // - found so subtract
         value -= term(str, index);    // the next term
         break;

      default:                         // If we reach here the string is junk
         char message[38] = "Expression evaluation error. Found: ";
         strncat_s(message, str + index - 1, 1);  // Append the character
         throw message;
         break;
    }
  }
}

// Function to get the value of a term
double term(char* str, int& index)
{
  double value(0.0);                   // Somewhere to accumulate 
                                       // the result

  value = number(str, index);          // Get the first number in the term

  // Loop as long as we have a good operator
  while(true)
  {

    if(*(str + index) == '*')          // If it's multiply,
      value *= number(str, ++index);   // multiply by next number

    else if(*(str + index) == '/')     // If it's divide,
      value /= number(str, ++index);   // divide by next number
    else
      break;
  }
  return value;                        // We've finished, so return what 
                                       // we've got
}

// Function to recognize a number in a string
double number(char* str, int& index)
{
  double value(0.0);                  // Store the resulting value

  // There must be at least one digit...
  if(!isdigit(*(str + index)))
  { // There's no digits so input is junk...
    char message[31] = "Invalid character in number: ";
    strncat_s(message, str+index, 1);  // Append the character
    throw message;
  }

  while(isdigit(*(str + index)))       // Loop accumulating leading digits
    value = 10*value + (*(str + index++) - '0');

                                       // Not a digit when we get to here
  if(*(str + index) != '.')            // so check for decimal point
    return value;                      // and if not, return value

  double factor(1.0);                  // Factor for decimal places
  while(isdigit(*(str + (++index))))   // Loop as long as we have digits
  {
    factor *= 0.1;                     // Decrease factor by factor of 10
    value = value + (*(str + index) - '0')*factor;   // Add decimal place
  }

  return value;                        // On loop exit we are done
}


Can anyone explain what it means by

"You could also analyze an arithmetic expression using a recursive function. If you think about the definition of an expression slightly differently, you could specify it as being either a term, or a term followed by an expression. The definition here is recursive (i.e., the definition involves the item being
defined), and this approach is very common in defi ning programming language structures."

I know how to turn it into a recursive function except what does it mean if I think about the expression slightly differently?

Can anyone please explain?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <cstddef>

constexpr char nullchar = 0 ;

namespace one
{
    // one way of thinking about a c-style string
    // a c-style string is: a sequence of char ending with a null char

    std::size_t length( const char* cstr )
    {
        std::size_t len = 0 ;
        while( *cstr++ != nullchar ) ++len ;
        return len ;
    }

    char* copy( char* dest, const char* srce )
    {
        char* p = dest ;
        while( ( *p++ = *srce++ ) != nullchar ) ;
        return dest ;
    }
}

namespace two
{
    // another way of thinking about a c-style string
    /* a c-style string is:
             a. a nullchar
          or b. a non-null char followed by a c-style string
    */

    std::size_t length( const char* cstr )
    {
        if( *cstr == nullchar ) return 0 ; // it is just a nullchar at cstr

        // it is a non-null char at cstr
        // followed by a c-style string at cstr+1
        else return 1 + length( cstr+1 ) ;
    }

    char* copy( char* dest, const char* srce )
    {
        *dest = *srce ;
        if( *srce != nullchar ) copy( dest+1, srce+1 ) ;
        return dest ;
    }
}
Last edited on
@JLBorges
1
2
3
4
5
6
    char* copy( char* dest, const char* srce )
    {
        char* p = dest ;
        while( ( *p++ = *srce++ ) != nullchar ) ;
        return p ;
    }


There is a typo.:) Shall be

return dest;

EDIT: though the using of the while loop for such a function is generally accepted I would prefer to use the for loop that to restrict the scope of local variable p.

1
2
3
4
5
6
    char* copy( char* dest, const char* srce )
    {
        for ( char *p = dest; *p = *srce; ++p, ++srce ) ;

        return dest ;
    }
Last edited on
> There is a typo.:)

Thanks! Corrected.
As for the original question the author of the book said that function expr could be rewritten as a recursive function instead of using the loop for( ;; ) within its body.
Topic archived. No new replies allowed.