Programsystemkonstruktion med C++: ¨ Ovning 3
Karl Palmskog palmskog@kth.se
september 2010
Programsystemkonstruktion med C++: ¨Ovning 3 Tentar¨attning
Tentafr˚ aga: Att s¨ oka sekvenser
a. Skriv en generell typparametriserad funktion SeqSearch som tar fyra parametrar. Parametrarna definerar tv˚ a sekvenser i godtycklig m¨ angd. Funktionen ska returnera huruvida den andra sekvensen ¨ ar en delsekvens av den f¨ orsta. Exempel: {1 2 3} ¨ ar en delsekvens av {1 2 3 4} och {2 4} ¨ ar en delsekvens av {1 2 3 4} medan varken {3 2} eller {2 2} ¨ ar en delsekvens av {1 2 3 4}. S¨ okning efter tomma m¨ angden ska ge falskt svar.
Algoritmen ¨ ar ungef¨ ar, g˚ a igenom det stora intervallet och
kontrollera om ett element ¨ aven finns i delsekvensen. S¨ okningen ¨ ar sann om alla delsekvensens element p˚ atr¨ affats i ordning.
b. Vad st¨ aller din l¨ osning f¨ or krav p˚ a parametrarna?
c. Kan man skriva funktionen s˚ a att den anropas med tv˚ a olika sorters
typparametrar? Motivera ditt svar.
L¨ osning: subseq.h
t e m p l a t e <c l a s s I t 1 , c l a s s I t 2 >
b o o l s u b s e q ( I t 1 i t 1 , I t 1 end1 , I t 2 i t 2 , I t 2 e n d 2 ) {
i f ( i t 2 == e n d 2 ) r e t u r n f a l s e ; f o r ( ; i t 1 != e n d 1 ; ++i t 1 )
i f ( i t 2 != e n d 2 && ∗ i t 1 == ∗ i t 2 ) i t 2 ++;
r e t u r n i t 1 == e n d 1 && i t 2 == e n d 2 ; }
Programsystemkonstruktion med C++: ¨Ovning 3 Tentar¨attning
Anv¨ andning: main.cpp
#i n c l u d e < s t r i n g >
#i n c l u d e <i o s t r e a m >
#i n c l u d e ” s u b s e q . h ” u s i n g namespace s t d ;
v o i d t e s t s t r i n g ( s t r i n g s ) { s t r i n g i p r = ” i p r e d ” ;
c o u t << ” s u b s e q : ’ ” << i p r << ” ’ i ’ ” << s << ” ’ ”
<< s u b s e q ( s . b e g i n ( ) , s . end ( ) , i p r . b e g i n ( ) , i p r . end ( ) )
<< e n d l ; }
i n t main ( ) {
s t r i n g s 1 = ” h e j h o p p ” ;
s t r i n g s 2 = ” i p r e d ” ;
s t r i n g s 3 = ” i f ¨o l j d i p r e d ” ; t e s t s t r i n g ( s 1 ) ;
t e s t s t r i n g ( s 2 ) ; t e s t s t r i n g ( s 3 ) ; }
K¨ orning
$ g++ −o s s q main . cpp
$ . / s s q
s u b s e q : ’ i p r e d ’ i ’ h e j h o p p ’ 0
s u b s e q : ’ i p r e d ’ i ’ i p r e d ’ 1
s u b s e q : ’ i p r e d ’ i ’ i f ¨ o l j d i p r e d ’ 1
Programsystemkonstruktion med C++: ¨Ovning 3 Tentar¨attning
F¨ oreslagen l¨ osning av tentand
t e m p l a t e <c l a s s T>
b o o l s u b s e q (T s1 , T s 2 ) { u n s i g n e d i n t x = 0 ;
f o r ( u n s i g n e d i n t i = 0 ; i < s 1 . s i z e ( ) ; i ++) { i f ( s 1 [ i ] == s 2 [ i ] ) {
x++;
} }
r e t u r n x == s 2 . s i z e ( ) ; }
Utskrift fr˚ an k¨ orning:
s u b s e q : ’ i p r e d ’ i ’ h e j h o p p ’ 0
s u b s e q : ’ i p r e d ’ i ’ i p r e d ’ 0
s u b s e q : ’ i p r e d ’ i ’ i f ¨ o l j d i p r e d ’ 0
Felrapportering
Fr˚ aga allvarlig felkod ¨ ovriga fel kommentar
1 1a-01
Funktionen har bara tv˚a parame- trar ist¨allet f¨or de specificerade fyra.1b-02 . . .
2 2a-03 . . .
Programsystemkonstruktion med C++: ¨Ovning 3 Tentafr˚agor
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ; s t r u c t T h e M a t r i x {
v i r t u a l T h e M a t r i x f o o ( ) {
c o u t << ” T h e M a t r i x : : f o o ( ) ” ; r e t u r n ∗ t h i s ; }
} ;
s t r u c t TheWorld : T h e M a t r i x { v i r t u a l T h e M a t r i x f o o ( ) {
c o u t << ” TheWorld : : f o o ( ) ” ; r e t u r n ∗ t h i s ; }
} ;
i n t main ( ) { TheWorld w o r l d ;
T h e M a t r i x m a t r i x = w o r l d ; T h e M a t r i x & r e f = w o r l d ;
c o u t << e n d l << ” a ) ” ; w o r l d . f o o ( ) ; c o u t << e n d l << ” b ) ” ; m a t r i x . f o o ( ) ; c o u t << e n d l << ” c ) ” ; r e f . f o o ( ) ;
c o u t << e n d l << ” d ) ” ; r e f . f o o ( ) . f o o ( ) ; c o u t << e n d l ; }
Typparametriserad swap
I standardbiblioteket finns den typparametriserade funktionen swap som byter p˚ a tv˚ a argument:
i n t a = 3 ; i n t b = 5 ;
swap ( a , b ) ; // now a i s 5 and b i s 3
a. Implementera swap.
b. Varf¨ or fungerar swap ineffektivt om den anropas med tv˚ a
Vector fr˚ an labb 1?
Programsystemkonstruktion med C++: ¨Ovning 3 Tentafr˚agor
Julkalendern
Sveriges television vill best¨ alla ett kalenderprogram till jul.
Programmet ska kunna g˚ a p˚ a export, det ska finnas en svensk och en kinesisk kalender och s˚ a sm˚ aningom fler.
a. Ett f¨ oretag erbjuder en l¨ osning d¨ ar den svenska och kinesiska kalendern ¨ arver fr˚ an en gemensam basklass. De h¨ avdar att de anv¨ ander sig av polymorfi och det g¨ or deras l¨ osning b¨ ast. Vad menas med polymorfi?
b. Ett annat f¨ oretag erbjuder en typparametriserad kalender. De menar att de anv¨ ander sig av compile-time polymorfi. Vad tror du de menar med det?
c. Den slutliga l¨ osningen blir en arvshierarki d¨ ar samtliga
subklasser ¨ arver multipelt h¨ ar och var. Beskriv vad som kan
bli problem med multipelt arv.
Input/Output i C
i n t f p r i n t f ( FILE ∗ s t r e a m , c o n s t c h a r ∗ f o r m a t , . . . ) ; i n t f s c a n f ( FILE ∗ s t r e a m , c o n s t c h a r ∗ f o r m a t , . . . ) ;
i n t main ( ) { c h a r c ;
FILE ∗ f p = f o p e n ( ” /tmp/ f i l e . t x t ” , ” r b ” ) ; w h i l e ( f s c a n f ( f p , ”%c ” , &c ) == 1 ) {
p r i n t f ( ”%c ” , c ) ; }
f c l o s e ( f p ) ;
f p r i n t f ( s t d e r r , ” N o t h i n g more i n t h e f i l e ” ) ; f p r i n t f ( s t d o u t , ” P i h a s t h e v a l u e : %.4 f %s ” , M PI , ” \ nSo t h e r e ! \ n ” ) ;
p r i n t f ( ” P r e s s e n t e r t o e x i t :> ” ) ; f f l u s h ( s t d o u t ) ;
s c a n f ( ”%∗s ” ) ; // r e a d a s t r i n g and i g n o r e i t r e t u r n 0 ;
}
Programsystemkonstruktion med C++: ¨Ovning 3 Str¨ommar
Input/Output i C++
i n t main ( ) { c h a r c ;
i s t r e a m i n f i l e ( ” /tmp/ f i l e . t x t ” , i o s b a s e : : b i n a r y ) ; w h i l e ( i n f i l e . g e t ( c ) ) { // c a n n o t u s e i n f i l e >> c
c o u t << c ; // b e c a u s e i t i g n o r e s b i n a r y mode }
c e r r << ” N o t h i n g more i n t h e f i l e ” ;
c o u t << ” P i h a s t h e v a l u e : ” << p r e c i s i o n ( 4 ) <<
M PI << ” \ nSo t h e r e ! ” << e n d l ; c o u t << ” P r e s s e n t e r t o e x i t :> ” ; c o u t . f l u s h ( ) ;
c i n . i g n o r e ( ) ; // r e a d a s t r i n g and i g n o r e i t r e t u r n 0 ;
} // i n f i l e c l o s e d h e r e
#i n c l u d e <i o s t r e a m >
c l a s s A { p u b l i c :
i n t i ;
A ( ) : i ( 0 ) {}
v i r t u a l ˜A ( ) {}
v i r t u a l v o i d d o S t u f f ( ) {}
} ;
c l a s s B : p u b l i c A { p u b l i c :
i n t j ;
B ( ) : j ( 1 ) {}
v o i d d o S t u f f ( ) {}
} ;
s t d : : o s t r e a m& o p e r a t o r <<( s t d : : o s t r e a m &o , c o n s t A &a ) { o << a . i ;
r e t u r n o ; }
s t d : : o s t r e a m& o p e r a t o r <<( s t d : : o s t r e a m &o , c o n s t B &b ) { o << b . i << ’ ’ << b . j ;
r e t u r n o ; }
Programsystemkonstruktion med C++: ¨Ovning 3 Str¨ommar
Problem med arv och str¨ ommar
#i n c l u d e ” ab . h ” u s i n g namespace s t d ;
i n t main ( ) {
A a ; B b ;
A &a R e f = b ; // OK, a i s p u b l i c b a s e o f B c o u t << a << e n d l ;
c o u t << b << e n d l ;
c o u t << a R e f << e n d l ; // hmmm, what w i l l h a p p e n h e r e ? r e t u r n 0 ;
}
#i n c l u d e <i o s t r e a m >
c l a s s A { p u b l i c :
i n t i ;
A ( ) : i ( 0 ) {}
v i r t u a l ˜A ( ) {}
v i r t u a l v o i d d o S t u f f ( ) {}
v i r t u a l s t d : : o s t r e a m& p r i n t ( s t d : : o s t r e a m &o ) c o n s t { o << i ; r e t u r n o ;
} } ;
c l a s s B : p u b l i c A { p u b l i c :
i n t j ;
B ( ) : j ( 1 ) {}
v o i d d o S t u f f ( ) {}
s t d : : o s t r e a m& p r i n t ( s t d : : o s t r e a m &o ) c o n s t { o << i << ’ ’ << j ; r e t u r n o ;
} } ;
s t d : : o s t r e a m& o p e r a t o r <<( s t d : : o s t r e a m &o , c o n s t A &a ) { r e t u r n a . p r i n t ( o ) ;
}