Zbytek po celočíselném dělení – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Zbytek po celočíselném dělení – C / C++ – Fórum – Programujte.comZbytek po celočíselném dělení – C / C++ – Fórum – Programujte.com

 

Vlákno bylo úspěšně vloženo.
Pokud sám přijdeš na řešení, nezapomeň ho sem přidat!
Adam
~ Anonymní uživatel
176 příspěvků
2. 1. 2012   #1
-
0
-

Dobrý den,

Učím se programovat podle knihy Karninghana a Ritchieho. Podle knihy jsem napsal kód (viz. níže). Program je vlastně jednoduchá kalkulačka podle obrácené polské notace (př.: 1 - 2 se musí zapisovat jako 1 2 -). K tomuto programu mám za úkol doplnit operátor zbytku dělení (%) a postarat se ještě o záporná čísla.

#include <stdio.h>
#include <stdlib.h> //pro atof()
#include <ctype.h> //pro isdigit()

#define MAXOP 100   //maximalni velikost operatoru nebo operandu
#define CISLO '0'   //signal oznamujici nalezeni cisla
#define MAXHODNOTA 100  //maximalni hloubka zasobniku
#define VELVPAMETI 100  //velikost vyrovnavaci pameti ve funkci vratz

int rp = 0;        //dalsi volna pozice na zasobniku
double zasobnik[MAXHODNOTA];      //zasobnik hodnot
char vpamet[VELVPAMETI];        //vyrovnavaci pamet pro vratz
int vpametp = 0;

int nactioperator(char []);
void vloz(double);
double vyjmi(void);
int nactiz(void);
void vratz(int);

/*Kazdy operand se umisti do zasobniku, jakmile se objevi operator
  ze zasobniku vyjmeme spravny pocet operandu (dva), na ne aplikujeme
  operator a vysledek se vrati zpet do zasobniku*/
main()
{
      int typ;
      double op2;
      char s[MAXOP], r[] = "";
     
      printf("\t****************************************\n");
      printf("\t* Tento program je jednoducha kalkulac-*\n");
      printf("\t* ka, podle obracene polske notace.    *\n");
      printf("\t* (1-2)*(4+5) zapisujte 1 2 - 4 5 + *  *\n");
      printf("\t* Program vytvoril Adam Lasak podle    *\n");
      printf("\t* algoritmu Kernighana a Ritchieho.    *\n");
      printf("\t* ver [1.0]                            *\n");
      printf("\t****************************************\n");
     
      scanf("%s", &r);
      while ((typ = nactioperator(r)) != EOF){
            switch(typ){
                case CISLO:
                     vloz(atof(r));
                     break;
                case '+':
                     vloz(vyjmi() + vyjmi());
                     break;
                case '*':
                     vloz(vyjmi() * vyjmi());
                     break;
                case '-':
                     /*zadani napr.: 1 2 - znamena, ze hodnota 2 se ulozi
                       pozdeji nez hodnota 1. => op2 = vyjmi() znamena
                       ze se od promenne rp odecte 1, a pri dalsim volani
                       vyjmi() bude jako prvni hodnota 1 (pri vypoctu)*/
                     op2 = vyjmi();
                     vloz(vyjmi() - op2);
                     break;
                case '/':
                     //uplne to stejne, akorat je zde podminka kvuli deleni 0
                     op2 = vyjmi();
                     if (op2 != 0.0)
                        vloz(vyjmi() / op2);
                     else
                         printf("Chyba: deleno nulou\n");
                     break;
                case '\n':
                     printf("\t%.8g\n", vyjmi());
                     break;
                case '%':
                     //ZDE JE CELOCISELNE DELENI
                     vloz(vyjmi() % vyjmi());
                     break;
                default:
                        printf("Chyba: neznamy prikaz %s\n", s);
                        break;
                        }
      }
      return 0;
}

//vloz: vlozi hodnoty do zasobniku
void vloz(double f)
{
     if (rp < MAXHODNOTA)
        zasobnik[rp++] = f;
     else
         printf("Chyba: plny zasobnik, nelze vlozit %g\n", f);
}

//vyjmi: vyjme hodnotu z vrcholu zasobniku
double vyjmi(void)
{
       if (rp > 0)
          return zasobnik[--rp];
       else {
            printf("Chyba: prazdny zasobnik\n");
            return 0.0;
            }
}

//nactioperator: ziska nasledujici operator nebo ciselny operand
int nactioperator(char r[])
{
    int i, z;
   
    while ((r[0] = z = nactiz()) == ' ' || z == '\t')
          ;
    r[1] = '\0';
    if (!isdigit(z) && z != '.')
       return z;    //neni cislem
    i = 0;
    if (isdigit(z)) //ziskej celociselnou cast
       while (isdigit(r[++i] = z = nactiz()))
             ;
    if (z == '.')   //ziskej zlomkovou cast
       while (isdigit(r[++i] = z = nactiz()))
             ;
    r[i] = '\0';
    if (z != EOF)
       vratz(z);
    return CISLO;
}

/*vratz vlozi vracene znaky do sdilene vyrovnavaci pameti - pole znaku. nactiz
  vyjme znak z vyrovnavaci pameti, neni-li prazdna, jestli je, zavolame getchar()*/
 
//nactiz: vrati nasledujici znak na vstupu
int nactiz(void)
{
    return (vpametp > 0) ? vpamet[--vpametp] : getchar();
}

//vratz: vrati znak zpet na vstup
void vratz(int z)
{
     if (vpametp >= VELVPAMETI)
        printf("Chyba: prilis mnoho znaku\n");
     else
         vpamet[vpametp++] = z;

}

HÁZÍ MI TO TUHLE CHYBU: 71 D:\Knihovny\Dokumenty\IT\C_C++\09_Externi_promenne\expromenne.cpp invalid operands of types `double' and `double' to binary `operator%'

takže jsem se pokoušel vracené hodnoty z funkce vyjmi() převést na celá čísla pomocí funkce atoi() z knihovny stdlib.h. Ale tohle bylo taky neúspěšné. Vubec nevim co s tim. 

Nahlásit jako SPAM
IP: 46.174.59.–
ondra.holub+1
Stálý člen
2. 1. 2012   #2
-
0
-

Použij header math.h a něj funkci fmod.

Nahlásit jako SPAM
IP: 194.138.12.–
Adam
~ Anonymní uživatel
176 příspěvků
2. 1. 2012   #3
-
0
-

#2 ondra.holub
Mám k tomu ale použít operátor %

Nahlásit jako SPAM
IP: 46.174.59.–
_tomas
~ Anonymní uživatel
22 příspěvků
2. 1. 2012   #4
-
0
-

double vyjmi(void);

vracia double

kolko je 10.2 % 5.8?

modulo operator pracuje len s celymi cislami - int

Nahlásit jako SPAM
IP: 46.150.223.–
Adam
~ Anonymní uživatel
176 příspěvků
2. 1. 2012   #5
-
0
-

#4 _tomas
Právě proto jestli to jde převádět pomocí atoi

int a, b;

a = atoi(vyjmi());

b = atoi(vloz());

a pak by bylo tohle

a % b

jenže tenhle způsob mi nejde

Nahlásit jako SPAM
IP: 46.174.59.–
vitamin+8
Grafoman
2. 1. 2012   #6
-
0
-

atoi konvertuje cislo reprezentovane ako c retazec na integer.

tebe staci pouzit toto:


double a = vloz(),
       b = vloz();
((int)a) % ((int)b)
Nahlásit jako SPAM
IP: 178.143.60.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
ondra.holub+1
Stálý člen
2. 1. 2012   #7
-
0
-

vy#5 Adam

Zatím víme, že

  • vyjmi vraci double
  • atoi bere jako argument const char*
  • atoi(vyjmi()) tedy nejde, protože double nejde automaticky konvertovat na const char*

Takže pokud je v požadavcích použití operátoru % a čísla máme v typu double, tak nezbývá, než převést double na int. Můžeš to udělat třeba takto:

int zbytek(double a, double b)
{
   return (int)a % (int)b; 
}

Samozřejmě je třeba počítat s tím, že do proměnné typu double se vejdou taková čísla, která se do intu nevejdou, takže v takovém případě to asi bude házet lehce zmatené výsledky.

Nahlásit jako SPAM
IP: 194.138.12.–
Adam
~ Anonymní uživatel
176 příspěvků
2. 1. 2012   #8
-
0
-

#7 ondra.holub
Jo to je ono, to sem potřeboval vědět. 

Díky moc

Nahlásit jako SPAM
IP: 46.174.59.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 17 hostů

Podobná vlákna

Zbytek po dělení — založil Foret

[C++] Delení % — založil Re4DeR

Dělení s ocáskem — založil Dan

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý