C++ - detekce zda do proměnné ukládám číslo zda písmeno – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

C++ - detekce zda do proměnné ukládám číslo zda písmeno – C / C++ – Fórum – Programujte.comC++ - detekce zda do proměnné ukládám číslo zda písmeno – C / C++ – Fórum – Programujte.com

 

ls20150
Duch
10. 8. 2015   #1
-
0
-

Ahoj, začínám, a přestože jsem vygooglil několik různých řešení, neuspělo u mě ani jedno.

Mám program, kde je menu ovládáno pomocí čísel ( 8) Konec, a podobně), a chci tam dodat detekci 

situace, kdy mi program oznámí zadání "ne-čísla" - zatím mi jen vypíše chybu, když napíšu číslo, které v menu už není. "else if( isalpha(volba) )  " je místo detekce nečísla, zkoušel sem tam ale i jiné možnosti.

Děkuji za nápady.

#include <iostream>
#include <cmath>
#include <ctype.h>
using namespace std;
int main()
{
  int volba, cislo1, cislo2 ; // deklarovani funkce volba a operandů příkladů
  float deleni ; // deleni se zbytkem umoznuje pouze nekolik druhu pameti, viz Floating point anebo Pohyblivá řádová čárka
  double polomer, povrch ; // podobný typ jako float
  do //do-while loop starts here.that display menu again and again until user select to exit program
  { 
     //Vlastni nabidka:
     cout << "Vitejte v ukazkovem programu matematickych operaci." << endl;
     cout << "Upozorneni: pri psani desetinnych cisel dodrzujte" << endl;
     cout << "anglosasky standart, tudiz 2.5 (nikoliv 2,5)!" << endl;
     cout << "(Vyhotoven: 9.8.2015)" << endl;
     cout << "1) Soucet +" << endl;
     cout << "2) Soucin *" << endl;
     cout << "3) Rozdil -" << endl;
     cout << "4) Podil / " << endl;
     cout << "5) Modulo % " << endl;
     cout << "6) Povrch kruhu " << endl;   // obvod kruhu - Circumference
     cout << "7) rez" << endl;
     cout << "8) KONEC" << endl;

     cout << "Prosim, zadejte volbu: ";
     cin >> volba;
     
     if(volba == 1) 
     {
    cout << "Zvoleno scitani:" << endl;
    cout << "Zadejte prvni cislo: " << endl;
    cin >> cislo1;
    cout << "Zadejte druhe cislo: " << endl;
    cin >> cislo2;
    cislo1 += cislo2;
    cout << "Vas vysledek: " << endl;
    cout << cislo1 << endl;
     }
     else if(volba == 2) 
     {
    cout << "Zvoleno nasobeni:" << endl;
    cout << "Zadejte prvni cislo: " << endl;
    cin >> cislo1;
    cout << "Zadejte druhe cislo: " << endl;
    cin >> cislo2;
    cislo1 *= cislo2;
    cout << "Vas vysledek: " << endl;
    cout << cislo1 << endl;
     }
     else if(volba == 3) 
     {
    cout << "Zvoleno odcitani:" << endl;
    cout << "Zadejte prvni cislo: " << endl;
    cin >> cislo1;
    cout << "Zadejte druhe cislo: " << endl;
    cin >> cislo2;
    cislo1 -= cislo2;
    cout << "Vas vysledek: " << endl;
    cout << cislo1 << endl;
     }
    else if(volba == 4) 
     {
    cout << "Zvoleno deleni:" << endl;
    //cout << "POZOR: pri deleni typu 10/4 je nutny zapis ve formatu 10.0/4" << endl;   V manuálu to ale tak bylo napsáno, čím to je?
    //cout << "anebo 10/4.0, program jinak nezobrazi udaje za desetinou carkou." << endl;
    cout << "Zadejte prvni cislo: " << endl;
    cin >> deleni;
    cout << "Zadejte druhe cislo: " << endl;
    cin >> cislo1;
    deleni /= cislo1;
    cout << "Vas vysledek: " << endl;
    cout << deleni << endl;
  }
    else if(volba == 5) 
     {
    cout << "Zvoleno MODULO (navratka zbytku po deleni):" << endl;
    cout << "Zadejte prvni cislo: " << endl;
    cin >> cislo1;
    cout << "Zadejte druhe cislo: " << endl;
    cin >> cislo2;
    cislo1 %= cislo2;
    cout << "Vas vysledek: " << endl;
    cout << cislo1 << endl;
  }
    else if(volba == 6) 
     {
       cout << "Zvolen vypocet povrchu kruhu:" << endl; // P = π × r², umocnění se dělá pomocí funkce
        cout << "Zadejte polomer kruhu: " << endl; // pow, definované  v souboru cmath - pow(2,  3)
        cin >> polomer;                             // umocní dvě na třetí
        povrch = 3.14 * pow(polomer,  2);          // http://kruh.wikina.cz/ ;
        cout << "Vas vysledek: " << endl;
        cout << povrch << endl;
  }
    else if(volba == 7) 
     {
       
        cout << "test rez" << endl;
  }
     else if(volba == 8) 
     {
       cout << "Ukonceni programu..." << endl;
     }
      else if( isalpha(volba) )  
     {
       
        cout << "Toto neni cislo!" << endl;
     }
  else //doplnit hlídání CÍSELNÝCH výrazů
     {
       // Displaying error message
       cout << "Zadan neplatny udaj." << endl;
     }
  }
  while(volba != 8);  
   
   return 0;
}

Nahlásit jako SPAM
IP: 85.13.75.–
ls20150
Duch
10. 8. 2015   #2
-
0
-

a ani nic z tohoto nepomohlo:

http://stackoverflow.com/questions/19521320/why-do-i-get-an-infinite-loop-if-i-enter-a-letter-rather-than-a-number

Nahlásit jako SPAM
IP: 85.13.75.–
Ovrscout
~ Anonymní uživatel
113 příspěvků
10. 8. 2015   #3
-
0
-

#2 ls2015
Mno nejsem uplne odbornik na tuto (c++, konzole) ale podle meho odhadu program selze uz v casti cin >> volba kde se pokusi prevest znak/znaky z klavesnice na cislo. a protoze se to nepovede tak ani neulozi novou hodnotu do "volba".

zkusil bych něco na způsob http://stackoverflow.com/…ecking-error

 

if (cin >> volba)
{
 cout <<"dobra volba"<<endl
}else
{
 cout <<"Spatna volba"<<endl
 cin.ignore();
 cin.clear();
 volba=-1;
}

Případně zkusin načíst z cin nikoliv číslo ale znak/znaky, (místo int použít char? jen hádám), a pak porovnávat ne na číslo ale na znak tj n2co jako : if(volba == '7') 

Taky jukni sem http://stackoverflow.com/…from-cin-get
 , aby ti nezůstávali v cin frontě znaky odřádkování.

Nahlásit jako SPAM
IP: 193.165.79.–
Ovrscout
~ Anonymní uživatel
113 příspěvků
11. 8. 2015   #4
-
0
-

#3 Ovrscout
hmm, tak hlavně má být nejdříve clear a pak ignore.
A pak podle https://www.daniweb.com/…input-stream to není nic snadného. Asi bude nejlepší načíst z cin řetězec a ten pak převést na číslo.

Tohle mi funguje dobře ale je to takové všelijaké, snad někdo poradí lépe.  

string trimspaces(string& str)
{
	if (str.length() <= 0)return str;
	size_t first = str.find_first_not_of(' ');
	size_t last = str.find_last_not_of(' ');
	return str.substr(first, (last - first + 1));
}
int GetIntValueFromCIN(int &val)
{
	string line;
	getline(cin, line);
	line=trimspaces(line)	
	if (sscanf_s(line.c_str(), "%i", &val) != 1)
	{
		val=0;//pri chybe vratime hodnotu nula, ale je lepsi si kontrolovat navratovouhodnotu
		return -1;
	}
	return 0;
}

//v main potom volat takto
if (GetIntValueFromCIN(volba) != 0)volba = -1;

//a nahradit i další volání cin >> cislox
GetIntValueFromCIN(cislo1);//pripadne doplnit kontrolu navratove hodnoty pro pripad ze nekdo zada neco jineho nez cislo
Nahlásit jako SPAM
IP: 188.120.223.–
kikot
~ Anonymní uživatel
14 příspěvků
11. 8. 2015   #5
-
0
-

assert.
isdigit

Zasláno z mobilního telefonu.

Nahlásit jako SPAM
IP: 82.145.208.–
ls2015
~ Anonymní uživatel
5 příspěvků
11. 8. 2015   #6
-
0
-

#5 kikot
Co tím chtěl básník říci?

Nahlásit jako SPAM
IP: 85.13.75.–
KIIV
~ Moderátor
+43
God of flame
11. 8. 2015   #7
-
+1
-
Zajímavé
Kit +

#6 ls2015
assert je neco jako bys na kole zjistil, ze si spatne zahnul, tak spachas ritualni sebevrazdu skokem ze skaly

isdigit by se hodil, kdybys nacital po znacich a prevadel na cislo

Nahlásit jako SPAM
IP: 93.91.152.–
Program vždy dělá to co naprogramujete, ne to co chcete...
KIIV
~ Moderátor
+43
God of flame
11. 8. 2015   #8
-
0
-

Jinak neni zase takovy problem osetrit ty vstupy... Pro ukazku (neimplementoval jsem vse, jen soucet a modulo a je to bez menu):

// kompilace a spusteni:   g++ --std=c++11 test.cpp && ./a.out
#include <map>
#include <iostream>
#include <functional>

bool akce_soucet(bool&);
bool akce_soucin(bool&);
bool akce_rozdil(bool&);
bool akce_podil(bool&);
bool akce_modulo(bool&);
bool akce_obvod_kruhu(bool&);
bool akce_ukoncit(bool&konec);

int main() {
  std::map<int, std::function<bool(bool&)>> functions {
    {1,std::bind(&akce_soucet, std::placeholders::_1)},
    {2,std::bind(&akce_soucin, std::placeholders::_1)},
    {3,std::bind(&akce_rozdil, std::placeholders::_1)},
    {4,std::bind(&akce_podil,  std::placeholders::_1)},
    {5,std::bind(&akce_modulo, std::placeholders::_1)},
    {6,std::bind(&akce_obvod_kruhu, std::placeholders::_1)},
    {8,std::bind(&akce_ukoncit,std::placeholders::_1)}
    };

  bool konec = false;
  do {
    if (std::cin.fail()) {
      if (std::cin.eof()) {
        konec = true;
      } else {
        std::cin.clear();
        std::cin.ignore(1);
      }
    }
    int volba;
    if (std::cin >> volba) {
      auto it = functions.find(volba);
      if (it == functions.end()) {
        std::cout << "Neplatna volba\n";
        continue;
      }
      if (! it->second(konec)) {
        std::cout << "Nacitani z nejakeho duvodu selhalo (nejspise eof)\n";
      } 
    }
  } while (!konec);
}


template <typename T>
std::istream& readInput(std::istream& in, T& value) {
  while (!(in >> value) && !in.eof()) {
    std::cout << "Invalid value\n";
    in.clear();
    in.ignore(1); // ignore one character
  }
  return in;
}


bool akce_soucet(bool&) {
  std::cout << "Vybran Soucet\n";
  double a,b;
  if (!readInput(std::cin,a) || !readInput(std::cin,b)) {
    return false;
  }
  std::cout << a << "+" << b << "=" << (a+b) << "\n";
  return true;
}

bool akce_soucin(bool&) {
  std::cout << "Vybran Soucin\n";
  return true;
}

bool akce_rozdil(bool&) {
  std::cout << "Vybran Rozdil\n";
  return true;
}

bool akce_podil(bool&) {
  std::cout << "Vybran Podil\n";
  return true;
}

bool akce_modulo(bool&) {
  std::cout << "Vybrano Modulo\n";
  int a,b;
  if (!readInput(std::cin,a) || !readInput(std::cin,b)) {
    return false;
  }
  std::cout << a << "%" << b << "=" << (a%b) << "\n";
  return true;
}

bool akce_obvod_kruhu(bool&) {
  std::cout << "Vybran Obvod kruhu\n";
  return true;
}

bool akce_ukoncit(bool&konec) {
  konec=true;
  return true;
}

Nebo jeste misto zahozeni jednoho znaku pouzivam std::string x; cin >> x; na zahozeni celeho slova. Kdyz by ses snazil, najdes asi i jine moznosti

Nahlásit jako SPAM
IP: 93.91.152.–
Program vždy dělá to co naprogramujete, ne to co chcete...
KIIV
~ Moderátor
+43
God of flame
11. 8. 2015   #9
-
0
-

Nebo alternativa s funkcnim objektem (pro udrzeni nazvu nabidky)

#include <map>
#include <iostream>
#include <functional>
#include <string>

class akce {
  public:
    typedef std::function<bool(bool&)>    callback_t;

    akce(const char* popis, callback_t funkce): m_popis{popis}, m_funkce{funkce} {;}
    bool operator()(bool& konec) const { return m_funkce(konec); }
    std::string const& menu_popis() const { return m_popis; }

  private:
    std::string   m_popis;
    callback_t   m_funkce;
};

bool akce_soucet(bool&);
bool akce_soucin(bool&);
bool akce_rozdil(bool&);
bool akce_podil(bool&);
bool akce_modulo(bool&);
bool akce_obvod_kruhu(bool&);
bool akce_ukoncit(bool&konec);


int main() {
  std::map<int, akce> functions {
    {1, akce{"Soucet",      std::bind(&akce_soucet,      std::placeholders::_1)}},
    {2, akce{"Soucin",      std::bind(&akce_soucin,      std::placeholders::_1)}},
    {3, akce{"Rozdil",      std::bind(&akce_rozdil,      std::placeholders::_1)}},
    {4, akce{"Podil",       std::bind(&akce_podil,       std::placeholders::_1)}},
    {5, akce{"Zbytek",      std::bind(&akce_modulo,      std::placeholders::_1)}},
    {6, akce{"Obvod Kruhu", std::bind(&akce_obvod_kruhu, std::placeholders::_1)}},
    {8, akce{"Konec",       std::bind(&akce_ukoncit,     std::placeholders::_1)}}
    };

  bool konec = false;
  do {
    std::cout << "Menu: \n";
    for (auto & key_val_pair : functions) {
      std::cout << key_val_pair.first << ") " << key_val_pair.second.menu_popis() << "\n";
    }
    std::cout << "Volba: ";

    if (std::cin.fail()) {
      if (std::cin.eof()) {
        konec = true;
      } else {
        std::cin.clear();
        std::cin.ignore(1);
      }
    }
    int volba;
    if (std::cin >> volba) {
      auto it = functions.find(volba);
      if (it == functions.end()) {
        std::cout << "Neplatna volba\n";
      } else {
        if (! it->second(konec)) {
          std::cout << "Nacitani z nejakeho duvodu selhalo (nejspise eof)\n";
        }
      } 
    }
  } while (!konec);
}


template <typename T>
std::istream& readInput(std::istream& in, T& value) {
  while (!(in >> value) && !in.eof()) {
    std::cout << "Invalid value\n";
    in.clear();
    in.ignore(1); // ignore one character
  }
  return in;
}


bool akce_soucet(bool&) {
  std::cout << "Vybran Soucet\n";
  double a,b;
  if (!readInput(std::cin,a) || !readInput(std::cin,b)) {
    return false;
  }
  std::cout << a << "+" << b << "=" << (a+b) << "\n";
  return true;
}

bool akce_soucin(bool&) {
  std::cout << "Vybran Soucin\n";
  return true;
}

bool akce_rozdil(bool&) {
  std::cout << "Vybran Rozdil\n";
  return true;
}

bool akce_podil(bool&) {
  std::cout << "Vybran Podil\n";
  return true;
}

bool akce_modulo(bool&) {
  std::cout << "Vybrano Modulo\n";
  int a,b;
  if (!readInput(std::cin,a) || !readInput(std::cin,b)) {
    return false;
  }
  std::cout << a << "%" << b << "=" << (a%b) << "\n";
  return true;
}

bool akce_obvod_kruhu(bool&) {
  std::cout << "Vybran Obvod kruhu\n";
  return true;
}

bool akce_ukoncit(bool&konec) {
  konec=true;
  return true;
}
Nahlásit jako SPAM
IP: 93.91.152.–
Program vždy dělá to co naprogramujete, ne to co chcete...
ls2015
~ Anonymní uživatel
5 příspěvků
17. 8. 2015   #10
-
0
-

Ahoj, nakonec sem se pokusil to celé překopat na jednotlivě volané funkce, ale zase to hlásí nějaký chyby:

[code]#include <iostream>
#include <cmath>
#include <ctype.h>
using namespace std;
int main()
{
  char input;
  int volba, cislo1, cislo2 ; // deklarovani funkce volba a operandů příkladů
  float deleni ; // deleni se zbytkem umoznuje pouze nekolik druhu pameti, viz Floating point anebo Pohyblivá řádová čárka
  double polomer, povrch ; // podobný typ jako float
  do //do-while loop starts here.that display menu again and again until user select to exit program
  { 
     //Vlastni nabidka:
     cout << "Vitejte v ukazkovem programu matematickych operaci." << endl;
     cout << "Upozorneni: pri psani desetinnych cisel dodrzujte" << endl;
     cout << "anglosasky standart, tudiz 2.5 (nikoliv 2,5)!" << endl;
     cout << "(Vyhotoven: 9.8.2015)" << endl;
     cout << "1) Soucet +" << endl;
     cout << "2) Soucin *" << endl;
     cout << "3) Rozdil -" << endl;
     cout << "4) Podil / " << endl;
     cout << "5) Modulo % " << endl;
     cout << "6) Povrch kruhu " << endl;   // obvod kruhu - Circumference
     cout << "7) rez" << endl;
     cout << "8) KONEC" << endl;

     cout << "Prosim, zadejte volbu: ";
     cin >> input;
     if (!isdigit(input))
     cout << "Toto není číslice!" << endl;
     cout << "Prosim, zadejte ZNOVU volbu: " << endl;
     else 
     cin >> volba;   
    }
   
   return 0;
}
    
     void menu()
{ if(volba == 1) 
     {
    cout << "Zvoleno scitani:" << endl;
    cout << "Zadejte prvni cislo: " << endl;
    cin >> cislo1;
    cout << "Zadejte druhe cislo: " << endl;
    cin >> cislo2;
    cislo1 += cislo2;
    cout << "Vas vysledek: " << endl;
    cout << cislo1 << endl;
     }
     else if(volba == 8) 
     {
       cout << "Ukonceni programu..." << endl;
     }
  else //doplnit hlídání CÍSELNÝCH výrazů
     {
       // Displaying error message
       cout << "Zadan neplatny udaj." << endl;
     }
  }
  while(volba != 8);  
      while (volba < 0)
    {
        cin >> input;
       volba = static_cast<int>(volba) - 48;
    }
   
   return 0;
}[/code]

CHAR.cpp:32:3: error: 'else' without a previous 'if'    ---pročpak, když ho tam mám?
CHAR.cpp:36:11: error: expected 'while' before numeric constant
CHAR.cpp:36:11: error: expected '(' before numeric constant

Nahlásit jako SPAM
IP: 85.13.75.–
17. 8. 2015   #11
-
0
-

   

 if (!isdigit(input))
     cout << "Toto není číslice!" << endl;
     cout << "Prosim, zadejte ZNOVU volbu: " << endl;
     else //TOTO JE TEN PŘEBYTEČNÝ else
     cin >> volba;   

Že by ty dva cout patřily do bloku kódu?

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:520:b71...–
ls2015
~ Anonymní uživatel
5 příspěvků
17. 8. 2015   #12
-
0
-

if (!isdigit(input)) cout << "Toto není číslice!" << endl; cout << "Prosim, zadejte ZNOVU volbu: " << endl; else //TOTO JE TEN PŘEBYTEČNÝ else cin >> volba;

TOTO JE TEN PŘEBYTEČNÝ else

Není: myslel sem to takto: pokud nezadám číslo, vypíše mi to oznámení a žádost o znovu zadání, pokud číslo zadám, dojde k dalšímu kroku, a to je převod znaku do proměné "volba".

Nahlásit jako SPAM
IP: 85.13.75.–
17. 8. 2015   #13
-
0
-

je, protože se to chová takto: 

if (!isdigit(input))
     cout << "Toto není číslice!" << endl;
//zde končí podmínka
cout << "Prosim, zadejte ZNOVU volbu: " << endl;
else  //je "bezprizozorní"

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:520:b71...–
17. 8. 2015   #14
-
0
-

"Idiots Guide": 

if (výraz)  {
  příkaz1;
  příkaz2;
}
else  {
  příkaz3;
  příkaz4;
}

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:520:b71...–
Kit+15
Guru
17. 8. 2015   #15
-
0
-

#1 ls2015
U původního příkladu jsem změnil typ proměnné "volba" na "char" a šlape to jak hodinky.

Samozřejmě jsem změnil i její testování: 

if (volba == '1') { ...

Ještě jedna rada: Pro druhou mocninu nikdy nepoužívej funkci pow(), protože je pomalá. Prostě napiš výraz x*x.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:f973:...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
17. 8. 2015   #16
-
0
-

#15 Kit
až budou čísla volby dvouciferný, tak narazíš....

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:520:b71...–
Kit+15
Guru
17. 8. 2015   #17
-
0
-

#16 hlucheucho
Nenarazím. Přečtu první znak ... switch ... druhý znak ... switch ... operand ...

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:f973:...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
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, 99 hostů

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ý