• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Ograniczenia na daty i rok przestępny: problem

Object Storage Arubacloud
0 głosów
595 wizyt
pytanie zadane 8 października 2018 w C i C++ przez Vitall Początkujący (400 p.)
edycja 8 października 2018 przez Vitall

Cześć wszystkim!

Od wczoraj walczę z zadaniem. Na pewno rozwiązanie jest mega proste, ale jednak póki co nie udało mi się tego rozgryźć.

Treść zadania jest następująca:

"Napisać program wczytujący z klawiatury dwie daty (zapisane za pomocą trzech liczb całkowitych, oznaczającychj dzień, miesiąc i rok) i sprawdzający, czy te daty są prawidłowe (uwzględniając przy tym przestępność lat) oraz czy pierwsza data jest wcześniejsza od drugiej."

Więc może słowem wstępu - zadanie poprzedzające to zadanie, które polegało na sprawdzeniu, czy rok jest przestępny, czy też nie. Zamieszczę swoje rozwiązanie (nie wiem czy jest ok, bo nie mam odpowiedzi, w necie nie znalazłem żadnego, które wyglądałoby jak moje, ale wydaje mi się, że działa poprawnie). Treść tego zadanie dokładnie jest taka:

"Napisać program sprawdzający, czy podany przez użytkownika rok jest rokiem przestępnym. Rok przestępny (liczbowo) spełnia następujące warunki: jest podzielny przez 4 i niepodzielny przez 100, chyba, że jest podzielny przez 400. "

Moje rozwiązanie: 

#include<iostream>
#include<cmath>
using namespace std;

int main()
{
	int rok;
	cout << "Sprawdzamy przestepnosc liczbowa roku.\nPodaj rok: "; 
	cin >> rok;
	
	if (rok %4 == 0)
		if(rok %100 != 0)
			cout << "Rok przestepny - podzielny przez 4 i niepodzielny przez 100";
		else if (rok %400 == 0)
			cout << "Rok przestepny, bo podzielny przez 400";
		else 
			cout << "Rok nie jest przestepny, bo niepodzielny przez 400";
	else
		cout << "Rok nieprzestepny, bo niepodzielny przez 4";
	
	return 0;
}

Odnośnie problemu, to o ile napisałem program, który pobiera od użytkownika trzy liczby dwukrotnie i umie powiedzieć, kiedy która z nich jest <,=,> od drugiej, o tyle mam poważny problem z ograniczeniem na daty. U mnie może być 31.02.0012 r., także absolutnie bez sensu.. Myślałem o instrukcji switch() i w case'ach rozróżniać miesiące, ale na moje (uczące się dopiero) oko powtarzałbym pewniem kod w case'ach wielokrotnie, a chyba tego w programowaniu się unika - powtarzanie tego, czego nie trzeba.

Czy ktoś z Was ma jakiś pomysł? Będę wdzięczny za każdą wskazówkę, sugerację, cokolwiek. 

Mój kod:

#include<iostream>
using namespace std;

int main()
{
	int d1, d2, m1, m2, r1, r2;
	cout << "Podaj dwie daty w kolejnosci dzien, miesiac, rok.\ndata1: ";
	cin >> d1 >> m1 >> r1;
	cout <<"data 2: ";
	cin >> d2 >> m2 >> r2;
		
	if ( r1>0 & r2>0 & m1>=1 & m1 <=12 & m2>=1 &m2<=12 & d1>=1 & d1<=31 & d2>=1 & d2<=31)	
		if (r1 < r2)
			cout << "data 1 jest wczesniejsza od daty 2";
		else if (r1 == r2)
			if(m1 < m2)
				cout << "data 1 jest wczesniejsza od daty 2";
			else if (m1 == m2)
				if(d1 < d2)
					cout << "data 1 jest wczesniejsza od daty 2";
				else if (d1 == d2)
					cout << "daty sa rowne";
				else
					cout << "data 2 wczesniejsza od daty 1";
			else
				cout << "data 2 wczesniejsza od daty 1";	
		else
			cout << "data 2 wczsniejsza od daty 1";
	else
		cout << "Dzien, miesiac, rok nie mieszcza w racjonalnym przedziale - sa bez sensu";
	
	return 0;
}

 

komentarz 8 października 2018 przez Tomek Sochacki Ekspert (227,510 p.)
Nie znam C++ więc nie będę się wypowiadal o kodzie itp. ale taka moja pierwsza myśl to czy nie chodziło w zadaniu o umiejętność wykorzystania gotowych libek do obsługi dat? Generalnie to w takich przypadkach bezpieczniej jest często korzystać w gotowych rozwiązań języka niż tworzyć wszystko na nowo, pisać do wszystkiego nowe unit testy itp.
komentarz 8 października 2018 przez Vitall Początkujący (400 p.)
edycja 8 października 2018 przez Vitall
Zadanie jest umieszczone w temacie dotyczącym instrukcji warunkowych: if, if-else if, if-else, switch, pętli - while i do..while i korzystania z bibliotek cmath i iomanip. Mi się wydaje, że prościej (do czego dopiero dojdę) daty robić jako stringi, ale zadanie ma być wykonane przy pomocy tych narzędzi, które wymieniłem, a o stringach słyszałem, jeszcze nie dotykałem ;)

Myślę, że właśnie chodzi o pisanie "od nowa", żeby kminić ten proces. Jak już to znasz, wiesz, rozumiesz, to wtedy z gotowców.

Ja po prostu nie wiem jak narzucić programowi, żeby można było miesiące wpisywać 1-12 i jak mamy np miesiąc 2, to wtedy liczba dni jest max 28, chyba, ze rok przestepny, to 29. Nie wiem też jak narzucic na rok, zeby nie zaczynal sie od zer, tj, zeby nie bylo 0000, 0001, 0011, 0111 lub tego typu i zeby rok mial 4 - cyfry (choc nie wiem, czy o taki rygor chodzi).

1 odpowiedź

+1 głos
odpowiedź 9 października 2018 przez niezalogowany
  1. Sprawdzanie lat przestępnych jest dobre, ale można krócej.
  2. Jeżeli nie chcesz używać switch dobrym rozwiązaniem do zapisywania ile dni ma miesiąc jest tablica.
  3. Do sprawdzania poprawnego roku możesz użyć instrukcji warunkowej - if(year > 1900) ...
  4. Na łańcuchach nie będzie łatwiej. Łatwiej będzie z wykorzystaniem funkcji. Pomogłoby Ci to łatwiej tworzyć kod i wygodnie się po nim poruszać.
  5. Zamiast & używaj &&.
komentarz 11 października 2018 przez Vitall Początkujący (400 p.)
edycja 11 października 2018 przez Vitall
Dzięki, jeszcze nie doszedłem do tablic, więc jak już tam będę, to wrócę do tego zadania.

Wydaje mi się, że nie trzeba tu znać tablic, żeby to zrobić, bo inaczej dlaczego to zadanie pojawiałoby się w dziale bez tablic. Póki co nie wiem jak to zrobić :(

Dlaczego && zamiast &?
Jeśli rozumiem, to jest to operator koniunkcji matematycznej, czyli, jeśli 1 - prawda, 0 - fałsz, to koniunkcja jest prawdziwa, wtw, gdy jednocześnie a oraz b są prawdziwe. Jak co najmniej jedna z nich jest fałszywa, to koniunkcja też taka jest.

Znalazłem w necie, że a = 1 & b = 1, to komputer sprawdza najpierw lewą stronę, czy jest prawdą, a potem prawą i dopiero podejmuje decyzję, czy koniunkcja jest prawdziwa.

A jak jest a = 1 && b = 1, to sprawdza tylko lewą stronę i jak jest prawdą, to niesprawdzajac prawej uznaje, że całość jest prawdą.

A co jeśli, po prawej mielibyśmy fałsz? Wtedy będzie zły wynik...

* znalazłem, że & jest koniunkcją bitową, mógłby ktoś łopatologicznie wyjaśnić różnice między & i &&, jaki jest ich sposób działania?

Będę wdzięczny, bo czytam, czytam, ale... narazie nie wiem :(
komentarz 11 października 2018 przez niezalogowany

Operatory logiczne - &&, ||, ! działają na zmiennych typu bool. Przykład:

1 && 1 = 1 // koniunkcja (logiczna)
1 && 0 = 0
0 && 1 = 0
0 && 0 = 0

Operatory bitowe - &, |, >>, <<, ^ działają na liczbach (ich bitowych reprezentacjach):

01000101 & 0000100 = 0000100 // tu też koniunkcja (ale bitowa)
01000101 | 0000010 = 01000111 // a tu alternatywa 

W swoim komentarzu mylisz chyba działanie koniunkcji z alternatywą. W zasadzie nie powinno się używać operatorów bitowych na zmiennych bool. Raz, że nikt tak nie robi, bo to nielogiczne (jak widzę w kodzie operator bitowy to raczej spodziewam się jakiejś optymalizacji, obliczeń na liczbach, a nie jakiegoś dziwnego warunku). Dwa wynikiem takiego działania będzie liczba (a nie bool) co w dalszych operacjach może, ale nie musi prowadzić do jakichś problemów.

Jakiś inny prostszy przykład nierozważnego użycia operatorów bez wiedzy jak działają:

 if (5 == 5 == 1)
 {
        std::cout << "5 == 5 == 1    lul :D" << "\n";
 }

Warunek 5 == 5 == 1 jest prawdziwy, bo 5 == 5 to true i wartość ta zostanie dopasowana to kolejnego działania czyli porównania dwóch liczb. Wartość logiczna bool zostanie zamieniona na 1, więc kolejnym działaniem będzie 1 == 1 co jest prawdą.

komentarz 12 października 2018 przez Vitall Początkujący (400 p.)
Dzięki za wyjaśnienie, ale koniunkcji z alternatywą akurat nie mylę ;)
Opetatory logiczne mają działać na zmiennych o typie bool i tego się trzymać, a operatory bitowe na reprezentacjach liczb w kompie, w zaistniałej potrzebie :)

Podobne pytania

0 głosów
0 odpowiedzi 257 wizyt
pytanie zadane 7 sierpnia 2021 w C i C++ przez Wiktor51207 Początkujący (380 p.)
0 głosów
2 odpowiedzi 750 wizyt
pytanie zadane 14 października 2018 w C i C++ przez Vitall Początkujący (400 p.)
0 głosów
1 odpowiedź 425 wizyt

92,555 zapytań

141,403 odpowiedzi

319,557 komentarzy

61,940 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...