Pages

Sunday, 11 March 2018

Chapter 7 // Exercise 5 - Principles & Practice Using C++

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


Chapter 7 // Exercise 5


5. Modify Token_stream::get() to return Token(print) when it sees a new line. This implies looking for whitespace characters and treating newline ('\n') specifically.You might find the standard library function isspace(ch), which returns true is ch is a whitespace character useful.


This stumped me a little until I did some research and found that cin >> skips whitespace. I know it was already in the comments but my brain clearly wasn't working properly. A quick search showed that cin.get() doesn't skip whitespace allowing you to check for special characters such as '\n'.

I simply changed the char print to '\n' and then added a while loop in get() which checks to see if there is any whitespace in the buffer. If there is it checks to see if that whitespace is a newline, if it is it returns the command to print, if not it gets the next char in the buffer as we still need to check for spaces inbetween naming.


//evaluate each char in the stream and determine what it is 
Token Token_stream::get()
{
 if (full) //check if we have already have a token ready
 { 
  full = false; 
  return buffer; 
 }

 char ch;
 cin.get(ch);        //does not skip whitespace
 while (isspace(ch))       //if ch is whitespace
 {
  if(ch == '\n')       //if ch == newline 
   return Token(print);    //print result

  cin.get(ch);       //if not newline get next ch in stream
 }

 switch (ch) 
 {
  case '(': case ')': case '+': case '-':
  case '*': case '/': case '%': 
  case '=': case ',':
   return Token(ch);     //let each char represent itself
  case '.':
  case '0': case '1': case '2': case '3':
  case '4': case '5': case '6': case '7':
  case '8': case '9':
  { 
   cin.unget();      //put digit back into the input stream
   double val;
   cin >> val;       //read a floating-point number
   return Token{ number, val };  //return number or . with a value, put back into buffer
  }

  //allo user defined variables if user types #
  case '#':
   return Token(let);
  
  default:
   //do this if ch is a letter
   if (isalpha(ch) || ch == '_') 
   {
    string s;
    s += ch;

    //while there are still chars in cin, read them into s
    while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) 
     s += ch;
    cin.unget();

    //if string is equal to other commands defined below, return them
    if (s == declKey) 
     return Token(let);
    if(s == constKey)
     return Token(isConst);
    if (s == quitKey) 
     return Token(quit);
    if (s == sqrtKey)
     return Token(squareR);
    if (s == powKey)
     return Token(findPow);

    return Token(name, s);
   }

   //if the char does not fit any of these paramenters return an error message
   error("Bad token");
 }
}

No comments:

Post a Comment