DM560, Introduction to Programming in C++

Sheet 7

Task 1

Task 2

#include<iostream>
#include<iomanip>
#include<limits>

#include<climits>


using namespace std;

const int width=20;

void print_num(double n) {
  cout<<scientific<<setprecision(10)<<setw(width)<<n;
}

void print_head(string s) {
  cout<<setw(width)<<s;
}



int main () {
  print_head("type");
  print_head("lowest()");
  print_head("min()");
  print_head("max()");
  cout<<"\n";
  

  print_head("int");
  print_num(numeric_limits<int>::lowest());
  print_num(numeric_limits<int>::min());
  print_num(numeric_limits<int>::max());
  cout<<"\n";
  
  print_head("unsigned int");
  print_num(numeric_limits<unsigned int>::lowest());
  print_num(numeric_limits<unsigned int>::min());
  print_num(numeric_limits<unsigned int>::max());
  cout<<"\n";
  
  print_head("short int");
  print_num( numeric_limits<short int>::lowest());
  print_num(numeric_limits<short int>::min());
  print_num( numeric_limits<short int>::max());
  cout<<"\n";

  print_head("long int");
  print_num(numeric_limits<long int>::lowest());
  print_num(numeric_limits<long int>::min());
  print_num(numeric_limits<long int>::max());
  cout<<"\n";
        
  print_head("float");
  print_num(numeric_limits<float>::lowest());
  print_num(numeric_limits<float>::min());
  print_num(numeric_limits<float>::max());
  cout<<"\n";

  print_head("double");
  print_num(numeric_limits<double>::lowest());
  print_num(numeric_limits<double>::min());
  print_num(numeric_limits<double>::max());
  cout<< '\n';

  print_head("char");
  print_num(+numeric_limits<char>::lowest());
  print_num(+numeric_limits<char>::min());
  print_num(+numeric_limits<char>::max());
  cout<< '\n';

  print_head("uchar");
  print_num(numeric_limits<unsigned char>::lowest());
  print_num(numeric_limits<unsigned char>::min());
  print_num(numeric_limits<unsigned char>::max());
  cout<< '\n';

 
  exit(EXIT_SUCCESS);
}

Task 3

/*

Binary number:
100  1101 0010
Binary signed 2's complement:
00000100 11010010
Hex number:
4d2


 */

#include <iostream>

using namespace std;

template <class T> char *as_bytes(T &x) { return &reinterpret_cast<char &>(x); }

int main() {
  const int num = 1234;

  int x = static_cast<int>(num);
  cout << x << "\t";
  cout << sizeof(x) << "\n";
  for (int i = 0; i < sizeof(x); i++) {
    cout << hex << showbase << (0xff & (unsigned int)(*(as_bytes(x) + i)))
         << " ";
  }
  cout <<endl;
  // Note that you need to mask the cast int against 0xff to display the least
  // significant byte: (0xff & (unsigned int)el). Otherwise, if the highest bit
  // is set the cast will result in the three most significant bytes being set
  // to ff.
  for (int i = 0; i < sizeof(x); i++) {
    cout << hex << showbase << ((int)(*(as_bytes(x) + i))) << " ";
  }
  cout <<endl;
  for (int i = 0; i < sizeof(x); i++) {
    cout << hex << showbase << ((short int)(*(as_bytes(x) + i))) << " ";
  }
  cout <<endl;
  for (int i = 0; i < sizeof(x); i++) {
    cout << hex << showbase << ((long int)(*(as_bytes(x) + i))) << " ";
  }
  cout <<endl;
  for (int i = 0; i < sizeof(x); i++) {
    cout << hex << showbase << ((float)(*(as_bytes(x) + i))) << " ";
  }
  cout <<endl;
  for (int i = 0; i < sizeof(x); i++) {
    cout << hex << showbase << ((double)(*(as_bytes(x) + i))) << " ";
  }
  cout <<endl;
  //    cout << hex << showbase << (0xff & (string)(*(as_bytes(x) + i)))<< "\n";

  cout << hex << *(as_bytes(x)) << "\t";
  exit(EXIT_SUCCESS);
}

Task 4

Review the code on the Punctuation example from the book.

The code is explained in Section 11.7 of the text book.

Task 5

Decrypt the following message (use Punct_stream to eliminate punctuation):

SURJUDPV PXVW EH ZULWWHQ IRU SHRSOH WR UHDG, DQG RQOB LQFLGHQWDOOB IRU
PDFKLQHV WR HAHFXWH.

This is an example of [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher). Using the `Punctuation` library from the previous task we can solve the task by brute force, trying all possible shifts (in this case, from 1 to 25):

#include "punct_stream.h"
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>

using namespace std;

void inplace_decrypt(string &word, const string &letters, const int shift) {
  int new_i = 0;
  int size = letters.size();
  for (char &c : word) {
    for (int i = 0; i < size; i++) {
      new_i = (i + shift) % size;
      if (letters[new_i] == c) {
        c = letters[i];
        break;
      }
    }
  }
}

int main() {
  string letters = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  transform(letters.begin(), letters.end(), letters.begin(),
            [](unsigned char c) { return tolower(c); });

  string message = "SURJUDPV PXVW EH ZULWWHQ IRU SHRSOH WR UHDG, DQG RQOB "
                   "LQFLGHQWDOOB IRUPDFKLQHV WR HAHFXWH.\n";
  stringstream ins;
  ins.str(message);

  Punct_stream ps{ins};
  ps.whitespace(";:,.?!()\"{}<>/&$@#%^*|~"); // note \“ means ” in string
  ps.case_sensitive(false);
  // cout << "please enter words (ctrl-D to terminate)\n";

  vector<string> vs;
  for (string word; ps >> word;)
    vs.push_back(word);

  for (int s = 0; s < letters.size(); s++) {
    stringstream sentence;
    for (string word : vs) {
      inplace_decrypt(word, letters, s);
      sentence << word << " ";
    }
    cout << "shift:" << setw(3) << s << " " << sentence.str() << endl;
  }
}

All together the code is available from here: cipher.tgz.

The code provides an example of:

all:
	$(MAKE) -C lib clean

Task 8

Draw the graph of Task 2 in Sheet 6. Make up some coordinates for the points. For example, place the points at equal distance in a circle.