Kihagyás

2. gyakorlat

Fejlesztői környezet

Szövegszerkesztő

Amikor elkezdünk programozni, akkor amire biztosan szükségünk lesz az egy szövegszerkesztő. Fontos, hogy olyan szövegszerkesztőt használjunk, amit nem formázott szöveg szerkesztésére terveztek (MS Word, OpenOffice Writer, stb. kizárva), hanem egyszerű (plain text) szövegek írására.

Linux és Windows alatt használható néhány szövegszerkesztő:

Miután kiválasztottuk a számunkra megfelelő szövegszerkesztőt, mellyel a programokat fogjuk írni, szükségünk lesz egy fordítóprogramra is, amivel a forráskódból futtatható (bináris) állományt hozunk létre. Ilyen például a gcc (GNU Compiler Collections), ami alapvetően Linux alatt érhető el, de Windows-ra is felvarázsolható (MinGW).

Megjegyzés

Az előre telepített image-en már van gcc telepítve, így aki azt használja nyugodtan ugorja át a következő részeket!

gcc telepítés Linux alatt

  1. Nyiss egy terminált!
  2. sudo apt update
  3. sudo apt install build-essential
  4. sudo apt-get install manpages-dev
  5. gcc --version

A 2. sor frissíti a telepíthető csomagok listáját, a 3. sorban telepítjük a fejlesztéshez szükséges alapvető eszközöket, melyek között a gcc is megtalálható. A 4. sor opcionális jellegű, de hasznos lehet, mivel felhasználói kézikönyvet (manual) telepíti a fejlesztőeszközökhöz, azaz a gcc-hez is. Az utolsó sorral validálhatjuk, hogy a gcc valóban telepítésre került. Valamilyen hasonló kimenetet kell kapnunk:

Kimenet

1
2
3
4
gcc (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

gcc telepítés Windows alatt

Ehhez egy kicsit több lépésre van szükségünk.

  1. lépés: MinGW (Minimalist GNU for Windows) telepítése

    Töltsük le a MinGW Installer-t, majd alapbeállításokkal telepítsük a rendszert! Én a telepítőben a C:\MinGW könyvtárat adtam meg, így a továbbiakban ezt használom majd. Amennyiben valaki ezt máshová adta meg, az majd az útvonalakat ennek függvényében módosítsa.

  2. Amikor a MinGW elindult (ha nem indult el magától akkor MinGW Installation Manager-t kell keresned), bal oldalon válaszd a "Basic Setup"-ot, és mellette jobbra jelöld ki mingw32-base-bin csomagot (Mark for installation)!

  3. Ezután menüben válaszd ki az Installation -> Apply Changes -> Apply pontot!
  4. Ezután, ha elnavigálunk a telepítési könyvtárba, ami C:\MinGW volt, akkor ott látnunk kell egy bin könyvtárat, melyben megtalálható a gcc.exe állomány.
  5. Annak érdekében, hogy ne kelljen mindig abszolút útvonallal meghívni a gcc-t, adjuk hozzá a PATH környezeti változóhoz (a PATH változó adja meg azon útvonalak halmazát, ahol a rendszer keresi a futtatható programokat a kiadott parancsoknak megfelelően) ezt a telepítési helyet!
  6. Windows gomb -> "A rendszer környezeti változóinak módosítása" -> "Környezeti változók" gomb -> "Rendszerváltozók" (ha nincs rendszergazdai jogod, akkor fenti "xyz felhasználói változói") alatt keresd meg a Path-ot és jelöld ki, majd Szerkesztés... -> Új -> Másold be a C:\MinGW\bin\ elérési utat -> OK
  7. Teszteléshez nyiss egy új parancssort (Windows -> cmd -> ), majd írd be, hogy gcc --version!
  8. Az alábbi kimenethez hasonlót kell kapnod:

    Kimenet

    1
    2
    3
    4
    gcc (MinGW.org GCC Build-2) 9.2.0
    Copyright (C) 2019 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    

IDE (Integrated Development Environment)

Az egyszerű szövegszerkesztők mellett léteznek úgynevezett IDE-k (Integrated Development Environment), melyek megkönnyíthetik a fejlesztést (inkább nagyobb projektek esetében), mivel automatikus kódkiegészítést, IDE-n belüli fordítást és futtatást is lehetővé tesznek, illetve ezen felül rengeteg extra műveletet kínálnak még. Ha valamilyen IDE mellett döntünk, nagy valószínűséggel akkor is fel kell telepítenünk egy fordítót, mert az IDE alapból azt nem adja, csak használja.

IDE-k C programozáshoz:

Az említett IDE-k szintén telepítve vannak a kiadott Ubuntu VM image-ben. Természetesen magunk is telepíthetjük őket, ha szeretnénk.

C alapok

Mielőtt beleugrassz a gyakorlati részekbe hasznos lehet, ha elolvasod az előadáshoz tartozó jegyzet idevágó részét.

Első lépések

Első dolgunk, hogy megnyitjuk a kedvenc szövegszerkesztőnket vagy az IDE-t, amit használni szeretnénk a fejlesztéshez. Hozzunk létre egy új szöveges állományt, melynek kiterjesztése .c legyen! Legyen a fájl neve például progalap.c! Ezután már írhatjuk is a C nyelvű programjainkat.

Ahogy a legtöbb programozási nyelv, úgy a C nyelv is támogatja a kommentek írását, melybe mindenféle hasznos megjegyzést rakhatunk anélkül, hogy az a program működését befolyásolná.

Két fajtája létezik:

  • egysoros (line comment): ami a // után van az adott sorban az komment lesz
  • többsoros (block comment): amit /*...*/ közé írunk, azok a blokk komment részei lesznek
1
2
3
4
5
6
7
//  Ez egy egysoros komment, azaz bármilyen magyarázó szöveg kerülhet ide
/*
    Ez egy többsoros komment,
    tehát több son keresztül írhatok
    mindenféle haszontalan dolgot
    csak hogy szaporodjanak a bájtok.
*/

Minden programnak van valamilyen belépési pontja, azaz valahol el kell kezdeni a program futtatását. Például, amikor kiadjuk Linux alatt az ls parancsot - amely szintén egy program - akkor valahol elkezdődik a program futtatása. C-ben a programok belépési pontja a main függvény. Egyelőre nem fontos, hogy mi az a függvény és miért van main elé az írva, hogy int. Egyelőre fogadjuk el, hogy elé int-et írunk, utána rakunk egy zárójelpárost, amibe nem kell most még semmit se írni. Azt, hogy mit csináljon a program a main függvény törzsében adjuk meg, azaz a {...} jelek között. Nézzük is meg, hogy hogyan néz ki egy nagyon egyszerű program, ami igazából nem is csinál semmit.

1
2
3
4
5
6
/*
    main függvény, ez a függvény fog lefutni először
*/
int main() {
    return 0;
}

A main-en belül most a return 0 utasítás szerepel. A return egy utasítás, melyet a függvényeken belül adhatunk ki, és segítségükkel valamilyen értéket adhatunk vissza az őket meghívóknak. A main függvényt maga az operációs rendszer hívja meg, így a return 0 eredményeképpen ez a program 0-t ad vissza az operációs rendszernek, ami megegyezés szerint azt jelenti, hogy a programunk sikeresen lefutott. 0-tól különböző visszatérési értéket szokás használni arra, ha valamilyen hibát szeretnénk jelezni az operációs rendszer felé.

A fenti C kód csak maga a forrás. Ezt még nem tudjuk lefuttatni, előtte le kell fordítani olyan nyelvre, amelyet megért a számítógép (közvetlenül végre tud hajtani). Ezt a melót végzik el a fordítóprogramok (igen ezek is programok), mint amilyen például a gcc.

Így néz ki Linux alatt (terminalban) a gcc-vel történő fordítás:

1
$ gcc -o prog progalap.c

és futtatás:

1
$ ./prog

Az első parancsban a gcc-nek megmondjuk, hogy a progalap.c állományt szeretnénk lefordítani, illetve a -o prog kapcsolómegadással azt fejezzük ki, hogy a kimeneti futtatható állomány neve prog legyen. A második paranccsal futtatjuk az aktuális könyvtárban lévő prog programunkat, mely jelen esetben nem csinál semmit, így vissza is kell kapnunk egyből a command prompt-ot ($-al kezdődő szöveg a terminálon), amellyel jelzi az operációs rendszer, hogy kész fogadni az utasításainkat.

Megjegyzés

A fordítás menetét részletesen lásd itt!

Megjegyzés

Ha nem a fenti elvárt viselkedést tapasztaljuk és még fordítás közben valamilyen hibát kapunk, akkor alaposan nézzük meg, hogy mindent helyesen írtunk-e be!

A legegyszerűbb C nyelvű program megírását mutatja be az alábbi videó is:

Legegyszerűbb C program

Minden programozási nyelv tanulása során az első feladatok közé tartozik, hogy írjunk egy olyan programot, ami kiírja a "Hello World" szöveget a képernyőre. Ez a szokás Brian Kernighan, "Programming in C: A Tutorial" könyvéből eredeteztethető, aki nem mellesleg a C nyelv egyik megalkotója. Tehát nincs más választásunk, meg kell írni ezt a programot.

A programozás és maga a szoftverfejlesztés nem tartana ott ahol, ha nem használnánk fel már megírt kódokat. Ilyen előre megírt kódot biztosítanak a szabványos függvénykönyvtárak is. C-ben a standard input/output műveleteket már nem kell magunknak megírnunk, hanem elég az stdio (standard input/output) szabványos függvénykönyvtárat használnunk, pontosabban ebből most egy függvényt fogunk felhasználni mégpedig a printf-et.

A standard függvénykönyvtárak használatához a következőt kell a programunkba illesztenünk:

1
2
3
4
#include <stdio.h>
/*
    Ezek után használhatjuk a scanf és printf I/O függvényeket
*/

Az #include mondja meg, hogy ide emeljük be az stdio.h (header)fájl tartalmát, amiben a printf függvény deklarációja is található. Ezek után nézzük meg a teljes "Hello World" program kódját!

1
2
3
4
5
6
#include <stdio.h>

int main() {
    printf("Hello World!\n");
    return 0;
}

Kimenet

1
Hello World!

Ebben a kódban a printf() függvényt hívjuk meg, melyet azzal jelzünk, hogy a függvény neve mögé kitesszük a kerek zárójelpárt, amik között az argumentumokat adhatjuk meg. A printf argumentuma az a szöveg, amit ki kell írnia a képernyőre. Ezt a szöveget idézőjelek közé kell tennünk. Itt meg is adjuk a "Hello World" szöveget, azonban van utána egy furcsa \n is. Mivel az idézőjelek között nem tudunk Enter-t megadni (ez fordítási hibát okozna), ha a kiírásban valahol - jelen esetben a "Hello World" szöveg után - sortörést szeretnénk csinálni, azt máshogy tudjuk jelezni. (Ha nem lenne sortörés, akkor a Hello World után jelenne meg a command prompt, és nem új sorban.) Konkrétan a printf paraméterében (melyet formátumsztring-nek is neveznek) egy \n-nel tudjuk jelezni a sortörést (és más speciális karakterkombinációkkal az egyéb speciális, úgynevezett vezérlő karaktereket).

Mint ahogyan az már kezd kirajzolódni, az utasításaink (printf, return) után mindig kell egy pontosvesszőt raknunk. Ezzel zárjuk az utasításokat. Egyelőre ízlelgessük a szintaxist.

A helloworld program fordítása és futtatása:

1
2
$ gcc -o hello helloworld.c      # fordítás
$ ./hello                        # futtatás

HelloWorld program videóban bemutatva:

Hello World

Feladat (f0002)

Feladat:

Írj egy olyan C programot, ami kiírja, hogy "Hello Vilag!"! Készíst belőle egy hello nevű futtathatót először egy, majd két lépésben (helloworld.o objekten keresztül), és futtasd!

Problémafelvetés:

Írj egy olyan C programot, ami kiírja, hogy "Hello Vilag!"!

Specifikáció:

A programnak nincs inputja. A program outputja a "Hello Vilag!" szöveg egy lezárt sorban.

Megoldás (m0002.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program egyetlen kiírató utasítást tartalmaz, melynek paramétere a
 *    kiíratandó szöveg.
 *
 * Megvalósítás:
 *    A sor lezárását a szöveg végén a "\n" biztosítja!
 *
 * fordítás egy lépésben:
 *    gcc -o hello m0002.c
 *
 * futtatás:
 *    ./hello
 *
 * fordítás két lépésben:
 *    gcc -c -o helloworld.o m0002.c
 *    gcc -o hello helloworld.o
 *
 * futtatás:
 *    ./hello
 */

#include <stdio.h>

main() {
    printf("Hello Vilag!\n");
}

Feladat (f0003)

Feladat:

Írj egy olyan C programot, ami kiírja, hogy "Hello Vilag!"! Javítsd ki a programot, hogy fordításkor ne legyen benne warning -Wall kapcsolóval sem! Futtasd!

Problémafelvetés:

Írj egy olyan C programot, ami kiírja, hogy "Hello Vilag!"!

Specifikáció:

A programnak nincs inputja. A program outputja a "Hello Vilag" szöveg egy lezárt sorban.

Megoldás (m0003.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program egyetlen kiírató utasítást tartalmaz, melynek paramétere a
 *    kiíratandó szöveg.
 *
 * Megvalósítás:
 *    A sor lezárását a szöveg végén a "\n" biztosítja! Mivel a feladat
 *    szerint warning-mentes programot kell írni, a main metódusnak megadjuk
 *    a típusát, és a return utasítás segítségével explicit módon vissza is
 *    adunk egy értéket, ami jelen esetben 0, vagyis a program hibátlan
 *    lefutását jelzi az operációs rendszer felé.
 *
 * fordítás:
 *    gcc -Wall -o m0003 m0003.c
 *
 * futtatás:
 *    ./m0003
 */

#include <stdio.h>

int main() {
    printf("Hello Vilag!\n");
    return 0;
}

Szekvenciák

Minden utasítást pontosvessző (";") zár. Ha nem teszünk pontosvesszőt, akkor kifejezésről beszélünk. Kifejezés - egy érték olyan jelölése, amely műveleteket is tartalmazhat, pl.: 3 + 5. Utasítások sorozatát szekvenciának nevezzük.

Példa:

1
2
3
4
main() {
    3 + 5   // kifejezés, a pontosvessző hiánya miatt ez így fordítási hiba
    3 + 5;  // utasítás
}

Változók használata

Minden programozási nyelvben szükség van arra, hogy valamilyen adatokon tudjunk műveleteket elvégezni. Az adatokat a program futása közben a memóriában tárolhatjuk. A programban deklarálhatunk változókat, azaz kérünk egy kis szeletet a memóriából, hogy abban majd számunkra valamilyen hasznos adatot tudjunk tárolni. Attól függően, hogy milyen jellegű adatot szeretnénk benne tárolni másképpen kell a memóriaterületet elkérni az operációs rendszertől (különböző mennyiségű bit-et kaphatunk egy egész szám tárolásához, mint egy valós szám tárolásához).

Az adattárolásról bővebben majd a előadás adatkezelés szintjeiről és elemi adattípusokról szóló részében lesz szó.

Vizsgáljuk meg a következő kódrészletet, melyben különböző deklarációkat láthatunk.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void main() { // csak a demonstráció kedvéért, a main() függvény típusa int

    // void - Ez egy adatot tárolni képtelen típus, többek között eljárásokhoz használatos
    int egesz;  // Egy "egyszavas" (esetünkben 32 bites - 4 bájtos) előjeles egész szám
                // Műveletek: +, -, *, /, %, ahol a / az egészosztás egészrésze,
                // a % az egészosztás maradéka
    char karakter;  // Egy egybájtos, előjeles, vagy előjeltelen egész szám. Jól használható
                    // szöveges karakterek tárolására is, ascii-kód segítségével.
    float valos1;   // Egy egyszavas lebegőpontos szám
                    // Műveletek: +, -, *, /
    double valos2;  // Annyiban különbözik a float-tól, hogy 8 bájtos
    // Logikai és szöveges típus külön nincs, azokat máshogy kell megvalósítani.
    // (Későbbi gyakorlaton látni fogjuk.)
}

Miután deklaráltuk a változónkat, a hozzárendelt memóriaterületre értékeket is elhelyezhetünk, azaz tárolni tudjuk az adatot. Amikor értéket is adunk egy változónak, akkor definiáljuk azt (változó definíció). Nézzük meg az alábbi kódrészletet, melyben az alap típusú változóknak értékeket is adunk a deklarációval egy időben, azaz kezdőértékkel látjuk el a változókat (inicializáljuk őket).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void main() {

    int egesz = 2014;
    char karakter = 'A'; // Karakterek megadásakor (és mint láttuk/később látjuk, szövegekben
                         // is) használhatunk escape-szekvenciákat, pl.: \" - idézőjel,
                         // \' - aposztróf, \t - tabulátor, \n - soremelés (új sor),
                         // \r - kocsi-vissza
    float valos1 = 3.1415916;   // természetesen a float és double is tud tárolni sokkal
                                // nagyobb számokat is (ezekről későbbi gyakorlaton lesz szó)
    double valos2 = 3.1415916;  // hogy pontosan miben is különbözik a 4 és a 8 bájton való
                                // tárolás, arról is később lesz szó
}

Videó egyszerű változó deklarációról:

Változó deklaráció

Egyszerű műveletek

Miután már vannak változóink is, valószínűleg szeretnénk velük valamilyen műveleteket elvégezni. A matematikában megszokott összeadás (+), kivonás (-), osztás (/), szorzás (*) mellet van maradékos osztás (%) alapműveletünk is. A zárójelezést szintén a megszokott módon használhatjuk.

Két szám összegét kiszámító program:

Két szám összege

Az alapműveletek használatát bemutató program:

Alapműveletek

Konstansok

A változók mellett előfordulhat, hogy konstans értékekkel (értéke állandó) szeretnénk dolgozni. Ilyen állandó értékek megadására használhatjuk a define preprocesszor utasítást. A konstansok nevét általában csupa nagy betűvel írjuk, így amikor találkozunk velük a kódban, már ránézésre tudjuk, hogy egy állandóról van szó. Példa:

1
2
3
4
5
6
7
8
#define PI 3.14159265358979323

int main() {
    double radius = 10.0;
    double area = radius * radius * PI;  // PI helyére behelyettesítődik a "3.14159265358979323" érték

    return 0;
}

A define a preprocessálás ideje alatt fut és egyszerű szöveges behelyettesítést végez, szóval teljesen legálisan csinálhatunk huncutságokat (mármint a fordító nem fog érte szólni, viszont készüljünk fel a mérges kollégákra):

1
#define 1 0 

Túlcsordulás

Az elemi adattípusoknál látható, hogy az egyes típusok milyen értékhatárok között képesek tárolni az értékeket. Amikor az értékhatár aljánál "lejjebbi", azaz kisebb értéket szeretnénk beállítani, akkor a bitjeink nem tudnak hirtelen megsokasodni, hogy kisebb számot is képesek legyenek tárolni, így nincs más választásuk, mint "átbillenek" és az intervallum tetejére kerülünk. Ilyen esetben beszélünk alulcsordulásról, illetve a fordított esetben, amikor felfelé szaladunk ki az értéktartományból, akkor felülcsordulással van dolgunk. Magát a jelenséget általánosságában túlcsordulásnak nevezzük.

Példa:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <stdio.h>
#include <limits.h>

int main(){
    int val = INT_MAX; // limits.h-ban van deklarálva ez a konstans
    printf("val = %d\n", val);

    val++;  // ugyanaz, mint val = val + 1, ami ugyanaz, mint val += 1
    printf("val = %d\n", val);

    return 0;
}

Kimenet

1
2
val = 2147483647
val = -2147483648

A túlcsordulás jelenségét az alábbi videó is bemutatja:

Túlcsordulás

Input/Output alapok

printf

A "Hello World" programban már használtuk a kiíratásra használatos függvényt, a printf-et. Most, hogy már ismerjük a változókat, a következő feladat az, hogy valamilyen formában képesek legyünk a változók aktuális értékét kiírni a képernyőre. Vizsgáljuk meg a következő kódrészletet!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>      // <---- printf miatt szükséges ez az include

int main() {

    /* Változók deklarálása és definiálása */
    int egesz = 2014;
    char karakter = 'A';
    float valos1 = 3.1415916;
    double valos2 = 3.1415916;

    /* Kiíratás képernyõre */
    /* % + "adott típus jelző karakter(ek)" kombináció helyére fog behelyettesítődni,
       a szöveg után megadott változó értéke. Ügyeljünk a típusra! */
    printf("Egyszerű szöveg\n");
    printf("Integer érték: %d\n", egesz);   // %d - int
    printf("Karakter: %c\n", karakter);     // %c - char
    printf("Float érték: %f\n", valos1);    // %f - float
    printf("Double érték: %lf\n", valos2);  // %lf - double
    printf("%s\n", "Szöveg, mint \"string\"\n");
    return 0;
}

A fenti kódban azt láthatjuk, hogy a printf első argumentumában, a formátumsztringben szerepelnek % jelek. Így adhatjuk meg, hogy az adott helyre majd valamilyen változó (vagy kifejezés) értékét helyettesítse a rendszer. Pl: a %d jelenti azt, hogy "ide majd egy egész számot írj ki decimális formában". Hogy pontosan mi lesz ez a szám, azt a printf további argumentumaiban adhatjuk meg (az argumentumokat vesszővel választjuk el egymástól). Ez azt is jelenti, hogy egy printf-ben több változó/kifejezés értékét is kiírhatjuk. Például a egesz változó és annak duplájának kiírására használhatnánk a következő utasítást:

1
printf("Integer érték: %d, melynek duplája: %d\n", egesz, egesz * 2);

Videó az alapvető típusokról és ilyen típusú változók értékeinek kiírásáról:

Alapvető típusok

C nyelvben a printf függvény formátumsztringjében a % és lf közé a.b alakban írt két egész számmal vezérelhetjük a valós számok kiíratásának "szélességét" és "pontosságát". Az a jelenti, hogy összesen legalább hány karakteren szélességben legyen kiírva a szám, a b pedig a tizedesjegyek számát jelenti. Ha az a elmarad, akkor a .b alak csak a tizedesjegyek számát fixálja, de minimális "szélességet" nem mond. Pl:

1
2
3
printf("%10.3lf", 42.7); => "    42.700"
printf("%10.0lf", 42.7); => "        43"
printf("%.2lf", 42.7);   => "42.70"

Feladat

  • Kezdj új programot!
  • Hozz létre három változót, int, float és char típusúakat!
  • A programban adj értékeket ezeknek a változóknak!
  • printf paranccsal írasd ki a változók értékét magyarázó szöveggel, mindet új sorban!
  • printf paranccsal írasd ki az int és a float típusú változó összegét magyarázó szöveggel, új sorban!
  • printf paranccsal írasd ki a char változót, mintha int lenne. Működik? Miért? Hogyan?
Lehetséges megoldás
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main() {
    int i = 10;
    char c = 'A';
    float f = 5.123146932;

    printf("Az egesz erteke: %d\n", i);
    printf("A karakter erteke: %c\n", c);
    printf("A lebegopontos szam erteke: %f\n", f);

    printf("int es float osszege = %f\n", i + f);

    printf("a char erteke decimalisan: %d\n", c);

    return 0;
}

Az utolsó két printf kicsit trükkösebb. Egy egész és egy valós típusú változó összege (igazából a közöttük végzett bármilyen értelmes alapművelet) eredménye valós típusú lesz, így azt %f-fel kell kiíratni.

A másik trükk a karakter kiírása, amiben igazából nincs semmi trükk csak azt fontos megértenünk, hogy a memóriában bináris formában kerülnek tárolásra az adatok, így a karakterek is. Egészen pontosan egy karakter tárolására 1 bájtot, azaz 8 bitet kapunk, ami 256 (\(2^8\)) különböző értéket vehet fel. Ezek az értékek vannak megfeleltetve az egyes karaktereknek (általánosságában a karakterek számmal való reprezentációját hívjuk karakter kódolásnak). A C nyelv alapból az ASCII kódolás kódolást használja.

Feladat (f0005)

Problémafelvetés:

Deklarálj egy valós, egy karakter és két egész típusú változót! Inicializáld a valós értéket 3.14 -re, a karaktert a nagy A karakterre, és művelettel adj értéket a két egész változónak is. Írasd ki a változók értékeit, valamint a két egész változó összegét és szorzatát is!

Specifikáció:

A programnak nincs inputja. A program outputja külön-külön sorokban az "A", a 3.1415 érték lebegőpontos alakban tetszőleges pontossággal, egy-egy tetszőleges egész érték, valamint a két egész érték összege és szorzata (a+b)=c és (a*b)=d alakban. Vagyis összesen 6 sor.

Megoldás (m0005.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program egyetlen kiírató utasítást tartalmaz, melynek paraméterei a
 *    kiíratandó értékek.
 *
 * Megvalósítás:
 *    A formátumsztringben sorban egy valós szám (%lf), egy karakter (%c),
 *    két egész szám (%d), valamint további 6, megfelelő környezetbe
 *    helyezett egész szám kiíratását jelezzük. Az értékeket kifejezésként,
 *    a korábban deklarált változókat felhasználva adjuk át. A sorok
 *    lezárását most is a megfelelően elhelyezett "\n"-ek biztosítják!
 *
 * fordítás:
 *    gcc -Wall -o m0005 m0005.c
 *
 * futtatás:
 *    ./m0005
 */

#include <stdio.h>

int main() {
    double f = 3.14; // inicializálás
    char  c = 'A';   // inicializálás
    int   a, b;      // nincs inicializálás
    a = 7;           // értékadás
    b = 12;          // értékadás
    printf("%lf\n%c\n%d\n%d\n(%d+%d)=%d\n(%d*%d)=%d\n",
    /*      \|/  \|  \|  \|   \| \|  \|   \| \|  \|   */ 
             f,   c,  a,  b,   a, b, a+b,  a, b, a*b);
    return 0;
}

A következő programka is azt hivatott illusztrálni, hogy a különböző típusú adatokat hogyan írhatjuk ki és az milyen hatással lesz a kiírás eredményére. Próbáld ki a programot!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <stdio.h>

int main() {

    // Egész egészként és karakterként
    printf("%d\n", 65);
    printf("%c\n\n", 65);       // az ASCII tábla szerint a 65. karakter az 'A'
    // Valós valósként és egészként
    printf("%f\n", 65.5555);
    printf("%d\n\n", 65.5555); // egészként kiíratva egy valós számot
                               // nem épp a helyes eredményt kapjuk meg 
    // Karakter karakterként és egészként
    printf("%c\n",'A');
    printf("%d\n",'A'); // az ASCII tábla szerint ismét csak az 'A' karakterkódja 65
    return 0;
}

scanf

Az adatok kiírása mellett egy másik fontos opció, hogy a felhasználótól adatokat kérjünk be. A printf "párja" a scanf, mely nagyon hasonló paraméterezéssel működik, de beolvasáshoz használjuk. Nézzünk is egy példát!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main() {

    int egesz;
    float valos1;
    double valos2;

    /* Adatok bekérése */
    printf("Adj meg egy egész számot:\n");
    scanf("%d", &egesz);
    printf("Adj meg két valós számot (Üss Enter-t a két szám bevitele között):\n");
    scanf("%f", &valos1);
    scanf("%lf", &valos2);
    printf("\n\n");
    return 0;
}

A scanf első argumentuma szintén a formátumsztring, ahol a printf-nél megszokott placeholderek (%<valami>) használhatóak. A további argumentumok pedig ezeknek a placeholdereknek mondják meg, hogy akkor hova is tegyék az adatot. Például a 11. sorban az egesz változóba helyezzék el a beolvasott értéket. Azt egyelőre fogadjuk el, hogy a scanf-nél kell az & a változó neve elé, későbbi gyakorlaton meg fogjuk érteni, hogy ez miért is szükséges. Most olvassuk úgy a kódot, hogy: "Olvass be egy értéket a xy változóba"!

Videó a scanf alapvető használatáról:

scanf_alap

Ahogy egyszerre több adatot is ki tudtunk írni egy printf segítségével, úgy igaz ez a scanf-re is.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>

int main() {

    int st, rd;     // egész típusú változók
    char nd, th;    // karakter típusú változók

    printf("Beolvasás (egész karakter egész karakter): ");
    scanf("%d%c%d%c", &st, &nd, &rd, &th); // Egyszerre több dolgot is beolvashatunk, de
                                           // ezzel vigyázzunk! A scanf-nek lelke van!
    printf("first = %d; second = '%c'; third = %d; fourth = '%c';\n", st, nd, rd, th);
    return 0;
}

scanf használatáról egy másik bővebb videó, ahol némi anomáliát is felfedezhetünk:

scanf_base_types

Feladat

Írj egy programot amely bekéri a születési dátumodat, kiszámítja a korodat (idén hányadik évedet töltöd be), és ezt kiírja a képernyőre!

Feladat (f0006)

Problémafelvetés:

Kérj be két egész számot, cseréld meg, majd írd ki őket!

Specifikáció:

A program inputja két egész szám. A program outputja a két bekért egész érték egy sorban, egy szóközzel elválasztva, a bevitelhez képest fordított sorrendben.

Megoldás (m0006.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program először bekéri a két egész számot, majd az m segédváltozón
 *    keresztül megcseréli a változók értékeit, végül kiíratja a két
 *    változót. A változókat a beolvasás sorrendjében írjuk ki, hiszen az
 *    értékcsere miatt a beolvasott értékek így lesznek megfordítva.
 *
 * Megvalósítás:
 *    A beolvasás formátumsztringjében két, whitespace karakterrel (ezt
 *    jelzi a szóköz) elválasztott egész érték egész változóba történő
 *    beolvasását jelezzük.
 *
 * fordítás:
 *    gcc -Wall -o m0006 m0006.c
 *
 * futtatás:
 *    ./m0006
 */

#include <stdio.h>

int main() {
    int a, b, m;              // nincs inicializálás
    scanf("%d %d", &a, &b);   // beolvasás
    m = a;                    // csere
    a = b;
    b = m;
    printf("%d %d\n", a, b);  // kiíratás
    return 0;
}

Feladat (f0007)

Olvass be egy egész, egy valós és egy karakter értéket, majd írasd ki őket! Mi történik, ha különféle értékeket próbálsz meg egy sorban megadni? Mit olvas be a program, és mit nem? Próbáld ki a következő inputokat:

1
2
3
4
100 100.200 X
100 100 100
100.200 100.200 100.200
X X X

Problémafelvetés:

Olvass be egy egész, egy valós és egy karakter értéket, majd írasd ki őket.

Specifikáció:

A program inputja egy-egy whitespace karakterrel elválasztott egész, valós és karakter érték. A program outputja külön-külön sorokban a beolvasott egész, (lebegőpontos alakban tetszőleges pontossággal kiírt) valós valamint karakter értékek.

Megoldás (m0007.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program először bekéri az értékeket, majd külön sorokban kiírja
 *    őket.
 *
 * Megvalósítás:
 *    A formátumsztringben sorban egy egész szám (%d), egy valós szám (%lf)
 *    és egy karakter (%c) beolvasását jelezzük.
 *
 * fordítás:
 *    gcc -Wall -o m0007 m0007.c
 *
 * futtatás:
 *    ./m0007
 */

#include <stdio.h>

int main() {
    int    a = 2015;
    double f = 3.14;
    char   c = '#';
    scanf("%d %lf %c", &a, &f, &c);
    printf("%d\n%lf\n%c\n", a, f, c);
    return 0;
}

Rajzoló program (grafika)

A fejlesztés során lehetőségünk van mások által megírt programrészleteket használni a saját programjainkban. Ebben az a jó, hogy egyrészt ezeket nem nekünk kell megírni, másrészt igazából a belső működésükkel sem szükséges tisztában lennünk, elég ha tudjuk, hogy milyen függvényeket használhatunk és azoknak mi az eredménye (mit csinálnak, mi a visszatérési értékük).

Korábban találkoztunk már az stdio.h header fájllal, amit include-olnunk kellett ahhoz, hogy használni tudjuk a printf és scanf függvényeket.

A header fájlok (többnyire) függvénydeklarációkból állnak, vagyis csak azt mondják meg, hogy milyen nevű függvényt hogyan lehet felparaméterezni, és mivel tér vissza, de magát a működést (itt még) nem írják le. Minden header fájlhoz tartozik egy (vagy több) forrásfájl is, amely tartalmazza a függvények definícióit, tehát már leírja a függvények konkrét működését is. Ezeknek a részletes ismerete azonban nem szükséges a függvények a használathoz (sokszor maga a forráskód rendelkezésünkre sem áll).

Grafika példa

A következőkben bemutatunk egy olyan header fájlt, melynek segítségével Linux-on (X11 felületen) grafikus programokat lehet készíteni, hasonlóan a Logo nyelvhez (csak ez itt sokkal kevesebbet tud és nem néz ki olyan jól). A rajzoláshoz a paint.h header fájlt fogjuk használni, ami így néz ki:

Header fájl Logo szerű programozáshoz (paint.h)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/* Logo-szerű függvénykönyvtár C nyelvhez
 *
 * A függvénykönyvtár alapját Douglas Thain `A simple graphics library for
 * CSE 20211' munkája képezi (gfx.h és gfx.c fájlok)
 * http://www.nd.edu/~dthain/courses/cse20211/fall2013/gfx
 *
 * Gercsó Márk, gmark@inf.u-szeged.hu
 * Gergely Tamás, gertom@inf.u-szeged.hu
 */

#ifndef GRAPHICS_LOGO_H
#define GRAPHICS_LOGO_H

#include <stdbool.h>

/* Előre definiált színek listája */
typedef enum {
    WHITE        = 0xFFFFFF,
    RED          = 0xFF0000,
    LIGHT_RED    = 0xF08080,
    DARK_RED     = 0x8B0000,
    PINK         = 0xFF69B4,
    LIGHT_PINK   = 0xFFC0CB,
    ORANGE       = 0xFFA500,
    CORAL        = 0xFF7F50,
    YELLOW       = 0xFFFF00,
    GOLD         = 0xFFD700,
    LIGHT_YELLOW = 0xFFFFE0,
    PURPLE       = 0xBA55D3,
    LIGHT_PURPLE = 0xD8BFD8,
    DARK_PURPLE  = 0x800080,
    GREEN        = 0x00FF00,
    LIGHT_GREEN  = 0x00FA9A,
    DARK_GREEN   = 0x2E8B57,
    BLUE         = 0x0000FF,
    LIGHT_BLUE   = 0x87CEEB,
    DARK_BLUE    = 0x00008B,
    BROWN        = 0xA52A2A,
    LIGHT_BROWN  = 0xDEB887,
    DARK_BROWN   = 0x8B4513,
    LIGHT_GRAY   = 0xC0C0C0,
    GRAY         = 0x808080,
    BLACK        = 0x000000
} color_t;

/* Elkészít egy ablakot megadott méretben, az alapértelmezett beállításokkal
 * A kurzor a képernyő közepén helyezkedik el, a háttér fekete, az előtér
 * fehér, míg a kurzor zöld színű lesz.
 * width: az ablak szélessége
 * height: az ablak magassága
 */
void create_window(int width, int height);

/* Várakozik a 'q' billentyű lenyomására, majd bezárja az ablakot. */
void close_window();

/* Beállítja az előtér színét, amely színnel a rajzolás történik.
 * c: az előtér új színe a color_t listából
 */
void set_color(color_t c);

/* Beállítja az előtér színét, amely színnel a rajzolás történik.
 * r: a szín piros komponense (0..255)
 * g: a szín zöld komponense (0..255)
 * b: a szín kék komponense (0..255)
 */
void set_color_rgb(int r, int g, int b);

/* Beállítja a háttér színét.
 * c: a háttér új színe a color_t listából
 */
void set_background(color_t c);

/* Beállítja a háttér színét.
 * r: a szín piros komponense (0..255)
 * g: a szín zöld komponense (0..255)
 * b: a szín kék komponense (0..255)
 */
void set_background_rgb(int r, int g, int b);

/* Beállítja a kurzort jelző nyíl színét.
 * c: a háttér új színe a color_t listából
 */
void set_arrow_color(color_t c);

/* Beállítja a kurzort jelző nyíl színét.
 * r: a szín piros komponense (0..255)
 * g: a szín zöld komponense (0..255)
 * b: a szín kék komponense (0..255)
 */
void set_arrow_color_rgb(int r, int g, int b);

/* Visszaad egy véletlenszerű színt a color_t listából. */
color_t get_random_color();

/* Visszaad egy teljesen véletlenszerű RGB színt. */
color_t get_random_color_rgb();

/* Engedélyezi a kurzort jelző nyíl megjelenítését. */
void show_cursor();

/* Letiltja a kurzort jelző nyíl megjelenítését. */
void hide_cursor();

/* Kitölti az előtér színével azt az egybefüggő, azonos színű területet,
 * ahol a kurzor jelenleg áll. Ha a kurzor egy olyan pixelen áll, amely
 * színe megegyezik az előtér színével, akkor nem történik semmi.
 */
void fill();

/* Felemeli a tollat. Amíg fel van emelve a toll, addig nem történik
 * rajzolás a kurzor mozgatása közben.
 */
void pen_up();

/* Leteszi a tollat. Ha le van téve a toll, akkor a kurzor mozgatása közben
 * a bejárt útvonalat végigrajzoljuk az előtér színével.
 */
void pen_down();

/* A kurzort distance egységnyi pixellel előre mozgatja.
 * distance: a mozgatás mértéke pixelben
 */
void forward(float distance);

/* A kurzort distance egységnyi pixellel hátrafel mozgatja.
 * distance: a mozgatás mértéke pixelben
 */
void back(float distance);

/* A kurzort elforgatja balra angle fokkal.
 * angle: a forgatás mértéke fokban
 */
void left(float angle);

/* A kurzort elforgatja jobbra angle fokkal.
 * angle: a forgatás mértéke fokban
 */
void right(float angle);

/* Beállítja az animáció (mozgás, fordulás, kitöltés) sebességét.
 * value: 0 (leglassabb) és 10 (leggyorsabb) közötti szám
 */
void set_speed(int value);

/* Beállítja a mozgás animáció sebességét.
 * value: 0 (leglassabb) és 10 (leggyorsabb) közötti szám
 */
void set_move_speed(int value);

/* Beállítja a forgás animáció sebességét.
 * value: 0 (leglassabb) és 10 (leggyorsabb) közötti szám
 */
void set_turn_speed(int value);

/* Beállítja a kurzor irányát target_angle fokra.
 * target_angle: a kívánt szög fokban (0: jobbra, 90: le, 180: balra, 270: fel)
 */
void turn_to(float target_angle);

/* A kurzor irányát beállítja felfelé (270). */
void turn_up();

/* A kurzor irányát beállítja lefelé (90). */
void turn_down();

/* A kurzor irányát beállítja balra (180). */
void turn_left();

/* A kurzor irányát beállítja jobbra (0). */
void turn_right();

/* A kurzort a megadott (x, y) pozícióba mozgatja. Mozgás közben rajzol, ha
 * lent van a toll.
 * x: vízszintes pozíció
 * y: függőleges pozíció
 */
void goto_position(float x, float y);

/* A kurzort a megadott (x, y) pozícióra helyezi. Nincs rajzolás.
 * x: vízszintes pozíció
 * y: függőleges pozíció
 */
void jump_to_position(float x, float y);

/* A kurzor aktuális helyzete (x, y pozíció, irány) lesz a `home' helyzet.
 * Kezdetben ez a képernyő közepe, és a kurzor felfelé néz.
 */
void set_home();

/* A kurzort a mentett `home' helyzetbe mozgatja. Ha kell, rajzol közben. */
void goto_home();

/* A kurzort a mentett `home' helyzetbe helyezi. Nincs rajzolás. */
void jump_home();

/* Visszaadja a kurzor aktuális helyzetének vízszintes koordinátáját. */
float get_x_position();

/* Visszaadja a kurzor aktuális helyzetének függőleges koordinátáját. */
float get_y_position();

/* Visszaadja a kurzor aktuális helyzetének irányát (fokban). */
float get_angle();

/* Visszaadja az előtér (rajzolás) színét. */
color_t get_foreground_color();

/* Visszaadja a háttér színét. */
color_t get_background_color();

/* Visszaadja a kurzor színét. */
color_t get_cursor_color();

/* Visszaadja, hogy a toll le van-e rakva? */
int is_pen_down();

/* Visszaadja, hogy a kurzor meg van-e jelenítve? */
int is_cursor_active();

/* Az ablak tartalmát ppm formátumban elmenti a filename nevű fájlba.
 * filename: a létrehozandó fájl neve.
 */
void save_image(const char* filename);

/* Ellenőrzi, hogy a következő esemény a bal egérkattintás-e? */
bool new_event_is_left_click();

/* Ellenőrzi, hogy a következő esemény a key billentyű leütése-e?
 * key: a várt billentyű
 */
bool new_event_is_button(char key);

/* Visszaadja az utolsó esemény x koordinátáját. */
int last_event_x();

/* Visszaadja az utolsó esemény y koordinátáját. */
int last_event_y();

/* Egy boldog felhő kirajzolása az aktuális pozíció köré megadott méretben.
 * size: a felhő mérete (min: 8)
 */
void draw_cloud(float size);

#endif

Ezt a header-t kell majd include-olni #include "paint.h" módon (tehát <> helyett "" között), de a teljes működéshez szükség lesz még a paint.c, gfx.h és gfx.c fájlokra is. Ezeket is töltsük le (ugyanabba a könyvtárba mentsük, ahol a paint.h is van, és ahol a grafikus programokat is írjuk majd)!

Most készítsünk egy egyszerű programot, ami mindössze egy vonalat rajzol. Ehhez csak létre kell hoznunk egy nem túl nagy grafikus ablakot, előremozogni a kurzorral, majd bezárni az ablakot. Ez a program a paint.h segítségével így nézne ki:

1
2
3
4
5
6
7
8
#include "paint.h"

int main() {
    create_window(500, 500);
    forward(250);
    close_window();
    return 0;
}

A fájl első sora tartalmazza az include-ot, ez teszi lehetővé, hogy használhassuk a paint.h-ban lévő függvényeket. Azt természetesen tudnunk kell, hogy ezek a függvények MIT csinálnak, de azt nem, hogy HOGYAN. A create_window(500, 500) például létrekoz egy 500x500 pixeles grafikus ablakot, amelynek kezdetben a közepén van a kurzor (és felfelé néz). A forward(250) előrefele mozgatja ezt a kurzort 250 pixelnyit, és közben fehérrel rajzolja a bejárt útvonalat, a close_window() pedig megvárja, amíg megnyomjuk a 'q' pillentyűt, és bezárja az ablakot.

Mentsük el az elkészített programot mondjuk pelda.c néven!

A program fordítása az eddigiekhez képest kicsit bonyolultabb lesz, mert a paint.h-ban deklarált függvények megvalósítására, az ezekben használt egyéb függvények megvalósítására, az ezekben használt ... (ezt itt jó sokáig lehetne folytatni) ... függvények megvalósítására is szükség lesz. További részletek nélkül, a fordítás így néz ki (a paint.c gfx.c -lX11 -lm parancssorhoz adása a lényeg):

1
$ gcc pelda.c paint.c gfx.c -lX11 -lm -o program -Wall

Futtassuk le a programot:

1
$ ./program

Otthoni használat

A program az XLib függvénykönyvtárat használja, amely csak linuxon elérhető, ezért a használatához valamilyen grafikus linuxra lesz szükség. (Az ssh tehát alapesetben nem megoldás; bár azon keresztül is megoldható lenne, ezzel most nem foglalkozunk.) Egy grafikus interfésszel rendelkező virtuális gép vagy natív linux megfelelő lehet.

Lehetőségek

A Logo alapvetően úgy működik, hogy egy kurzort mozgatunk a képernyőn néhány parancs segítségével, a megtett útvonalat pedig bejelöli a program (de kérhetjük, hogy ne tegye, csak menjen). Érdemes átnézni a paint.h fájlt, hogy milyen lehetőségeink vannak a mozgatásra, színezésre, stb. Minden függvényhez tartozik egy leírás (a függvény előtti komment).

További feladatok

Feladat (f0008)

Problémafelvetés:

Készíts egy programot, amely beolvas 3 valós számot, majd kiírja őket, mindegyiket új sorba!

Specifikáció:

A program inputja három valós szám, whitespace karakterekkel elválasztva. A program outputja a három beolvasott valós szám tetszőleges pontossággal, egy-egy új sorban.

Lehetséges megoldás (m0008.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0008 m0008.c
 *
 * futtatás:
 *    ./m0008
 */

#include <stdio.h>

int main() {
    double d1, d2, d3;
    scanf("%lf %lf %lf", &d1, &d2, &d3);

    printf("Első szám: %lf\n", d1);
    printf("Második szám: %lf\n", d2);
    printf("Harmadik szám: %lf\n", d3);

    return 0;
}

Feladat (f0019)

Problémafelvetés:

Írj egy programot ami az oldalhosszból kiszámítja egy négyzet kerületét és területét!

Specifikáció:

A program inputja egyetlen nemnegatív valós szám, a négyzet oldalhossza. A program outputja két sor. Az elsőben a "T = " szöveg után a négyzet területe, a második sorban a "K = " szöveg után a négyzet kerülete szerepel. Mindkét számot 10 karakteren jobbra igazítva 3 tizedesjegy pontossággal kell kiíratni! A beolvasás előtt a program elején ki kell írni egy rövid tájékoztatót arról, hogy a program milyen adatot kér be!

Lehetséges megoldás (m0019.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0019 m0019.c
 *
 * futtatás:
 *    ./m0019
 */

#include <stdio.h>

int main() {
    double a;
    printf("Adja meg a négyzet oldalhosszát!\na = ");
    scanf("%lf", &a);

    printf("T = %10.3lf\n", a * a);
    printf("K = %10.3lf\n", 4.0 * a);

    return 0;
}

Feladat (f0030)

Problémafelvetés:

Írj egy programot ami az átló hosszából kiszámítja egy négyzet kerületét és területét!

Specifikáció:

A program inputja egyetlen nemnegatív valós szám, a négyzet átlójának hossza. A program outputja két sor. Az elsőben a "T = " szöveg után a négyzet területe, a második sorban a "K = " szöveg után a négyzet kerülete szerepel. Mindkét számot 10 karakteren jobbra igazítva 3 tizedesjegy pontossággal kell kiíratni. A beolvasás előtt a program elején ki kell írni egy rövid tájékoztatót arról, hogy a program milyen adatot kér be!

Lehetséges megoldás (m0030.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0030 m0030.c
 *
 * futtatás:
 *    ./m0030
 */

#include <stdio.h>
#include <math.h>

int main() {
    double atlo, oldal;
    printf("Adja meg a négyzet átlótjának hosszát!\n");
    scanf("%lf", &atlo);

    oldal = atlo / sqrt(2.0);

    printf("T = %10.3lf\n", oldal * oldal);
    printf("K = %10.3lf\n", 4.0 * oldal);

    return 0;
}

Feladat (f0032)

Problémafelvetés:

Írj egy programot ami a három oldalhosszból kiszámítja egy téglatest felszínét és térfogatát!

Specifikáció:

A program inputja három nemnegatív valós szám, a téglatest oldalhosszai. A program outputja két sor. Az elsőben a "V = " szöveg után a téglalap térfogata, a második sorban az "A = " szöveg után a téglalap felülete szerepel. Mindkét számot 10 karakteren jobbra igazítva 3 tizedesjegy pontossággal kell kiíratni. A beolvasás előtt a program elején ki kell írni egy rövid tájékoztatót arról, hogy a program milyen adatot kér be.

Lehetséges megoldás (m0032.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0032 m0032.c
 *
 * futtatás:
 *    ./m0032
 */

#include <stdio.h>

int main() {
    double a, b, c;
    printf("Adja meg a tégletest oldalhosszait\n");
    printf("a = ");
    scanf("%lf", &a);
    printf("b = ");
    scanf("%lf", &b);
    printf("c = ");
    scanf("%lf", &c);

    printf("V = %10.3lf\n", a * b * c);
    printf("A = %10.3lf\n", 2*a*b + 2*a*c + 2*b*c);

    return 0;
}

Feladat (f0044)

Problémafelvetés:

Írj egy programot ami kiszámítja, hogy egy adott kezdősebességgel függőlegesen kilőtt test adott nehézségi gyorsulás (\(g=1,63 m/s^2\)) mellett mennyi idő alatt esik vissza a Hold felszínére? Feltételezhető, hogy a kezdősebesség nem elég nagy ahhoz, hogy a testre ható tömegvonzás érezhetően megváltozzon.

Algoritmustervezés:

A számításhoz segítség lehet a \(v=v_0+(a*t)\) képlet, ahol \(v_0\) a kezdősebességet, \(a\) a gyorsulást, \(t\) pedig az eltelt időt jelenti.

Lehetséges megoldás (m0044.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0044 m0044.c
 *
 * futtatás:
 *    ./m0044
 */

#include <stdio.h>

#define GRAVITY 1.63

int main() {
    double v0;
    printf("Adja meg a kezdősebességet (v_0)!\n");
    scanf("%lf", &v0);

    printf("Visszatérés időtartama = %lf sec.\n", 2 * v0 / GRAVITY);

    return 0;
}

Feladat (f0023)

Problémafelvetés:

Írj programot, amely egy Euróban megadott összeget adott középárfolyamon Forintra számít át!

Specifikáció:

A program inputja két nemnegatív valós szám, az Euro árfolyama (1EUR/1HUF) és az átváltandó összeg. A program megfelelő tájékoztatás után kéri be a két értéket. A program outputja egyetlen sor, melynek tartalma egy valós szám tizedesjegyek nélkül, ami a megadott Euromennyiség adott árfolyamon számolt értéke Forintban, valamint mögötte egy szóközzel elválasztva a "HUF" megjelölés.

Lehetséges megoldás (m0023.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0023 m0023.c
 *
 * futtatás:
 *    ./m0023
 */

#include <stdio.h>

int main() {
    double act, eur;
    printf("Adja meg a jelenlegi középárfolyamot (EUR -> HUF)!\n");
    scanf("%lf", &act);

    printf("Adja meg mennyi eurót szeretne váltani!\n");
    scanf("%lf", &eur);

    printf("%.0lf HUF\n", eur * act);

    return 0;
}

Feladat (f0010)

Problémafelvetés:

Írj egy programot, amely az egész típus értékkészletének korlátossága miatt rossz eredményt ad valamilyen műveletekre. Az alul- és túlcsordulást is mutasd meg!

Specifikáció:

A programnak nincs inputja. A program outputja két egész szám. A két szám egy-egy művelet eredménye, amely műveletek matematikailag olyan eredményt adnának, amik a típus értékkészletéből felfelé illetve lefelé kilógnak.

Megvalósítás:

Mivel az int értékkészlete a legtöbb mai rendszeren kb. \(\pm2.1 \times 10^9\), érdemes olyan 1500000000 (\(1.5 \times 10^9\)) körüli értékekkel dolgozni. Két ilyen nagyságrendű pozitív szám összeadása negatív számot, két ilyen nagyságrendű negatív szám összeadása pozitív számot eredményez (ha az eredményt is int változóban tároljuk). De dolgozhatunk char típussal is, akkor ezek a jelenségek -128 alatt és 127 felett fordulnak elő.

Lehetséges megoldás (m0010.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * Jász Judit, 2017. őszi félév.
 *
 * Algoritmustervezés:
 *    A program outputja két művelet és az eredményük. A két művelet olyan,
 *    hogy matematikailag a típus értékkészletéből felfelé illetve lefelé
 *    kilógó eredményt ad. Ez a két művelet konkrétan az értéktartomány
 *    legnagyobb illetve legkisebb elemének növelése illetve csökkentése.
 *
 * fordítás:
 *    gcc -Wall -o m0010 m0010.c
 *
 * futtatás:
 *    ./m0010
 */

#include <stdio.h>
#include <limits.h>

int main() {
    int a = INT_MAX;
    int b = 1;
    int c = INT_MIN;

    printf("%d + %d = %d\n", a, b, a + b);
    printf("%d - %d = %d\n", c, b, c - b);
    return 0;
}

Feladat (f0021)

Problémafelvetés:

Adott a síkon két pont. Határozd meg a távolságukat!

Specifikáció:

A program inputja kép koordinátapár, összesen négy valós szám, melyek \(x_1, y_1, x_2, y_2\) sorrendben a \(P_1(x_1,y_1)\) és \(P_2(x_2,y_2)\) síkbeli pontok koordinátái. A program outputja egyetlen sor, amely a

1
"P1(x1,y1) es P2(x2,y2) pontok tavolsaga d"

tartalmú, ahol x1, y1, x2 és y2 a megadott koordináták, d pedig a két pont síkbeli távolsága. A beolvasás előtt a program elején ki kell írni egy rövid tájékoztatót arról, hogy a program milyen adatot kér be.

Megvalósítás:

Négyzetgyök számítására a math.h-ban deklarált egyparaméteres

1
double sqrt(double)

függvény használható. Ehhez a C program elejére be kell szúrni az

1
#include <math.h>

sort, ezután a programban használható az sqrt() függvény, amely az argumentumként megadott valós kifejezés négyzetgyökével tér vissza. De ez még nem elég, a fordításkor (pontosabban annak a linkelési lépésében) meg kell adni a -lm kapcsolót is. Próbáld ki, milyen hibaüzenet lesz a fordítás eredménye, ha nem adod meg a -lm kapcsolót.

Lehetséges megoldás (m0021.c)

Szükséges képlet \(d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}\)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0021 m0021.c
 *
 * futtatás:
 *    ./m0021
 */

#include <stdio.h>
#include <math.h>

int main() {
    double x1, x2, y1, y2;
    double d;

    printf("Adja meg a két pont koordinátáit!\n");

    printf("x1 = ");
    scanf("%lf", &x1);
    printf("x2 = ");
    scanf("%lf", &x2);
    printf("y1 = ");
    scanf("%lf", &y1);
    printf("y2 = ");
    scanf("%lf", &y2);

    d = sqrt( pow(x1 - x2, 2) + pow(y1 - y2, 2) );        
    printf("P1(%lf,%lf) es P2(%lf,%lf) pontok tavolsaga %lf\n", x1, y1, x2, y2, d);

    return 0;
}

Feladat (f0022)

Problémafelvetés:

Írj egy programot ami kiszámítja, hogy egy egyenletes sebességgel egyenes vonalban haladó test mennyi idő alatt tesz meg egy adott útszakaszt!

Specifikáció:

A program inputja egy pozitív és egy nemnegatív valós szám, a test sebessége (\(v\)) és az útszakasz hossza (\(s\)). A program megfelelő tájékoztatás után kéri be a két értéket, melyek mértékegységei \(m/s\) illetve \(m\). A program outputja a megadott \(s\) távolság egyenletes \(v\) sebességgel történő megtételéhez szükséges \(t\) idő, másodpercekben, ezredmásodperces pontossággal kiírva.

Algoritmustervezés:

Az eltelt idő az \(s=vt\) képletből számolható.

Lehetséges megoldás (m0022.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0022 m0022.c
 *
 * futtatás:
 *    ./m0022
 */

#include <stdio.h>

int main() {
    double v, s;

    printf("Adja meg a sebességet!\n");
    scanf("%lf", &v);

    printf("Adja meg az út hosszát!\n");
    scanf("%lf", &s);

    printf("Az út megtételéhez %.3lf sec szükséges.\n", s/v);

    return 0;
}

Feladat (f0025)

Problémafelvetés:

Írj programot ami bekér egy pénzösszeget (egy számot), majd meghatározza, hogyan fizethető ki ez az összeg a lehető legkevesebb 200, 100, 50, 20, 10, 5, 2 és 1 koronás érmével!

Specifikáció:

A program inputja egyetlen nemnegatív egész szám, a felváltandó összeg. A program kimenete nyolc sor, minden érmetípushoz egy. Minden sor első három karaktere jobbra igazítva tartalmazza az érme értékét, ezt egy kettőspont és egy szóköz követi, majd az adott érméből szükséges darabszám szintén három karakteren jobbra igazítva. A program semmi mást ne írjon ki.

Algoritmustervezés:

Ezekkel az érmékkel a felváltás egyszerű: ha mindig a legnagyobb olyan érmét választjuk, ami még "belefér" az összegbe, akkor az érmeszám minimális lesz.

Lehetséges megoldás (m0025.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0025 m0025.c
 *
 * futtatás:
 *    ./m0025
 */

#include <stdio.h>

int main() {
    int osszeg;

    int ketszaz = 0;
    int szaz = 0;
    int otven = 0;
    int husz = 0;
    int tiz = 0;
    int ot = 0;
    int ketto = 0;
    int egy = 0;

    printf("Adja meg az osszeget!\n");
    scanf("%d", &osszeg);

    ketszaz = osszeg / 200; // ennyi 200-as jön ki belőle
    osszeg %= 200;          // ennyi marad: osszeg = osszeg % 200

    szaz = osszeg / 100;
    osszeg %= 100;

    otven = osszeg / 50;
    osszeg %= 50;

    husz = osszeg / 20;
    osszeg %= 20;

    tiz = osszeg / 10;
    osszeg %= 10;

    ot = osszeg / 5;
    osszeg %= 5;

    ketto = osszeg / 2;
    osszeg %= 2;

    egy = osszeg;

    printf("Minimális érmék száma:\n");
    printf("\t200: %3d db\n", ketszaz);
    printf("\t100: %3d db\n", szaz);
    printf("\t 50: %3d db\n", otven);
    printf("\t 20: %3d db\n", husz);
    printf("\t 10: %3d db\n", tiz);
    printf("\t  5: %3d db\n", ot);
    printf("\t  2: %3d db\n", ketto);
    printf("\t  1: %3d db\n", egy);

    return 0;
}

Feladat (f0045)

Problémafelvetés:

Írj egy programot ami adott nehézségi gyorsulás (\(g=9,81 m/s^2\)) mellett a kilövési szög és a kezdősebesség alapján kiszámolja, hogy hol lesz a kilőtt test a felhasználó által megadott idő múlva. Számítsd ki azt is, hogy mikor és hol éri el a röppálya maximális magasságát, illetve a test mikor és hol ér földet. Nem kell számolnod a légellenállással és feltételezd, hogy a terep sík, és a megadott idő alatt a test még nem esik vissza a földre.

Specifikáció:

A program inputjai:

  • \(\alpha\): valós érték, kilövési szög a vízszinteshez képest fokban megadva, \(0 < \alpha \leq 90\)
  • \(v_0\) : valós érték, kezdősebesség \(m/s\)-ben megadva, \(0 < v_0\)
  • \(t\) : valós érték, az eltelt idő, \(0 \leq t \leq\) {a teljes repülési idő}

A program outputjai:

  • \((x_t,y_t)\): Valós koordináta-pár, a test vízszintes \((x_t)\) és függőleges \((y_t)\) koordinátája a kilövés utáni \(t\) időpontban.
  • \(t_h\) : A maximális magasság eléréséhez szükséges idő.
  • \((x_h,y_h)\): Valós koordináta-pár, a test vízszintes \((x_h)\) és függőleges \((y_h)\) koordinátája a kilövés utáni \(t_h\) időpontban.
  • \(t_d\) : A földetérés időpontja.
  • \((x_d,y_d)\): Valós koordináta-pár, a test vízszintes \((x_d)\) és függőleges \((y_d)\) koordinátája a kilövés utáni \(t_d\) időpontban.

Megvalósítás:

A math.h a négyzetgyök számító függvény mellett (többek között) a szintén egyparaméteres

1
2
double sin(double)
double cos(double)

függvényeket is tartalmazza, melyek szintén használhatóak.

Lehetséges megoldás (m0045.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * fordítás:
 *    gcc -Wall -o m0045 m0045.c
 *
 * futtatás:
 *    ./m0045
 */

#include <stdio.h>
#include <math.h>

#define GRAVITY 9.81

int main() {
    double alpha;
    double v0;
    double t;

    printf("Adja meg a hajitasi szoget fokban!\n");
    scanf("%lf", &alpha);

    // converting degree to radian: sin, cos use radian
    alpha = alpha * (M_PI / 180);

    printf("Adja meg a hajitas kezdősebességét!\n");
    scanf("%lf", &v0);

    printf("Melyik időpillanatra kíváncsi (sec-ben)?\n");
    scanf("%lf", &t);

    double deltax = v0 * t * cos(alpha);
    double deltay = v0 * t * sin(alpha) - (GRAVITY / 2) * t*t;

    double max_height_t = v0 * sin(alpha) / GRAVITY;
    double full_t = 2 * max_height_t;

    double distance = (v0 * v0 * sin(2 * alpha)) / GRAVITY;
    double height = (v0 * v0 * sin(alpha) * sin(alpha)) / (2 * GRAVITY);

    printf("%.2lf sec után a test helyzet: (%.2lf, %2lf)\n", t, deltax, deltay);
    printf("A legmagasabb pont eléréséhez szükséges idő: %.2lf\n", max_height_t);
    printf("A legmagasabb pont koordinátái: (%.2lf, %.2lf)\n", distance / 2, height);
    printf("A hajítás időtartama: %.2lf\n", full_t);
    printf("A földetéréskor a test koordinátái: (%.2lf, %.2lf)\n", distance, 0.0);

    return 0;
}

Grafikus szorgalmi feladatok

A grafikus programozás nem lesz számonkérve, viszont látványos dolgokat lehet vele csinálni a C-s vezérlési szerkezetek gyakorlása mellett.

Feladat (fgr01)

Problémafelvetés:

Rajzoljunk egy négyzetet!

Megvalósítás:

A paint.h segítségével egy ablakban rajzoljunk egy négyzetet.

paint01

Lehetséges megoldás (mgr01.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* Grafikus példaprogram C nyelvhez.
 *
 * Egy négyzetet rajzol az ablakba.
 *
 * Gercsó Márk, gmark@inf.u-szeged.hu
 */

#include "paint.h"

int main() {
    create_window(1000, 600);

    forward(100);
    right(90);
    forward(100);
    right(90);
    forward(100);
    right(90);
    forward(100);

    close_window();
    return 0;
}
Feladat (fgr02)

Problémafelvetés:

Rajzoljunk egy gyógyszertári keresztet csak körvonalakkal!

Megvalósítás:

A paint.h segítségével egy ablakban rajzoljunk egy gyógyszertári keresztet.

paint01

Lehetséges megoldás (mgr02.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* Grafikus példaprogram C nyelvhez.
 *
 * Egy keresztet rajzol az ablakba.
 *
 * Gercsó Márk, gmark@inf.u-szeged.hu
 */

#include "paint.h"

void negyedkereszt(int meret) {
    forward(meret);
    right(90);
    forward(meret);
    right(90);
    forward(meret);
    left(90);
}

int main() {
    create_window(1000, 600);

    negyedkereszt(50);
    negyedkereszt(50);
    negyedkereszt(50);
    negyedkereszt(50);

    close_window();
    return 0;
}
Feladat (fgr03)

Problémafelvetés:

Rajzoljunk egymásba ágyazott négyzeteket!

Megvalósítás:

A paint.h segítségével egy ablakban rajzoljunk több négyzetet közös középponttal.

paint01

Lehetséges megoldás (mgr03.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* Grafikus példaprogram C nyelvhez.
 *
 * Három egymásbaágyazott színes négyzetet rajzol az ablakba.
 *
 * Gercsó Márk, gmark@inf.u-szeged.hu
 */

#include "paint.h"

void negyszog(int meret) {
    forward(meret);
    right(90);
    forward(meret);
    right(90);
    forward(meret);
    right(90);
    forward(meret);
    right(90);
}

int main() {
    create_window(1200, 600);

    set_color(RED);
    negyszog(100);

    pen_up();
    back(50);
    left(90);
    forward(50);
    right(90);
    pen_down();

    set_color(WHITE);
    negyszog(200);

    pen_up();
    back(50);
    left(90);
    forward(50);
    right(90);
    pen_down();

    set_color(GREEN);
    negyszog(300);

    close_window();
    return 0;
}
Feladat (fgr04)

Problémafelvetés:

Rajzoljunk egy négyzetes kokárdát!

Megvalósítás:

A paint.h segítségével egy ablakban rajzoljunk három egymásba ágyazott négyzetet közös középponttal, majd színezzük ki a kapott területeket.

paint01

Lehetséges megoldás (mgr04.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/* Grafikus példaprogram C nyelvhez.
 *
 * Egy négyzetes kokárdát rajzol az ablakba.
 *
 * Gercsó Márk, gmark@inf.u-szeged.hu
 */

#include "paint.h"

void negyszog(int meret) {
    forward(meret);
    right(90);
    forward(meret);
    right(90);
    forward(meret);
    right(90);
    forward(meret);
    right(90);
}

int main() {
    create_window(1200, 600);

    set_move_speed(9);

    set_color(RED);
    negyszog(100);

    pen_up();
    back(50);
    left(90);
    forward(50);
    right(90);
    pen_down();

    set_color(WHITE);
    negyszog(200);

    pen_up();
    back(50);
    left(90);
    forward(50);
    right(90);
    pen_down();

    set_color(GREEN);
    negyszog(300);

    pen_up();

    right(45);

    forward(70);
    fill();

    set_color(WHITE);
    forward(70);
    fill();

    set_color(RED);
    forward(70);
    fill();

    hide_cursor();

    close_window();
    return 0;
}
Feladat (fgr05)

Problémafelvetés:

Rajzoljunk egy virágot véletlenszerű színekkel!

Megvalósítás:

A paint.h segítségével egy ablakban rajzoljunk egy színes virágot.

paint01

Lehetséges megoldás (mgr05.c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/* Grafikus példaprogram C nyelvhez.
 *
 * Egy virágot rajzol az ablakba véletlenszerű színekkel, majd a képet elmenti
 * `virag.ppm' néven.
 *
 * Gercsó Márk, gmark@inf.u-szeged.hu
 */

#include "paint.h"

void level(int meret) {
    forward(meret);
    right(45);
    forward(meret);
    right(135);
    forward(meret);
    right(45);
    forward(meret);
    right(180);
}

int main() {
    create_window(1000, 600);

    int meret = 50;
    color_t viragszin = get_random_color_rgb();
    color_t torzsszin = get_random_color_rgb();


    set_background_rgb(100, 129, 196);

    set_color(viragszin);

    level(meret);
    level(meret);
    level(meret);
    level(meret);
    level(meret);
    level(meret);
    level(meret);
    level(meret);

    pen_up();
    back(meret);
    pen_down();
    set_color(torzsszin);
    back(4 * meret);

    save_image("virag.ppm");

    close_window();
    return 0;
}

Kapcsolódó linkek

C könyvtár-referencia


Utolsó frissítés: 2022-11-25 15:25:14