Ohjelmointi 2 2006/ 24.4

Demo C1 vastauksia


1. Esikääntäjä

Ohjelma esikääntäjän jälkeen:
... kaikki se mitä tiedostosta stdio.h jää jäljelle
... kun esikääntäjä on käsitellyt sen, mm. funktioiden prototyypit
int main(void){
int maksu = ==7;; *  (1+40 / 100.0) ;
printf("auto on vanha, mutta halpa: %d!\n",maksu) ;
printf(Tulkaa " kyytiin!" "\n") ;
return 0; }

Virheitä:
HUOM!  Järjestys ei juurikaan haittaa, ks. luentomonisteen
       selostus korvaamisen toiminnasta käyttötaulukon avulla.

#define pois return 0;              - OK jos käytetään varovasti, huono paikka
#include <stdio.h>                  - OK, mielummin alussa
#define HALPA=HINTA;                - ei yleensä = ja ;   
#define auto "Mosse"                - OK, varattu sana ei haittaa
#define Tul "Terve"                 - esiintymässä täytyy olla Tul kaa
#define kaa  "tuloa"                - parempi #define TULKAA "Tervetuloa"
#define TASTA int main(void){       - OK, ei ehkä selkeä
#define TAHAN pois }                - OK, -"-  
#define VAHAN                       - OK, tyhjän voi määritellä
#define PP ;                        - OK, onko järkeä?
#define VEROJA (1+40 prosenttia) PP - OK, jos käytetään kertolaskun kanssa
#define plus *                      - OK?, tosin hämäävä nimi
#define on =                        - OK, joskus voi olla käyttöä
#define HINTA=7;                    - OK, = ja ; yleensä pois
#define lf "\n"                     - OK, ei sotkeudu "%lf":n kanssa
#define prosenttia / 100.0          - OK, mutta vaarallinen jos ei käytetä
                                          "oikein"

Korjattu versio:
#define pois return 0;
#include <stdio.h>
#define HALPA HINTA
#define auto "Mosse"
#define Tulkaa "Tervetuloa"
#define TASTA int main(void){
#define TAHAN pois }
#define VAHAN
#define PP ;
#define VEROJA (1+40 prosenttia) PP
#define plus *
#define on =
#define HINTA 7
#define lf "\n"
#define prosenttia / 100.0

TASTA
  int maksu on HALPA plus VAHAN VEROJA
  printf(auto " on vanha, mutta halpa: %d!\n",maksu) PP
  printf(Tulkaa " kyytiin!" lf) PP
TAHAN
Nyt tulostuisi:
Mosse on vanha, mutta halpa: 9!
Tervetuloa kyytiin!

2. Huoneen mitat

/* huone_a.c */
/* Kysytään huoneen mitat ja lasketaan pinta-ala ja tilavuus  */
/* Jonne Itkonen 2.2.1994                                     */
#include <stdio.h>

void kysy_mitat(double *pituus, double *leveys, double *korkeus)
{
  printf("Anna huoneen pituus, leveys ja korkeus metreissä > ");
  scanf("%lf %lf %lf",pituus,leveys,korkeus);
}

double laske_pinta_ala(double pituus, double leveys)
{
  return  pituus * leveys;
}

double laske_tilavuus(double pinta_ala, double korkeus)
{
  return  pinta_ala * korkeus;
}

void tulosta_pinta_ala(double pinta_ala)
{
  printf("Huoneen pinta-ala on %3.1lf neliömetriä.\n",pinta_ala);
}

void tulosta_tilavuus(double tilavuus)
{
  printf("Huoneen tilavuus on %3.1lf kuutiometriä.\n",tilavuus);
}

int main(void) 
{
  double pituus,leveys,korkeus,pinta_ala,tilavuus;

  kysy_mitat(&pituus,&leveys,&korkeus);
      
  pinta_ala = laske_pinta_ala(pituus,leveys);
  tilavuus  = laske_tilavuus(pinta_ala,korkeus);

  tulosta_pinta_ala(pinta_ala);
  tulosta_tilavuus(tilavuus);

  return 0;
}

3. Huoneen mitat C++:lla

/* huone_a.cpp */
// Kysytään huoneen mitat ja lasketaan pinta-ala ja tilavuus 
// Jonne Itkonen 2.2.1994 /vl 31.1.1996                      
#include <iostream.h>

void desim(int des=0, ostream &os=cout)
{
  os.precision(des); os.setf(ios::showpoint); cout.setf(ios::fixed);
}

void kysy_mitat(double &pituus, double &leveys, double &korkeus)
{
  cout << "Anna huoneen pituus, leveys ja korkeus metreissä > ";
  cin >> pituus >> leveys >> korkeus;
}

double laske_pinta_ala(double pituus, double leveys)
{
  return  pituus * leveys;
}

double laske_tilavuus(double pinta_ala, double korkeus)
{
  return  pinta_ala * korkeus;
}

void tulosta_pinta_ala(double pinta_ala)
{
  desim(1);
  cout << "Huoneen pinta-ala on " << pinta_ala << " neliömetriä" << endl;
}

void tulosta_tilavuus(double tilavuus)
{
  desim(1);
  cout << "Huoneen tilavuus on " << tilavuus <<" kuutiometriä" << endl;
}

int main(void)
{
  double pituus,leveys,korkeus,pinta_ala,tilavuus;

  kysy_mitat(pituus,leveys,korkeus);

  pinta_ala = laske_pinta_ala(pituus,leveys);
  tilavuus  = laske_tilavuus(pinta_ala,korkeus);

  tulosta_pinta_ala(pinta_ala);
  tulosta_tilavuus(tilavuus);

  return 0;
}


4. Osoittimet

int a,b,c;
int *p;
int e;
     
     a=19       p=&b    *p=a+2    p=p+1    *p=7     p=p+2   *p=p-3   **p=199
    +-----+    +-----+  +-----+  +-----+  +-----+  +-----+  +-----+  +-----+  
100 | 19  | a  | 19  |  | 19  |  | 19  |  | 19  |  | 19  |  | 19  |  | 19  |   
    +-----+    +-----+  +-----+  +-----+  +-----+  +-----+  +-----+  +-----+   
102 | ??  | b  | ??  |<+| 21  |<+| 21  |  | 21  |  | 21  |  | 21  |  |199  |<-+
    +-----+    +-----+ |+-----+ |+-----+  +-----+  +-----+  +-----+  +-----+  |
104 | ??  | c  | ??  | || ??  | || ??  |<+|  7  |<+|  7  |  |  7  |  |  7  |  |
    +-----+    +-----+ |+-----+ |+-----+ |+-----+ |+-----+  +-----+  +-----+  |
106 | ??  | p  |102o-+-+|102o-+-+|104o-+-+|104o-+-+|108o-+-+|108o-+-+|108o-+-+|
    +-----+    +-----+  +-----+  +-----+  +-----+  +-----+ |+-----+ |+-----+ ||
108 | ??  | e  | ??  |  | ??  |  | ??  |  | ??  |  | ??  |<+|102  |<+|102o |<+|
    +-----+    +-----+  +-----+  +-----+  +-----+  +-----+  +-----+  +---+-+  |
                                                                         +----+ 

5. Pöytätesti

Jos d = &c-1  =>  d+1 == &c  ja *(d+1) == c
Jos b = &a ja a = 6;  k = ++(*b) =>  ++a eli a = 7 ja k = 7
Jos a=3 ja b=2, niin ( a > b ) => 1 (eli tosi)
                ja ( a > b ) + 5  => 1 + 5 => 6
            
+----------+------------+-------+--------+-------+ 
|          | globaalit  | main  |huijaus |puijaus|
+----------+----+---+---+---+---+---+----+---+---+
|          | *  |   |   |   |   |   | *  |** |   |
|   lause  |  d | c |  u| k1| k2| a |  b |  b| n |
+----------+----+---+---+---+---+---+----+---+---+
|02 int *d |NULL| 4 |  9|   |   |   |    |   |   |
|23 int k1 |&c-1|   |   | 31| 45|   |    |   |   |
|24 k1=huij|    |   |   |   |   | 49|&m.c|   |   |h.a=k2+*(d+1)=45+*(&c)=45+c=49
|06 *(d+1)=| -> | 5 |   |   |   |   | <- |   |   |*(d+1)==*(&c-1+1)==c = ++(c)
|07 c=*b-2 |    | 3 |   |   |   |   | <- |   |   |c = c-2 = 3
|08 *b +=a/|    |27 |   |   |   |   | <- |   |   |*b==c => c+=(int)49/2=24 => c=24+3
|09 return |    |   |   |   |   |   |    |   |   |palautus a>3 => tosi => 1
|24 k1=    |    |   |   |  1|   |   |    |   |   |
|25 k2=puij|    |   |   |   |   |   |    |&d |   |p.b=&d
|14 int n  |    |   |   |   |   |   |    |   | ? |
|15 *b = &u| &u |   |   |   |   |   |    |<- |   |*b = g.d = &u
|16 *d=175 | -> |   |175|   |   |   |    |   |   |*d = u = 175
|17 n = --u|    |   |174|   |   |   |    |   |174|u = 174, n= 174
|18 return |    |   |   |   |   |   |    |   |   |palautus 3*(*b==d)+n => 3 *(&u==d)+n =>3*1+174
|25 k2=    |    |   |   |   |177|   |    |   |   |
|26 printf(| -> |   |   |   |   |   |    |   |   |tulostuu:  174
|27 printf(|    |   |   |   |   |   |    |   |   |tulostuu:       174   27  177    1
|28 return |    |   |   |   |   |   |    |   |   |palauttaa 0
+----------+----+---+---+---+---+---+----+---+---+ 

6. Etumerkki ja vuosiluku

// etuvuosi.cpp
// Ohjelmalla testataan aliohjelmia etumerkki ja kysy_vuosi
// Vesa Lappalainen 12.2.2001
#include <iostream.h>
#include <stdio.h>
#include <string>
using namespace std;
#define VUOSISATA 2000

int etumerkki(double x, double eps)
{
  if ( x < -eps ) return -1;
  if ( x > eps  ) return 1;
  return 0;
}

int kysy_vuosi(int *vuosi)
{
  string s;
  *vuosi = 0;
  cout << "Anna vuosi >"; getline(cin,s);
  sscanf(s.c_str(),"%d",vuosi);
  if ( (*vuosi < VUOSISATA) || (VUOSISATA+100 <= *vuosi) ) return 1;
  return 0;
}

int main(void)
{
  int vuosi;

  cout << etumerkki(-0.1  ,0.01) << "\n";
  cout << etumerkki(-0.001,0.01) << "\n";
  cout << etumerkki( 0.001,0.01) << "\n";
  cout << etumerkki( 0.1  ,0.01) << "\n";

  if ( kysy_vuosi(&vuosi) )
    cout << vuosi << " ei ole tällä vuosisadalla!\n";
  else
    cout << vuosi << " on tällä vuosisadalla!\n";

  return 0;
}


7. Pienimmän paikka ja pienin

/* pienin.c */
/* Etsitään taulukon pienintä lukua /vl-94 */
#include <stdio.h>
#include <limits.h>

int pienimman_paikka(const int luvut[], int koko)
{
  int i,pienin_i,pienin=INT_MAX; /* Varmasti väärä arvaus */
  for (i=0; i<koko; i++)
    if ( luvut[i] < pienin ) {
      pienin   = luvut[i];
      pienin_i = i;
    }
  return pienin_i;
}

int pienin(const int luvut[], int koko)
{
  return luvut[pienimman_paikka(luvut,koko)];
}

int main(void)
{                     /*ta,he,ma,hu,to,ke,he,el,sy,lo,ma,jo*/
  int k_pituudet[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

  int i     = pienimman_paikka(k_pituudet,12);
  int helmi = pienin(k_pituudet,12);

  printf("Paikka %d = %d\n",i,helmi);

  return 0;
}


8. Palindromi

/* pali.c */
/* Tutkitaan onko jono palindormi vaiko ei /vl-94 */
#include <stdio.h>
#include <string.h>

/******************************************************************/
int onko_palindromi(const char jono[])
/* Funktio palauttaa 1 mikäli jono on palindromi
                     0 muuten
-------------------------------------------------------------
Algoritmi:
  Aloitetaan jonon 1. ja viimeisestä kirjaimesta
  Verrataan ko. kirjaimia
    Jos erit, niin lopetetaan, ei ole
    muuten siirrytään yksi sisäänpäin ja jatketaan
    vertaamista kunnes kaikki kirjaimet testattu
  Oli palindromi

  0.  alku = 0, loppu = jonon pituus-1
  1.  jos alku >= loppu niin palauta OLI
  2.  jos kirjaimet paikoissa alku ja loppu erit, niin
      palauta EI OLLUT
  3.  alku=alku+1 ja loppu=loppu-1
  4.  jatka 1
  5.  palauta OLI
-------------------------------------------------------------
*/
#if 0 /* Joko indekesillä: */
{
  int alku=0,loppu=strlen(jono)-1;

  while ( alku < loppu ) {
    if ( jono[alku] != jono[loppu] ) return 0;
    alku++;
    loppu--;
  }
  return 1;
}
#elif 0 /* Tai osoittimilla normaalisti: */
{
  const char *alku  = jono,
             *loppu = jono+strlen(jono)-1;

  while ( alku < loppu ) {
    if ( *alku != *loppu ) return 0;
    alku++;
    loppu--;
  }
  return 1;
}
#else /* Tai osoittimilla C-mäisesti: */
{
  const char *alku = jono,*loppu = jono+strlen(jono)-1;
  while ( alku < loppu ) if ( *alku++ != *loppu-- ) return 0;
  return 1;
}
#endif

int main(void)
{
  printf("Onko %d\n",onko_palindromi("saippuakauppias"));
  printf("Onko %d\n",onko_palindromi("shamppookauppias"));
  return 0;
}


// pali.cpp // Aliohjelma joka tutkii on C++-merkkijono palindromi vai ei // Vesa Lappalainen 27.4.2003 #include <string> #include <iostream> using namespace std; int onko_palindromi(const string &jono) { int alku=0,loppu=jono.length()-1; while ( alku < loppu ) { if ( jono[alku] != jono[loppu] ) return 0; alku++; loppu--; } return 1; } int main(void) { string jono = "abba"; cout << "Onko " << onko_palindromi(jono) << endl; cout << "Onko " << onko_palindromi("kissa") << endl; return 0; }

9 Poista_lopusta

// poista_l.cpp
// Aliohjelmia merkkijonojen käsittelyyn/vl-98

#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include <string>

char *poista_lopusta(char *jono,int lkm)
{
  int pit = strlen(jono);
  if ( lkm <= 0 ) return jono;
  if ( pit < lkm ) jono[0] = 0;
  else jono[pit-lkm] = 0;
  return jono;
}

string &poista_lopusta(string &jono,int lkm)
{
  int pit = jono.length();
  if ( lkm <= 0 ) return jono;
  if ( pit < lkm ) jono = "";
  else jono.erase(pit-lkm,lkm);
  return jono;
}

int main(void)
{
  char jono[20] = "Kissa istuu";
  printf("Poiston jälkeen |%s|\n",poista_lopusta(jono,3));
  printf("Poiston jälkeen |%s|\n",poista_lopusta(jono,5));
  printf("Poiston jälkeen |%s|\n",poista_lopusta(jono,5));
  printf("Poiston jälkeen |%s|\n",poista_lopusta(jono,5));
  string st("Kissa istuu");
  cout << "Poiston jälkeen |" << poista_lopusta(st,3) << "|" << endl;
  cout << "Poiston jälkeen |" << poista_lopusta(st,5) << "|" << endl;
  cout << "Poiston jälkeen |" << poista_lopusta(st,5) << "|" << endl;
  cout << "Poiston jälkeen |" << poista_lopusta(st,5) << "|" << endl;
  return 0;
}

10. Taulukosta poistaminen

/* poista.c */
/* Esimerkki alkioiden poistamiseksi taulukosta/ vl-96 */
#include <stdio.h>

int poista(int taulukko[],int lkm,int n)         /* indekseillä */
{
  int luku,kirj;
  for (luku=0,kirj=0; luku<lkm; luku++)
    if ( taulukko[luku] != n )
      taulukko[kirj++] = taulukko[luku];
  return kirj;
}

int poista_p(int taulukko[],int lkm,int n)       /* osoittimilla */
{
  int *luku,*kirj;
  for (luku=taulukko,kirj=taulukko; luku<taulukko+lkm; luku++)
    if ( *luku != n )
      *kirj++ = *luku;
  return (int)(kirj-taulukko);
}

int main(void)
{
  int t[]={4,5,7,3,7,2}, lkm=6, i;

  lkm = poista(t,lkm,7);
  for (i=0; i<lkm; i++)
    printf("%4d ",t[i]);
  printf("\n");
  return 0;
}