Demo 2 vastauksia

Demo 2 vastauksia	
1. 2-suuntainen lista (Tehtävä 2.36_1)	
2. Linkitetty lista (Tehtävä 2.36_2)	
3. 2-suuntainen linkitetty lista (Tehtävä 2.37_3)	
4. “Virheen” käsittely hävittäjän avulla (Tehtävä 2.38)	
5. “Virheen” käsittely poikkeusten avulla (Tehtävä 2.39)	

1.	2-suuntainen lista (Tehtävä 2.36_1)
/* teht8_1.cpp M 2.30.1 */
/*
Tehtäviä 1) Peri luokasta luokka list2, joka on kaksisuuntainen ja
            jossa voidaan siis liikkua kumpaankin suuntaan.
*/

#include <iostream.h>

inline int inside(int a,int x,int b) // x välille [a,b], jos b<a niin a
  { return b < a ? a : x < a ? a : x < b ? x : b; }

#define MAX_ELEM 100

#define TYPE char

...

class list2 : public list {
public:
  list2() : list() {};
  int  backward()  { --cursor;   return out();                 }
  TYPE previous()  { backward(); return current();             }
};

/****************************************************************************/
int main(void)
{
  list2 lc; lc.add('a'); lc.add('b'); lc.add('c'); lc.add('d');

  for (lc.toend(); !lc.out(); lc.backward() )
    cout << lc.current() << " ";

  return 0;
}
2.	Linkitetty lista (Tehtävä 2.36_2)
/* teht8_2.cpp M 2.30.2 */
/*
         2) Toteuta list "oikeana" dynaamisena listana.
*/

#include <iostream.h>

#define TYPE char
class list;

class elem {
  friend list;
  TYPE data;
  elem *next_elem;
  elem(TYPE d)  { data = d; next_elem = NULL; }
  int add(elem *n) { next_elem = n; return 0; }
};

class list {
protected:
  elem *first_elem;
  elem *last_elem;
  elem *cursor;          // Sijainti listassa
  TYPE out_data;
  int no_elem()    { first_elem = last_elem = cursor = NULL; out_data = 0;
                     return 0;                                               }
public:
  int delete_all();
  list()           { no_elem();                                              }
  ~list()          { delete_all();                                           }

  int  out()       { return ( cursor == NULL );                              }
  int  tobegin()   { cursor = first_elem;   return out();                    }
  int  forward()   { if ( !cursor ) return 1;
                     out_data = cursor->data;
                     cursor = cursor->next_elem; return 0;                   }
  int  toend()     { cursor = last_elem; return out();                       }
  TYPE current()   { return cursor ? cursor->data : out_data;                }
  TYPE first()     { tobegin(); return current();                            }
  TYPE next()      { forward(); return current();                            }
  TYPE last()      { toend();   return current();                            }
  int  empty()     { return ( first_elem == NULL );                          }
  int  add(TYPE p) { elem *n = new elem(p);
                     if ( !n ) return 1;
                     if ( first_elem ) last_elem->add(n);
                     else first_elem = n;
                     last_elem = n; return 0;
                   }
}; /* list */

int list::delete_all()
{
  elem *e;
  tobegin();
  while ( cursor ) { e = cursor; forward(); delete e; }
  return no_elem();
}

#define VIIVA "------------------------------------------------------------\n"
/****************************************************************************/
int main(void)
{
  cout << VIIVA;

  list lc; lc.add('a'); lc.add('b'); lc.add('c'); lc.add('d');

  for (char c=lc.first(); !lc.out(); c=lc.next() )
    cout << c << " ";

  cout << c << "\n" << VIIVA;

  for (lc.tobegin(); !lc.out(); lc.forward() )
    cout << lc.current() << " ";

  cout << lc.current() << "\n" << VIIVA;

  return 0;
}
3.	2-suuntainen linkitetty lista (Tehtävä 2.37_3)
/* teht8_3.cpp M 2.30.3 */
/*
         3) Peri tehtävän 2 listasta 2-suuntainen lista.
            Onnistuuko kunnolla? Ei ilman templatea!
*/

#include <iostream.h>

template <class TYPE>
class elem {
public:
  TYPE data;
  elem *next_elem;
  virtual int add(elem *n) { next_elem = n; return 0; }
  elem(TYPE &d)    { data = d; next_elem = NULL; }
};

template <class TYPE,class ELEM>
class base_list {
protected:
  ELEM *first_elem;
  ELEM *last_elem;
  elem<TYPE> *cursor;          // Sijainti listassa
  TYPE out_data;
  int no_elem()    { cursor = first_elem = last_elem = NULL;
                     out_data = 0; return 0;                                 }
public:
  int delete_all();
  base_list()      { no_elem();                                              }
  ~base_list()     { delete_all();                                           }

  int  out()       { return ( cursor == NULL );                              }
  int  tobegin()   { cursor = first_elem;   return out();                    }
  int  forward()   { if ( !cursor ) return 1;
                     out_data = cursor->data;
                     cursor = cursor->next_elem; return 0;                   }
  int  toend()     { cursor = last_elem; return out();                       }
  const TYPE &current()   { return cursor ? cursor->data : out_data;         }
  const TYPE &first()     { tobegin(); return current();                     }
  const TYPE &next()      { forward(); return current();                     }
  const TYPE &last()      { toend();   return current();                     }
  int  empty()     { return ( first_elem == NULL );                          }
  int  add(TYPE p) { ELEM *n = new ELEM(p);
                     if ( !n ) return 1;
                     if ( first_elem ) last_elem->add(n);
                     else first_elem = n;
                     last_elem = n; return 0;
                   }
}; /* base_list<TYPE,ELEM> */

template <class TYPE,class ELEM>
int base_list<TYPE,ELEM>::delete_all()
{
  elem<TYPE> *e;
  tobegin();
  while ( cursor ) { e = cursor; forward(); delete e; }
  return no_elem();
}

/****************************************************************************/
template <class TYPE>
class single_elem : public elem<TYPE> {
public:
  single_elem(TYPE &d) : elem<TYPE>(d) {};
}

template <class TYPE>
class list : public base_list<TYPE,single_elem<TYPE> > {
public:
  list() : base_list<TYPE,single_elem<TYPE> >  () {};
};

/****************************************************************************/
template <class TYPE>
class double_elem : public elem<TYPE>  {
public:
  double_elem *previous_elem;
  double_elem(TYPE &d) : elem<TYPE>(d) { previous_elem = NULL;};
  int add(elem<TYPE> *n) {
    ((double_elem<TYPE> *)n)->previous_elem = this; next_elem = n; return 0; }
}

template <class TYPE>
class dlist : public base_list<TYPE,double_elem<TYPE> > {
public:
  dlist() : base_list<TYPE,double_elem<TYPE> >  () {};
  int  backward()  { if ( !cursor ) return 1;
                     out_data = cursor->data;
                     cursor = ((double_elem<TYPE> *)cursor)->previous_elem;
                     return 0;                                               }
  const TYPE &previous() { backward(); return current();                     }
};

#define VIIVA "------------------------------------------------------------\n"
/****************************************************************************/
int main(void)
{
  cout << VIIVA;

  dlist<char> lc; lc.add('a'); lc.add('b'); lc.add('c'); lc.add('d');

  for (char c=lc.first(); !lc.out(); c=lc.next() )
    cout << c << " ";

  cout << c << "\n" << VIIVA;

  for (lc.tobegin(); !lc.out(); lc.forward() )
    cout << lc.current() << " ";

  cout << lc.current() << "\n" << VIIVA;
#if 1
  for (c=lc.last(); !lc.out(); c=lc.previous() )
    cout << c << " ";

  cout << c << "\n" << VIIVA;

  for (lc.toend(); !lc.out(); lc.backward() )
    cout << lc.current() << " ";

  cout << lc.current() << "\n" << VIIVA;
#endif
  return 0;
}
4.	“Virheen” käsittely hävittäjän avulla (Tehtävä 2.38)
/* Teht9  M 2.32 */
#include <iostream.h>
#include <stdio.h>
#include <string.h>

class tiedosto {
  FILE *f;
  char nimi[50];     // tiedoston nimi
public:
  tiedosto(char *s) { strncpy(nimi,s,sizeof(nimi)); f = NULL;                }
  int avaa()        { f = fopen(nimi,"r"); return (f != NULL) ? 0 : 1;       }
  int lue()         { int c = fgetc(f); return c != EOF ? c : 0;             }
  int sulje()       { if ( f ) fclose(f); return 0;                          }
  ~tiedosto()       { sulje();                                               }
};

int tiedostot(char *na, char *nb, char *nc)
{
  tiedosto a(na), b(nb), c(nc);
  if ( a.avaa() ) return -1;
  if ( b.avaa() ) return -2;
  if ( c.avaa() ) return -3;
  return  a.lue() + b.lue() + c.lue();
}

int main(void)
{
  int k = tiedostot("t1","t2","t3");
  cout << "Funktio palautti " << k << '\n'; 

  return 0;
}

5.	“Virheen” käsittely poikkeusten avulla (Tehtävä 2.39)
/* Teht9b  M 2.33 */
#include <iostream.h>
#include <stdio.h>
#include <string.h>

class tiedosto {
  FILE *f;
  char nimi[13];     // tiedoston nimi
  int nro;           // tiedoston numero
public:
  tiedosto(char *s,int k) { strncpy(nimi,s,sizeof(nimi));
                            f = NULL; nro = k; avaa();                       }
  int avaa() {
    f = fopen(nimi,"r");
    if (f == NULL) throw int(nro);
    return 0;
  }
  int lue()         { int c = fgetc(f); return c != EOF ? c : 0;             }
  int sulje()       { if ( f ) fclose(f); return 0;                          }
  ~tiedosto()       { sulje();                                               }
};

int tiedostot(char *na, char *nb, char *nc)
{
  try {
    tiedosto a(na,-1), b(nb,-2), c(nc,-3);
    return  a.lue() + b.lue() + c.lue();
  }
  catch ( int n ) { return n; }
}

int main(void)
{
  int k = tiedostot("t1","t2","t3");
  cout << "Funktio palautti " << k << '\n';

  return 0;
}