⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap9.lst

📁 The Art of C++一书的配套源代码
💻 LST
📖 第 1 页 / 共 3 页
字号:
  get_token(); // skip opening ( 
  eval_exp(cond); // initialization expression 
 
  if(*token != ';') throw InterpExc(SEMI_EXPECTED); 
  prog++; // get past the ; 
  temp = prog; 
 
  for(;;) { 
    // Get the value of the conditional expression. 
    eval_exp(cond); 
 
    if(*token != ';') throw InterpExc(SEMI_EXPECTED); 
    prog++; // get past the ; 
    temp2 = prog; 
 
    // Find start of for block. 
    paren = 1; 
    while(paren) { 
      get_token(); 
      if(*token == '(') paren++; 
      if(*token == ')') paren--; 
    } 
 
    // Confirm start of block. 
    get_token(); 
    if(*token != '{')  
      throw InterpExc(BRACE_EXPECTED); 
    putback(); 
 
    // If condition is true, interpret 
    if(cond) 
      interp(); 
    else { // otherwise, skip to end of loop  
      find_eob(); 
      return; 
    } 
 
    prog = temp2; // go to increment expression 
 
    // Check for break in loop. 
    if(breakfound) { 
      // Find start of loop block. 
      do { 
        get_token(); 
      } while(*token != '{' && tok != END); 
 
      putback(); 
      breakfound = false; 
      find_eob(); // now, find end of loop 
      return; 
    } 
 
    // Evaluate the increment expression. 
    eval_exp(cond); 
 
    prog = temp; // loop back to top 
  } 
} 
 
// Execute a cout statement. 
void exec_cout() 
{ 
  int val; 
 
  get_token(); 
  if(*token != LS) throw InterpExc(SYNTAX); 
 
  do { 
    get_token(); 
 
    if(token_type==STRING) { 
      // Output a string. 
      cout << token; 
    } 
    else if(token_type == NUMBER || 
            token_type == IDENTIFIER) { 
      // Output a number. 
      putback(); 
      eval_exp(val); 
      cout << val; 
    } 
    else if(*token == '\'') { 
      // Output a character constant. 
      putback(); 
      eval_exp(val); 
      cout << (char) val; 
    } 
 
    get_token(); 
  } while(*token == LS); 
 
  if(*token != ';') throw InterpExc(SEMI_EXPECTED); 
} 
 
// Execute a cin statement. 
void exec_cin() 
{ 
  int val; 
  char chval; 
  token_ireps vtype; 
 
  get_token(); 
  if(*token != RS) throw InterpExc(SYNTAX); 
 
  do { 
    get_token(); 
    if(token_type != IDENTIFIER)  
      throw InterpExc(NOT_VAR); 
 
      vtype = find_var_type(token); 
 
      if(vtype == CHAR) { 
        cin >> chval; 
        assign_var(token, chval); 
      } 
      else if(vtype == INT) { 
        cin >> val; 
        assign_var(token, val); 
      } 
 
      get_token();       
  } while(*token == RS); 
 
  if(*token != ';') throw InterpExc(SEMI_EXPECTED); 
} 
 
// Find the end of a block. 
void find_eob() 
{ 
  int brace; 
 
  get_token(); 
  if(*token != '{') 
    throw InterpExc(BRACE_EXPECTED); 
 
  brace = 1; 
 
  do { 
    get_token(); 
    if(*token == '{') brace++; 
    else if(*token == '}') brace--; 
  } while(brace && tok != END); 
 
  if(tok==END) throw InterpExc(UNBAL_BRACES); 
} 
 
// Determine if an identifier is a variable. Return 
// true if variable is found; false otherwise. 
bool is_var(char *vname) 
{ 
  // See if vname a local variable. 
  if(!local_var_stack.empty()) 
    for(int i=local_var_stack.size()-1; 
        i >= func_call_stack.top(); i--) 
    { 
      if(!strcmp(local_var_stack[i].var_name, vname)) 
        return true; 
    } 
 
  // See if vname is a global variable. 
  for(unsigned i=0; i < global_vars.size(); i++) 
    if(!strcmp(global_vars[i].var_name, vname)) 
      return true; 
 
  return false; 
} 
 
