ďťż

Ładny brzuch

Właśnie rozpoczynam przygodę z C++ ;)

if (zmienna==char) { //costam; } else { //costam; }

Poprawcie kod powyżej - chodzi mi o to, jak sprawdzić, czy jakaś zmienna przechowuje dany typ danych, np. char lub int. Konkretnie chodzi mi o to, aby uniknąć błędu, gdy użytkownik poda zmiennej wartość o typie, który jest niezgodny z typem danych, który przechowuje zmienna.

Mam nadzieję, że wyraziłem się jasno :)
Z góry THX.
Użytkownik Krzema edytował ten post 23 kwiecień 2005, 16:35


Interpretacja danych wejściowwych zależy od programisty. W type znakowym char dobrze się trzyma "małe" liczby. A najprostszym sposobem sprawdzenia typu danych jest, wczytanie ich jako napisu i porównanie do własciwosci typu. Np.:
same cyfry oznaczają, że chodzi o liczbę,
cyfry, kropka, 'e', +/- ,że typ zmiennoprzecinkowy
itp.

To, co opisujesz jest niemożliwe w całej postaci - w C++ zmienne przechowują tylko to, co mają przechować. Jak napiszesz:
char zmienna;
to masz gwarancję, że zmienna będzie zawsze typu char. Właśnie taka jest podstawowa dewiza C++, że kompilator pilnuje typów.

Inna sprawa, że char to typ numeryczny o rozmiarze jednego bajtu. Wartość w nim przechowywaną można interpretować jako kod ASCII jakiegoś znaku, i tak jest domyślnie traktowana. Dlatego jeśli chcesz sprawdzić, czy wczytany znak jest cyfrą, to musisz sprawdzić, czy wartość tego znaku odpowiada któremuś z kodów ASCII cyfr. Na nasze szczęście tak się akurat złożyło, że znaki cyfr w kodzie ASCII są po kolei, tj. ułożone 0, 1, 2, 3, ... ,9 , gdzie 0 ma kod 48, a 9 ma kod 57. Dlatego możesz napisać sobie np. taką funkcję

inline bool IsDigit(char c)
{
return ( c > 48 && c < 57);
}

Ostatnią instrukcję możemy też zapisać:
return ( c > '0' && c < '9');

Teraz piszesz w swoim kodzie:
if(IsDigit(zmienna))
{
//dzialania, jesli zmienna przechowuje cyfre
}
else
{
//dzialania, jesli zmienna przechowuje inny znak
}

Niemniej może się pojawić sytuacja, w której nie znasz konkretnego typu przechowywanego pod zmienną, ale tyczy się to tylko wskaźników na jakąś klasę podstawową. Do tego są operatory dynamic_cast i typeid :).

Zejdę trochę z tematu - nie pisałem nic od baardzo dawna, więc pozdrawiam wszystkich ludzi z 'mojego pokolenia' - tj. tych wszystkich, którzy bywali na tym forum od początku jego istnienia :D

TeMPOraL:
(nie cytuję, bo bez sensu tyle tekstu jeszcze raz ;))
O coś w tym rodzaju mi chodzi, ale konkretnie to ma sprawdzać, czy to jest liczba, a nie cyfra, a z tego, co sobie wyobrażam, sprawdzenie, czy to jest liczba, może być znacznie trudniejsze, albo łatwiejsze, bo może istnieje już taka gotowa funkcja.

Być może odpowiedź jest blisko, ale, jak wspominałem, rozpoczynam w C++'sie.




... to ma sprawdzać, czy to jest liczba, a nie cyfra, ...

To może przedstawię to na bardziej konkretnym przykładzie:
#include <iostream.h>
int main() {    float l1, l2, wynik;    char dzialanie;        cout << "Podaj pierwsza liczbe:" << endl;    cin >> l1;    cout << "Podaj druga liczbe:" << endl;    cin >> l2;    cout << "Teraz powiedz mi co chcesz zrobic z tymi dwiema liczbami. Wpisz +, -, * lub /." << endl;    cin >> dzialanie;    if (dzialanie == '+')    {        wynik = l1 + l2;    }    else if (dzialanie == '-')    {        wynik = l1 - l2;    }    else if (dzialanie == '*')    {        wynik = l1 * l2;    }    else if (dzialanie == '/')    {        wynik = l1 / l2;    }    cout << l1 << " " << dzialanie << " " << l2 << " = " << wynik << endl;     }

To jest kod jednego z moich pierwszych programów w C++. Np. gdy zamiast liczby użytkownik wpisze literę, ma pojawić się komunikat, że ma wpisać liczbę.
Wiem, że w pewnym sensie [b]char[/c] przechowuje liczby, bo przecież kod ANSI (lub ASCII - mylą mi się te nazwy), ale chodzi mi o to , aby jakoś to rozróżniał...

int main() {   float l1, l2, wynik;   char dzialanie;     cout << "Podaj pierwsza liczbe:" << endl;   cin >> l1;   cout << "Podaj druga liczbe:" << endl;   cin >> l2;   cout << "Teraz powiedz mi co chcesz zrobic z tymi dwiema liczbami. Wpisz +, -, * lub /." << endl;   cin >> dzialanie;   if((dzialanie =='+')&&(dzialanie=='-')&&(dzilanie=='*') &&(dzialanie=='/')) {   switch (dzialanie) {   case '+' :       wynik = l1 + l2;   case '-':          wynik = l1 - l2;    case'*':       wynik = l1 * l2;  case'/'       wynik = l1 / l2;   }   }   else  cout<<"Musisz podać znak +,-,*,/;   cout << l1 << " " << dzialanie << " " << l2 << " = " << wynik << endl;     }

przepraszam że to jest brzydko napisane i mówię że tu mogą być jakieś błędy ale głównie chyba chodzi o to.
najlepiej było by to napisać w funkcji.

Jeżeli dobrze rozumiem, to Tobie chodzi o to, żeby sprawdzić czy ktoś podał Ci tekst, podczas gdy miał podać którąś z liczb.

Otóż kod:
int zmienna;
cin >> zmienna;

wczytuje z klawiatury liczbę i umieszcza ją w zmiennej zmienna. Zastanówmy się, co się stanie gdy użytkownik poda tekst zamiast liczby. Strumień otrzymując tekst, którego nie jest w stanie zamienić w liczbę, przechodzi w stan błędu. Jednak niezależnie od tego, co sobie strumień myśli na temat użytkownika, musi on coś umieścić w zmiennej zmienna. Dlatego umieszcza w niej z grubsza przypadkowe dane. Strumień będący w stanie błędu będzie odpowiadał losowymi danymi na każdą próbę wczytania, dlatego jak raz wpiszesz wyraz zamiast liczby, to program się już nigdy Ciebie nie spyta o podanie czegoś z klawiatury.

Oczywiście stan błędu jest po to, żeby coś zasygnalizować i go naprawić. Sprawdzić, czy wczytywanie strumieniem się nie udało możemy z pomocą funkcji fail(). Najlepiej pokażę kod przykładowego wczytywania liczby:

while(1)
{
cin >> zmienna;
if(cin.fail())
{
cout << "Miales podac liczbe! Podaj jeszcze raz!\n";
cin.clear(cin.rdstate() & ~ios::failbit);
}
else
{
break;
}
}

Taka pętla będzie się wykonywała tyle razy, ile potrzeba żeby użytkownik podał poprawną daną liczbową. Ciekawa może być instrukcja cin.clear(cin.rdstate() & ~ios::failbit) - otóż wywołujemy tu funkcję clear(), która ustawia flagi błędów. Jako argument przekazujemy jakie flagi ma ustawić. Funkcja rdstate() odczytuje aktualny stan flag, a wyrażenie & ~ios::failbit zeruje tzw. bit failbit, czyli flagę odpowiadającą za stan błędu fail. Wykorzystujemy tu rdstate(), ponieważ strumień mógł sobie ustawić jeszcze jakąś inną flagę, a nie chcemy mu mieszać w niczym poza failbit. W rezultacie strumień wychodzi ze stanu błędu, i może kontynuować normalną pracę.

Mam nadzieję, że chodziło o to ;)
Pozdrawiam,
TeMPOraL.
Użytkownik TeMPOraL edytował ten post 25 kwiecień 2005, 15:56
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •