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;
}