// Return the type of variable. 
token_ireps find_var_type(char *vname) 
{ 
  // First, see if it's a local variable. 
  if(!local_var_stack.empty()) 
    for(int i=local_var_stack.size()-1; 
        i >= func_call_stack.top(); i--) 
    { 
      if(!strcmp(local_var_stack[i].var_name, vname)) 
        return local_var_stack[i].v_type; 
    } 
 
  // Otherwise, try global vars. 
  for(unsigned i=0; i < global_vars.size(); i++) 
    if(!strcmp(global_vars[i].var_name, vname)) 
        return local_var_stack[i].v_type; 
 
  return UNDEFTOK; 
}

listing 3
// ***** Internal Library Functions ***** 
 
// Add more of your own, here. 
 
#include <iostream> 
#include <cstdlib> 
#include <cstdio> 
#include "mccommon.h" 
 
using namespace std; 
 
// Read a character from the console. 
// If your compiler supplies an unbuffered 
// character intput function, feel free to 
// substitute it for the call to cin.get(). 
int call_getchar() 
{ 
  char ch; 
 
  ch = getchar(); 
 
  // Advance past ()   
  get_token(); 
  if(*token != '(') 
    throw InterpExc(PAREN_EXPECTED); 
 
  get_token(); 
  if(*token != ')') 
    throw InterpExc(PAREN_EXPECTED); 
 
  return ch; 
} 
 
// Write a character to the display. 
int call_putchar() 
{ 
  int value; 
 
  eval_exp(value); 
 
  putchar(value); 
 
  return value; 
} 
 
// Return absolute value. 
int call_abs() 
{ 
  int val; 
 
  eval_exp(val); 
 
  val = abs(val); 
 
  return val; 
} 
 
// Return a randome integer. 
int call_rand() 
{ 
   
  // Advance past ()   
  get_token(); 
  if(*token != '(') 
    throw InterpExc(PAREN_EXPECTED); 
 
  get_token(); 
  if(*token != ')') 
    throw InterpExc(PAREN_EXPECTED); 
 
  return rand(); 
}

listing 4
// Common declarations used by parser.cpp, minicpp.cpp, 
// or libcpp.cpp, or by other files that you might add. 
// 
const int MAX_T_LEN  = 128;   // max token length 
const int MAX_ID_LEN = 31;    // max identifier length 
const int PROG_SIZE  = 10000; // max program size 
const int NUM_PARAMS = 31;    // max number of parameters 
 
// Enumeration of token types. 
enum tok_types { UNDEFTT, DELIMITER, IDENTIFIER, 
                 NUMBER, KEYWORD, TEMP, STRING, BLOCK }; 
 
// Enumeration of internal representation of tokens. 
enum token_ireps { UNDEFTOK, ARG, CHAR, INT, SWITCH, 
                   CASE, IF, ELSE, FOR, DO, WHILE, BREAK, 
                   RETURN, COUT, CIN, END }; 
 
// Enumeration of two-character operators, such as <=. 
enum double_ops { LT=1, LE, GT, GE, EQ, NE, LS, RS, INC, DEC }; 
 
// These are the constants used when throwing a 
// syntax error exception. 
// 
// NOTE: SYNTAX is a generic error message used when 
// nothing else seems appropriate. 
enum error_msg 
     { SYNTAX, NO_EXP, NOT_VAR, DUP_VAR, DUP_FUNC, 
       SEMI_EXPECTED, UNBAL_BRACES, FUNC_UNDEF, 
       TYPE_EXPECTED, RET_NOCALL, PAREN_EXPECTED, 
       WHILE_EXPECTED, QUOTE_EXPECTED, DIV_BY_ZERO, 
       BRACE_EXPECTED, COLON_EXPECTED }; 
 
extern char *prog;  // current location in source code 
extern char *p_buf; // points to start of program buffer 
 
extern char token[MAX_T_LEN+1]; // string version of token 
extern tok_types token_type; // contains type of token 
extern token_ireps tok; // internal representation of token 
 
extern int ret_value; // function return value 
 
extern bool breakfound; // true if break encountered 
 
// Exception class for Mini C++. 
class InterpExc { 
  error_msg err; 
public: 
  InterpExc(error_msg e) { err = e; } 
  error_msg get_err() { return err; } 
}; 
 
// Interpreter prototypes. 
void prescan(); 
void decl_global(); 
void call(); 
void putback(); 
void decl_local(); 
void exec_if(); 
void find_eob(); 
void exec_for(); 
void exec_switch(); 
void get_params(); 
void get_args(); 
void exec_while(); 
void exec_do(); 
void exec_cout(); 
void exec_cin(); 
void assign_var(char *var_name, int value); 
bool load_program(char *p, char *fname); 
int find_var(char *s); 
void interp(); 
void func_ret(); 
char *find_func(char *name); 
bool is_var(char *s); 
token_ireps find_var_type(char *s); 
 
// Parser prototypes. 
void eval_exp(int &value); 
void eval_exp0(int &value); 
void eval_exp1(int &value); 
void eval_exp2(int &value); 
void eval_exp3(int &value); 
void eval_exp4(int &value); 
void eval_exp5(int &value); 
void atom(int &value); 
void sntx_err(error_msg error); 
void putback(); 
bool isdelim(char c); 
token_ireps look_up(char *s); 
int find_var(char *s); 
tok_types get_token(); 
int internal_func(char *s); 
bool is_var(char *s); 
 
// "Standard library" prototypes. 
int call_getchar(); 
int call_putchar(); 
int call_abs(); 
int call_rand();

listing 5
/* Mini C++ Demonstration Program #1. 
 
   This program demonstrates all features 
   of C++ that are recognized by Mini C++. 
*/ 
 
int i, j; // global vars  
char ch; 
 
int main() 
{ 
  int i, j; // local vars  
 
  // Call a "standard library' function. 
  cout << "Mini C++ Demo Program.\n\n"; 
 
  // Call a programmer-defined function. 
  print_alpha(); 
 
  cout << "\n"; 
 
  // Demonstrate do and for loops. 
  cout << "Use loops.\n"; 
  do { 
    cout << "Enter a number (0 to quit): "; 
    cin >> i; 
 
    // Demonstrate the if 
    if(i < 0 ) { 
      cout << "Numbers must be positive, try again.\n"; 
    } 
    else { 
      for(j = 0; j <= i; ++j) { 
        cout << j << " summed is "; 
        cout << sum(j) << "\n"; 
      } 
    } 
  } while(i != 0); 
 
  cout << "\n"; 
 
  // Demonstrate the break in a loop. 
  cout << "Break from a loop.\n"; 
  for(i=0; i < 100; i++) { 
    cout << i << "\n"; 
    if(i == 5) { 
      cout << "Breaking out of loop.\n"; 
      break; 
    } 
  } 
 
  cout << "\n"; 
 
  // Demonstrate the switch 
  cout << "Use a switch.\n"; 
  for(i=0; i < 6; i++) { 
    switch(i) { 
      case 1: // can stack cases 
      case 0: 
        cout << "1 or 0\n"; 
        break; 
      case 2: 
        cout << "two\n"; 
        break; 
      case 3: 
        cout << "three\n"; 
        break; 
      case 4: 
        cout << "four\n"; 
        cout << "4 * 4 is "<< 4*4 << "\n"; 
//        break; // this break is optional 
      // no case for 5 
    } 
  } 
  cout << "\n"; 
 
  cout << "Use a library function to generate "  
       << "10 random integers.\n"; 
  for(i=0; i < 10; i++) { 
    cout << rand() << " "; 
  } 
 
  cout << "\n"; 
  cout << "Done!\n"; 
 
  return 0; 
} 
 
// Sum the values between 0 and num. 
// This function takes a parameter. 
int sum(int num) 
{ 
  int running_sum; 
 
  running_sum = 0; 
 
  while(num) { 
    running_sum = running_sum + num; 
    num--; 
  } 
  return running_sum; 
} 
 
// Print the alphabet. 
int print_alpha() 
{ 
  cout << "This is the alphabet:\n"; 
 
  for(ch = 'A'; ch<='Z'; ch++) { 
    putchar(ch); 
  } 
  cout << "\n"; 
 
  return 0; 
}

listing 6
// Nested loop example. 
int main() 
{ 
  int i, j, k; 
 
  for(i = 0; i < 5; i = i + 1) { 
    for(j = 0; j < 3; j = j + 1) { 
      for(k = 3; k ; k = k - 1) { 
        cout << i <<", "; 
        cout << j << ", "; 
        cout << k << "\n"; 
      } 
    } 
  } 
 
  cout << "done"; 
 
  return 0; 
}

listing 7
// Assigments as operations. 
int main() 
{ 
  int a, b; 
 
  a = b = 5; 
 
  cout << a << " " << b << "\n"; 
 
  while(a=a-1) { 
    cout << a << " ";  
    do { 
      cout << b << " "; 
    } while((b=b-1) > -5); 
    cout << "\n"; 
  } 
 
  return 0; 
}

listing 8
// This program demonstrates a recursive function. 
 
// A recursive function that returns the 
// factorial of i. 
int factr(int i) 
{ 
  if(i<2) { 
    return 1; 
  } 
  else { 
     return i * factr(i-1); 
  } 
} 
 
int main() 
{ 
  cout << "Factorial of 4 is: "; 
  cout << factr(4) << "\n"; 
 
  cout << "Factorial of 6 is: "; 
  cout << factr(6) << "\n"; 
 
  return 0; 
}

listing 9
// A more rigorous example of function arguments.  
 
int f1(int a, int b) 
{ 
  int count; 
 
  cout << "Args for f1 are "; 
  cout << a << " " << b << "\n"; 
 
  count = a; 
  do { 
    cout << count << " "; 
  } while(count=count-1); 
 
  cout << a << " " << b 
       << " " << a*b << "\n"; 
 
  return a*b; 
} 
 
int f2(int a, int x, int y) 
{ 
  cout << "Args for f2 are "; 
  cout << a << " " << x << " " 
       << y << "\n"; 
  cout << x / a << " "; 
  cout << y*x << "\n"; 
 
  return 0; 
} 
 
int main() 
{ 
  f2(10, f1(10, 20), 99); 
 
  return 0; 
}

listing 10
// Exercise the loop statements. 
int main() 
{ 
  int a; 
  char ch; 
 
  // The while. 
  cout << "Enter a number: "; 
  cin >> a; 
  while(a) { 
    cout << a*a << " "; 
    --a; 
  } 
  cout << "\n"; 
 
  // The do-while. 
  cout << "\nEnter characters, 'q' to quit.\n"; 
  do { 
    // Use two "standard library" functions. 
    ch = getchar(); 
    putchar(ch); 
  } while(ch != 'q'); 
  cout << "\n\n"; 
 
  // the for. 
  for(a=0; a<10; ++a) { 
     cout << a << " "; 
  } 
 
  cout << "\n\nDone!\n"; 
 
  return 0; 
}

listing 11
// Demonstrate nested scopes. 
 
int x; // global x 
 
int main() 
{ 
  int i; 
 
  i = 4; 
 
  x = 99; // global x is 99 
 
  if(i == 4) { 
    int x; // local x 
    int num; // local to if statement 
 
    x = i * 2; 
    cout << "Outer local x before loop: " 
         << x << "\n"; 
 
    while(x--) { 
      int x; // another local x 
 
      x = 18; 
      cout << "Inner local x: " << x << "\n"; 
    }  
 
    cout << "Outer local x after loop: " 
         << x << "\n"; 
  } 
 
  // Can't refer to num here because it is local 
  // to the preceding if block. 
//  num = 10;  
 
  cout << "Global x: " << x << "\n"; 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -