Skocz do zawartości
Gość

Rozpoznanie czy znak jest liczbą

Rekomendowane odpowiedzi

Gość

Cześć. Znacie jakąś funkcję czy sposób, żeby sprawdzać, czy wprowadzona zmienna jest liczbą czy innym znakiem.

Piszę program do funkcji kwadratowych i chcę dać warunek w pętli, że dopóki wprowadzona zmienna long double nie jest liczbą to program będzie prosił do skutku o podanie wartości dla zmiennej.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

W tym pytaniu mieszasz "systemy walutowe". Albo wczytujesz zmienną jako ciąg znaków i sam analizujesz czy jest to liczba, wtedy każdy znak musi być z przedziału od '0' do '9', albo używasz funkcji do wczytania liczby i sprawdzasz, czy pojawił się błąd.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
wtedy każdy znak musi być z przedziału od '0' do '9'

Z przodu może być jeszcze '-' ;)

Edytowane przez Bono[UG]

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość

Język C++, zabawa w konsoli :D .

O co chodzi z tą notacją, poprostu notacja wykładnicza :) ?

Edytowane przez Gość

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Rozpoznawanie poprawnej liczby jest dość upierdliwe, a wyrażenia regularne na to dość skomplikowane (przynajmniej na liczby rozpoznawane przez współczesne kompilatory). Bo np. poprawne są zapisy -1. albo .5 ale -. już nie*. A to nawet nie dotknęło notacji wykładniczej.

 

najprościej to wczytać do napisu, przpuścić przez wbudowaną funkcję konwertująca (w c++ można chyba użyć sscanf) i sprawdzić czy zwróciła błąd. Jak tak to w pętli pytamy ponownie.

 

 

*) W Javie, C++ czy C# nie można napisać -., ale np. commodore basic traktował . jako 0 (jakaś logika w tym jest) i była to nawet sztuczka optymalizacyjna, bo . parsowała się szybciej niż 0 napisane wprost, tzn X=. działało szybciej niż X=0.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość

Dzięki za pomoc bardzo :thumbup::D:thumbup: . W takim razie spróbuję pobrane liczby z long double przerobić na string i potem sprawdzić każdy znak napisu, czy jest cyfrą i jeśli tak to znowu przekonwertować to na long double. Wydaje się sensowne, tylko poszukam funkcji do przekonwertowania. :thumbup:;):thumbup:

Edytowane przez Gość

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeśli masz wczytaną wartość jako long double, znaczy się, że użyłeś funkcji do wczytywania takowej (np scnaf, albo operatora z obiektu cin). To jeśli wystąpił błąd podczas wczytywania, możesz dowiedzieć się w inny sposób niż ponowne zamienianie wczytanej wartości do stringa... Chyba nim zaczniesz dalszą zabawę powinieneś jednak wrócić do podstaw języka. C++ nie jest prostym językiem, dlatego niewielu osobom bm polecił jako pierwszy język, ale jak juz się zdecydowałeś, to niestety trzeba porządnie zrozumieć podstawy inaczej dalej nie pójdziesz!

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

najprościej to wczytać do napisu, przpuścić przez wbudowaną funkcję konwertująca (w c++ można chyba użyć sscanf) i sprawdzić czy zwróciła błąd. Jak tak to w pętli pytamy ponownie.

Jak już jest propozycja sscanf, to nie prościej od razu wczytać scanf-em?

 

Oprócz tego są jeszcze atoi, atof, stod, stof, stol... Tylko trzeba dokładnie poczytać co funkcja zwraca w przypadku błędnej konwersji, może to być 0, a może rzucić wyjątkiem.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
' date='26 Lipiec 2019 - 09:13' timestamp='1564125186' post='15577094']

Jak już jest propozycja sscanf, to nie prościej od razu wczytać scanf-em?

Przyznam, że c i c++ pamiętam tylko ze studiow, ale czy aby nie jest tak, że scanf wczyta po cichu tyle ile dopasuje mu się do liczby i np. z "12dupa34" wczyta tylko 12? Jeżeli da się sprawdzić, czy w buforze nie pozostały jeszcze jakieś śmieci to w sumie sam scanf będzie oczywiście prostszy. Albo jakiś jego odpowiednik na strumieniach. Oczywiście przykład 12dupa34 jest dość głupi, ale podobnie będzie jak ktoś pomyłkowo użyje przecinka zamiast kropki itp.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Szczerze powiedziawszy nie wiem. scanfa używam dla siebie, więc bzdur staram się nie wpisywać. Trzeba by poczytać i popróbować jak się zachowuje.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
' date='26 Lipiec 2019 - 09:13' timestamp='1564125186' post='15577094']

Oprócz tego są jeszcze atoi, atof, stod, stof, stol... Tylko trzeba dokładnie poczytać co funkcja zwraca w przypadku błędnej konwersji, może to być 0, a może rzucić wyjątkiem.

Zwrócenie 0 gdy można rzucić wyjątek nie ma logicznego sensu, bo jest to jak najbardziej poprawna wartość do zwrócenia przez funkcję. Uniemożliwia to odróżnienie błędu konwersji od poprawnej konwersji której rezultatem jest 0.

 

To czyni ato* niezdatnymi do szerszego użytku. Albo dostajemy zero nie wiedząc co ono tak naprawdę oznacza, albo coś niezdefiniowanego.

 

sto* albo poprawnie konwertują, albo rzucają wyjątek.

 

 

Wybór narzędzia zależy od języka w jakim piszemy.

Jeżeli piszemy w c albo "c with cout" to owszem, scanf'y bądź strto*.

Jeżeli c++ który miałby trzymać się ogólnie przyjętych norm - stof i rodzinka z obsługą błędów po wyjątkach.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Rzucanie wyjątku przy każdej okazji, bo coś się nie zgadza jest bez sensem, 1) takie coś kosztuje, 2) to, że sprawdzamy, czy coś jest liczbą, a coś nie jest, nie znaczy, że jest to błąd, tylko np to, że nie jest to czego spodziewaliśmy się w pierwszym podejściu.

 

Jeśli ogólnie przyjętą normą jest rzucanie wyjątku przy byle problemie, to ja dziękuję za "takie normy".

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ale te funkcje to przecież nie ja Ci napisałem, tylko są w standardowej bibliotece c++.

Czy gdyby takie podejście miało być złe to naprawdę trafiłoby do standardu?

 

Ale tak na zdrowy rozum. Najbardziej wygodne i czytelne użycie uzyskuje się wtedy, gdy rezultat jest zwracany przez funkcję. Przykładowo:

int liczba = stoi( napis );
foo( liczba );

 

Co nam daje wyjątek tutaj?

Po pierwsze, nie musimy niczego sprawdzać w miejscu, gdzie używamy funkcji. Przy poprawnej konwersji idziemy dalej. Przy błędnej... zmienna liczba nigdy nie jest tworzona, ani nie jest wykonywany dalszy kod na niej bazujący. To duży plus, bo wyjątku nie da się zignorować, a więc i nigdy nie zostanie wykonany kod, który miałby przetwarzać błędną wartość.

 

Normami tutaj nazywam Core Guidelines. To nie są żadne zasady z księżyca, a coś, do czego doświadczony programista drogą pracy z kodem i własnych/czyichś błędów albo dochodzi sam, albo przynajmniej doskonale rozumie co stoi u ich podstawie.

Poczytaj -> KLIK

Powinno też rozwiać przynajmniej część Twoich obaw o wydajność wyjątków.

Jeżeli chce się naprawdę wykorzystać mocne strony c++, to nie można pisać jak w c, tylko z inaczej nazwanymi funkcjami.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

To, że czasami są przydatne, dlatego się pojawiły, ale nie znaczy, że są lekiem na całe zło. nie zawsze brak liczby tam, gdzie ją sprawdzamy jest błędem, a dodatkowo nie zawsze należy wtedy przerwać dalsze wykonywanie danego kawałka kodu. To wszystko zależy.

 

P**rdolenie o tym, że jak nie korzystasz w danym wypadku z jakiegoś szczególnej możliwości języka C++, bo jest to po prostu niewygodne i niewskazane (tak jak niewskazane jest rzucanie wszędzie wyjątkami, bo jak napisałem, jest to kosztowne, dodatkowo może przyczynić się do pominięcia ważnego kawałka kodu, choćby zdejmującego jakąś blokadę, oczywiście można to obejść, ale znowu funkcje które popiszemy będą wygladać, jak te z C, tylko działać będą wolniej)

 

I żeby nie było, nie czepiłem się tego, że informujesz, że są funkcje rzucające wyjatki w przypadku niezgodności, a to że napisałeś, ze jedyna prawilne to korzystanie z funkcji rzucających wyjątki. Tak, takie podejście uważam za idiotyczne.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

dodatkowo może przyczynić się do pominięcia ważnego kawałka kodu, choćby zdejmującego jakąś blokadę

To by oznaczało, że ma miejsce w kodzie ręczne zarządzanie zasobami. Jak opinii i praktyk używanych w c++ jest wiele, tak prawie całkiem uniwersalną jest ta, że ręczne zarządzanie zasobami gdy mamy RAII (jako przykład - unique_ptr, lock_guard) jest złą praktyką, i nie wyobrażam sobie poważnego projektu ani w c++, ani nawet "c++", w którym by owe ręczne zarządzanie przeszło code review.

 

Nie piszę, że wyjątkami należy rzucać na lewo i prawo. Ale jeżeli robimy funkcję, która ma zwracać liczbę, a nie może tego zrobić, to jakie inne sposoby sygnalizowania błędu mamy, i jaki powinniśmy wybrać?

 

Przy podjęciu takiej decyzji należy brać kilka istotnych rzeczy jednocześnie pod uwagę:

-Czy błąd może zostać zignorowany? Przy wyjątku - nie da się. Kod oczekujący poprawnego rezultatu wykona się tylko wtedy, gdy funkcja faktycznie zwróci poprawną wartość. Przy flagach/globalach/return code'ach - nie mamy takiego zabezpieczenia.

-Jak czytelny jest kod używający takiej funkcji? Wyjątek pozwala jasno oddzielić logikę "happy path" od sytuacji błędnych i wyjątkowych. Używając metod c-style w kodzie cały czas właściwa logika przeplata się z obsługą błędów.

-Jak to wpłynie na wydajność? Na ten temat było tyle porównań i elaboratów, że szkoda strzępić klawiaturę. Należy sobie odpowiedzieć jak istotny z punktu widzenia wydajności dany fragment kodu jest w ogóle, czy w ogóle istotna dla nas jest kwestia wydajności gdy błąd nastąpi, na jaką platformę piszemy i jakimi narzędziami.

 

Biorąc te trzy rzeczy pod uwagę (poprawność, czytelność, wydajność), wyjątki są preferowanym kompromisem w większości przypadków. W wyspecjalizowanych przypadkach - korzysta się tego, co tam będzie optymalne.

 

Postawienie sprawy ogólnie "wyjątki nie, bo przede wszystkim są kosztowne" traktuje temat trochę powierzchownie. Po blogu wnioskuję, że piszesz głównie w c. I teraz nie wiem, czy używasz c++, ale tylko bardzo wąskiego podzbioru języka, co Ci rzutuje na ogólny pogląd, czy może po prostu Cię ten język nie interesuje.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się

  • Ostatnio przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

×
×
  • Dodaj nową pozycję...