Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: OOP Kalkulačka výstup

Aktivity
Avatar
Lukáš Havlíček:24.1.2022 17:09

Ahoj, přešel jsem na učení OOP. Nyní si zkouším zkušenosti z prvních lekcí, tak si tvořím kalkulačku. Veškéré výpočty mi fungují. Jediný, co mi nefunguje, tak je výstup názvu operace. Místo "Sčítání" se mi zobrazuje "scitani"). Předem děkuji za kařdou radu. Určitě by se ten zdroják dal nějak zjednodušit například pomocí switche, ale ten se mi moc nelíbí. .Přikládám zdroják.

index.php

<!DOCTYPE html>
<html lang="cs-cz">

        <head>
                <meta charset="utf-8" />
                <meta name="description" content="" /> <!-- Popis stránky -->
                <meta name="keywords" content="" /> <!-- Klíčová slova -->
                <meta name="author" content="" /> <!-- Autor webu -->
                <link rel="shortcut icon" href="obrazky/ikona.ico" />
                <link rel="stylesheet" href="styl.css" type="text/css" />
                <title>Kalkulačka</title>
        </head>

        <body>
        <h1 style="text-align: center">PHP objektově orientovaná kalkulačka</h1>

        <form method="POSt">
            <table border="1">
                <tr>
                    <td>První číslo: </td>
                    <td><input name="prvniCislo" type="text" /> </td>
                </tr>
                <tr>
                    <td>Druhé číslo: </td>
                    <td><input name="druheCislo" type="text" /> </td>
                </tr>
                <tr>
                    <td>Operace: </td>
                    <td>
                        <select name="operace">
                            <option value="scitani">Sčítání</option>
                            <option value="odcitani">Odčítání</option>
                            <option value="nasobeni">Násobení</option>
                            <option value="deleni">Dělení</option>
                        </select>
                    </td>
                </tr>
            </table>
            <input type="submit" value="Zjistit výsledek" />
        </form>

        <?php
            mb_internal_encoding("UTF-8");
            require_once ('tridy/Kalkulacka.php');

            if ($_POST)
            {
                $kalkulacka = new Kalkulacka($_POST['prvniCislo'], $_POST['druheCislo'], $_POST['operace']);

                echo('Zvolil jsi operaci: <strong>' . mb_strtoupper($kalkulacka->operace) . '</strong>.<br />');
                echo('Výsledek této operace je: <strong>' . $kalkulacka->vypocitej() . '</strong>');
            }
        ?>
        </body>
</html>

Třída Kalkulacka.php

<?php

class Kalkulacka
{
    public $prvniCislo;
    public $druheCislo;
    public $operace;
    public $chyba = 'Nulou nelze dělit ty joudo!';

    public function __construct($prvniCislo, $druheCislo, $operace)
    {
        $this->prvniCislo = $prvniCislo;
        $this->druheCislo = $druheCislo;
        $this->operace = $operace;
    }

    public function vypocitej()
    {
        if ($this->operace == 'scitani')
        {
            $vysledek = $this->prvniCislo + $this->druheCislo;
            return $vysledek;
        }
        else if ($this->operace == 'odcitani')
        {
            $vysledek = $this->prvniCislo - $this->druheCislo;
            return $vysledek;
        }
        else if ($this->operace == 'nasobeni')
        {
            $vysledek = $this->prvniCislo * $this->druheCislo;
            return $vysledek;
        }
        else if ($this->operace == 'deleni')
        {
            if ($this->druheCislo != 0)
            {
                $vysledek = $this->prvniCislo / $this->druheCislo;
                return $vysledek;
            }
            else
            {
                return $this->chyba;
            }
        }
    }
}

Zkusil jsem: Zkoušel jsem všelijak upravovat kód.

Chci docílit: Snažím se dosáhnout toho, aby výstup zadané operace například Sčítání byl Sčítání a ne Scitani.

 
Odpovědět
24.1.2022 17:09
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:24.1.2022 22:30

Kod mas spravne, pouze si vykladas spatne, jak funguje.

--- toto tam mas ---

        <form method="POSt">
                         <select name="operace">
                            <option value="scitani">Sčítání</option>
                            <option value="odcitani">Odčítání</option>
                            <option value="nasobeni">Násobení</option>
                            <option value="deleni">Dělení</option>
                        </select>

--- pokud zvolis scitani, tak je to totez jako mit kod ---

        <form method="POST">
<input type=hidden name=operace value=scitani>

--- php to prebira jako ---

$_POST['operace'] = 'scitani'

--- v php to v construct ukladas jako $operace = 'scitani'

public function __construct($prvniCislo, $druheCislo, $operace)
...
$this->operace = $operace; // $this->operace = 'scitani'

--- dale to v php porovnavas ---

$this->operace == 'scitani'

--- po sem je to ok, ze? ---
--- a take pomoci php z class vypisujes ---

echo "...". mb_strtoupper($kalkulacka->operace) // $this->operace == 'scitani' je stale bez diakritiky
// takze se to vypise jak? take bez diakritiky?
// takze bys tam musel pridat translator operaci na text s diakritikou, treba pomoci pole a isset()
Editováno 24.1.2022 22:32
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
24.1.2022 22:30
Avatar
Odpovídá na Peter Mlich
Lukáš Havlíček:25.1.2022 15:54

Ahoj, děkuji moc za radu. Dlouho jsem přemýšlel, jak to udělat s polem a pak jsem si vzpoměl na jeden úkol z klasického PHP. Teď můj kód vypadá takto a všechno funguje.

index.php

<!DOCTYPE html>
<html lang="cs-cz">

        <head>
                <meta charset="utf-8" />
                <meta name="description" content="" /> <!-- Popis stránky -->
                <meta name="keywords" content="" /> <!-- Klíčová slova -->
                <meta name="author" content="" /> <!-- Autor webu -->
                <link rel="shortcut icon" href="obrazky/ikona.ico" />
                <link rel="stylesheet" href="styl.css" type="text/css" />
                <title>Kalkulačka</title>
        </head>

        <body>
        <h1 style="text-align: center">PHP objektově orientovaná kalkulačka</h1>

        <form method="POSt">
            <table border="1">
                <tr>
                    <td>První číslo: </td>
                    <td><input name="prvniCislo" type="text" /> </td>
                </tr>
                <tr>
                    <td>Druhé číslo: </td>
                    <td><input name="druheCislo" type="text" /> </td>
                </tr>
                <tr>
                    <td>Operace: </td>
                    <td>
                        <select name="operace">
                            <option value="scitani">Sčítání</option>
                            <option value="odcitani">Odčítání</option>
                            <option value="nasobeni">Násobení</option>
                            <option value="deleni">Dělení</option>
                        </select>
                    </td>
                </tr>
            </table>
            <input type="submit" value="Zjistit výsledek" />
        </form>

        <?php
            mb_internal_encoding("UTF-8");
            require_once ('tridy/Kalkulacka.php');

            if ($_POST)
            {
                $kalkulacka = new Kalkulacka($_POST['prvniCislo'], $_POST['druheCislo'], $_POST['operace']);

                echo('Zvolil jsi operaci: <strong>' . $kalkulacka->prevodOperace() . '</strong>.<br />');
                echo('Výsledek této operace je: <strong>' . $kalkulacka->vypocitej() . '</strong>');
            }
        ?>
        </body>
</html>

Třída Kalkulacka.php

?php

class Kalkulacka
{
    public $prvniCislo;
    public $druheCislo;
    public $operaceDiakritika = array (
        'scitani' => 'SČÍTÁNÍ',
        'odcitani' => 'ODČÍTÁNÍ',
        'nasobeni' => 'NÁSOBENÍ',
        'deleni' => 'DĚLENÍ',
    );
    public $operace;
    public $chyba = 'Nulou nelze dělit ty joudo!';

    public function __construct($prvniCislo, $druheCislo, $operace)
    {
        $this->prvniCislo = $prvniCislo;
        $this->druheCislo = $druheCislo;
        $this->operace = $operace;
    }

    public function prevodOperace()
    {
        $operace = strtr($this->operace, $this->operaceDiakritika);
        return $operace;
    }

    public function vypocitej()
    {
          if ($this->operace == 'scitani')
          {
              $vysledek = $this->prvniCislo + $this->druheCislo;
              return $vysledek;
          }
          else if ($this->operace == 'odcitani')
          {
              $vysledek = $this->prvniCislo - $this->druheCislo;
              return $vysledek;
          }
          else if ($this->operace == 'nasobeni')
          {
              $vysledek = $this->prvniCislo * $this->druheCislo;
              return $vysledek;
          }
          else if ($this->operace == 'deleni')
          {
              if ($this->druheCislo != 0)
              {
                  $vysledek = $this->prvniCislo / $this->druheCislo;
                  return $vysledek;
              }
              else
              {
                  return $this->chyba;
              }
          }
    }
}
 
Nahoru Odpovědět
25.1.2022 15:54
Avatar
kaskader202
Člen
Avatar
kaskader202:8.1.2023 19:44

Já vím že už je to uzavřené a že to vlastně nebylo cílem dotazu, ale přeci jen bych pro případné další čtenáře ten finální výsled trochu upravil, aby z toho ten smysl OOP byl vidět přeci jen trochu lépe. V žádném případě se nejedná o kritiku, nebo cokoliv negativního. Naopak jsem moc rád že se autor ptá a chce se posunul někam dál.

Co bych změnil a proč (budu se bavit jen o třídě Kalkulačka):

  • Podle názvu by třída měla fungovat jako kalkulačka tudíž její instance by měla být nezávislá na vstupech od uživatele. Tedy odstranit konstruktor či si v něm připravit obsah proměnné $operaceDiakritika a $chyba.
  • Ted jak je třída navržená tak by pro každou operaci musela být nová instance třídy a to přece nechceme.
  • Tak jak je to napsáno teď tak by se třída měla spíše jmenovat něco jako Příklad. Protože instance reprezentuje jeden konkrétní příklad.
  • Není vyřešený problém s nezadáním vstupu, či špatného vstupu (např text)
  • Používají se proměnné (Atributy třídy) i když jde o konstantní věci - $operaceDiakritika, $chyba. Nehledě na to, že jsou public i když k ním z venku nepřistupujeme.
  • Pokud s výsledkem dané operace není potřeba nic dalšího dělat tak můžeme požít return na přímo, bez zbytečného ukládání do proměnné.

Ten výsledný kód bych si představoval nějak takto (typy na vstupech funkci nepíšu aby to bylo nezávislé na verzi php):

Třída Kalkulacka.php

<?php

class Kalkulacka
{
    const OPERACE_SCITANI = 0;
    const OPERACE_ODCITANI = 1;
    const OPERACE_NASOBENI = 2;
    const OPERACE_DELENI = 3;

    const HLASKA_NEZNAMA_OPERACE = 'NEZNÁMÁ OPERACE';

    const PREKLADOVA_MAPA_OPERACI = [
        self::OPERACE_SCITANI => 'SČÍTÁNÍ',
        self::OPERACE_ODCITANI => 'ODČÍTÁNÍ',
        self::OPERACE_NASOBENI => 'NÁSOBENÍ',
        self::OPERACE_DELENI => 'DĚLENÍ',
    ];

    /**
     * @throws RuntimeException
     */
    public function vypocitej($prvniCisloString, $druheCisloString, $operaceVstup)
    {
        $prvniCislo = $this->osetriVstupniCislo($prvniCisloString);
        $druheCislo = $this->osetriVstupniCislo($druheCisloString);
        $operace = $this->osetriOperaci($operaceVstup);

        // použití swithce
        switch ($operace) {
            case self::OPERACE_SCITANI:
                return $this->secti($prvniCislo, $druheCislo);
            case self::OPERACE_ODCITANI:
                return $this->odecti($prvniCislo, $druheCislo);
            case self::OPERACE_NASOBENI:
                return $this->nasob($prvniCislo, $druheCislo);
            case self::OPERACE_DELENI:
                return $this->vydel($prvniCislo, $druheCislo);
            default:
                throw new \RuntimeException("Byla zadaná neznámá operace: {$operace}");
        }

        // když se nelíbí switch tak můžeme třeba takto
        if ($operace === self::OPERACE_SCITANI) {
            return $this->secti($prvniCislo, $druheCislo);
        }
        if ($operace === self::OPERACE_ODCITANI) {
            return $this->odecti($prvniCislo, $druheCislo);
        }
        if ($operace === self::OPERACE_NASOBENI) {
            return $this->nasob($prvniCislo, $druheCislo);
        }
        if ($operace === self::OPERACE_DELENI) {
            return $this->vydel($prvniCislo, $druheCislo);
        }
        throw new \RuntimeException("Byla zadaná neznámá operace: {$operace}");

        //případně od php 8.0 můžem použít match
        return match ($operace){
            self::OPERACE_SCITANI => $this->secti($prvniCislo, $druheCislo),
            self::OPERACE_ODCITANI => $this->odecti($prvniCislo, $druheCislo),
            self::OPERACE_NASOBENI => $this->nasob($prvniCislo, $druheCislo),
            self::OPERACE_DELENI => $this->vydel($prvniCislo, $druheCislo),
            default => throw new \RuntimeException("Byla zadaná neznámá operace: {$operace}")
        };
    }

    /**
     * @throws RuntimeException
     */
    private function osetriOperaci($operaceVstup)
    {
        if (is_int($operaceVstup) && $this->existujeOperaceVPrekladoveMape((int)$operaceVstup)) {
            return (int)$operaceVstup;
        }
        throw new \RuntimeException("Byla zadaná neznámá operace: {$operaceVstup}");
    }

    public function prevedOperaciNaText($operace)
    {
        if ($this->existujeOperaceVPrekladoveMape($operace)) {
            return self::PREKLADOVA_MAPA_OPERACI[$operace];
        }
        return self::HLASKA_NEZNAMA_OPERACE; // nebo lépe vyhodit Exception -> throw new \RuntimeException("Byla zadaná neznámá operace: {$operace}");
    }

    /**
     * @throws RuntimeException
     */
    private function osetriVstupniCislo($cisloVstup)
    {
        //tady může být x ruzných kontrol, třeba i pomocí regulárního výrazu atd.
        if (is_float($cisloVstup)) {
            return (float)$cisloVstup;
        }
        throw new RuntimeException("Zadaná hodnota: {$cisloVstup}, není číslo.");
    }

    private function existujeOperaceVPrekladoveMape($operace)
    {
        return array_key_exists($operace, self::PREKLADOVA_MAPA_OPERACI);
    }

    private function secti($prvniCislo, $druheCislo)
    {
        return $prvniCislo + $druheCislo;
    }

    private function odecti($prvniCislo, $druheCislo)
    {
        return $prvniCislo - $druheCislo;
    }

    private function nasob($prvniCislo, $druheCislo)
    {
        return $prvniCislo * $druheCislo;
    }

    /**
     * @throws RuntimeException
     */
    private function vydel($prvniCislo, $druheCislo)
    {
        if ($druheCislo === 0) {
            throw new \RuntimeException('Nulou nelze dělit ty joudo!');
        }
        return $prvniCislo / $druheCislo;
    }

}

A adekvátně upravíme i index.php, kde využijeme konstanty s operacemi.

<?php
mb_internal_encoding("UTF-8");
require_once('tridy/Kalkulacka.php');
?>
<!DOCTYPE html>
<html lang="cs-cz">

<head>
    <meta charset="utf-8"/>
    <meta name="description" content=""/> <!-- Popis stránky -->
    <meta name="keywords" content=""/> <!-- Klíčová slova -->
    <meta name="author" content=""/> <!-- Autor webu -->
    <link rel="shortcut icon" href="obrazky/ikona.ico"/>
    <link rel="stylesheet" href="styl.css" type="text/css"/>
    <title>Kalkulačka</title>
</head>

<body>
<h1 style="text-align: center">PHP objektově orientovaná kalkulačka</h1>

<form method="POST">
    <table border="1">
        <tr>
            <td>První číslo:</td>
            <td><input name="prvniCislo" type="text"/></td>
        </tr>
        <tr>
            <td>Druhé číslo:</td>
            <td><input name="druheCislo" type="text"/></td>
        </tr>
        <tr>
            <td>Operace:</td>
            <td>
                <select name="operace">
                    <option value="<?= Kalkulacka::OPERACE_SCITANI ?>">Sčítání</option>
                    <option value="<?= Kalkulacka::OPERACE_ODCITANI ?>">Odčítání</option>
                    <option value="<?= Kalkulacka::OPERACE_NASOBENI ?>">Násobení</option>
                    <option value="<?= Kalkulacka::OPERACE_DELENI ?>">Dělení</option>
                </select>
            </td>
        </tr>
    </table>
    <input type="submit" value="Zjistit výsledek"/>
</form>
<?php
if (isset($_POST['prvniCislo'], $_POST['druheCislo'], $_POST['operace'])) {
    $kalkulacka = new Kalkulacka();
    $operaceText = $kalkulacka->prevedOperaciNaText($_POST['operace']);
    $operaceVyslednyText = "Zvolil jsi operaci: <strong>{$operaceText}</strong>.";
    try {
        $vysledek = $kalkulacka->vypocitej($_POST['prvniCislo'], $_POST['druheCislo'], $_POST['operace']);
        $vysledekText = "Výsledek této operace je: <strong>{$vysledek}</strong>";
    } catch (RuntimeException $e) {
        $vysledekText = "Při výpočtu došlo k chybě: {$e->getMessage()}";
    }
    echo $operaceVyslednyText;
    echo '<br>';
    echo $vysledekText;
}
?>
</body>
</html>
Editováno 8.1.2023 19:46
 
Nahoru Odpovědět
8.1.2023 19:44
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 4 zpráv z 4.