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

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

Kapcsolódó linkek

C könyvtár-referencia


Utolsó frissítés: 2021-09-01 11:11:07