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

Wypisz liczby w kolejności malejącej nie używając tablic

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

Cześć,

mam zadanie następującej treści:

"Napisz program pobierający od użytkownika dwie liczby całkowite stanowiące krańce pewnego przedziału domkniętego, a następnie wypisujący ilość i sumę liczb podzielnych przez 3 należących do tego przedziału, a także wszystkie te liczby w kolejności malejącej."*

Chodzi o to by nie używać tablic ani innych struktur danych, które mogłyby je przechowywać.**

Wszystko super spoko, tylko to wypisanie liczb w kolejności malejącej..

Mój kod:


#include<iostream>	
#include<limits>

using namespace std;

int main()
{
	int a , b, liczba_prob = 0, ile_liczb = 0, suma = 0, max = numeric_limits<int>::min();
	bool czy_byly_liczby;

	do 
	{
		cout << "Podaj krance przedzialu domknietego. \nLewy - a, prawy - b.\na = ";
		cin >> a;
		cout << "b = ";
		cin >> b;
		if (a>b)
		{
			cout << "a  > b, wiec przedzial nie istnieje!" << endl;
			liczba_prob++;
			cout << "Pozostalo Ci: "<< 5-liczba_prob << " prob(a/y)."<< endl;
		}
		else if (a == b)
		{	
			cout << "a == b, wiec przedzial jest zdegenerowany!" << endl;
			liczba_prob ++;
			cout << "Pozostalo Ci: "<< 5-liczba_prob << "prob."<< endl;
		}
		else
			break;
		
	}
	while(liczba_prob != 5);
	
	if (liczba_prob >= 5)
		cout << "Liczba dopuszczalnych prob wynosila 5! Nie masz wiecej prob!!";
	
	for (int i = a; i <= b ; i++)
	{
		if (i % 3 == 0)
			{
				ile_liczb ++;
				suma = suma + i;
				czy_byly_liczby = true;
				if (i > max)	
					max = i;
			}
		else
			czy_byly_liczby = false;

	}
	
	if (czy_byly_liczby == true)
		cout << "nawjwieksza z liczb podzielnych przez 3 w tym przedziale, to: "
			 << max << endl;


		
			
	
	
	
	
	cout << "W przedziale a = " << a << ", b = " << b <<" jest " << ile_liczb 
	<< " liczb podzielnych przez 3. Ich suma wynosi: " << suma << "." << endl;
	
	
	

	
	
	
	return 0;
}

Proszę o podpowiedź/naprowadzenie.

Brakuje mi czegoś, co by "zapamiętywało" te wybrane liczby (podzielne przez 3), a nie mogę mieć zmiennej na każdą taką liczbę, bo raz nie wiem z góry ile takich liczb będzie, dwa, nawet jakbym wiedział, to bez sensu tworzyć miliony zmiennych na to samo.

 

* Ja sobie zmodyfikowałem treść, żeby użytkownik mógł max 5 razy wpisać [a;b] aż przedział będzie sensowy.

** Zadanie ma nacisk na to, że ma być bez tablic - to nie są moje "widzimisię" ;)

komentarz 14 października 2018 przez mokrowski Mędrzec (155,460 p.)
Nie lepiej pójść nieco inną drogą?

1. Wczytać krańce przedziału.

2. Wykryć czy nie zachodzi przypadek: a > b oraz a == b

3. Obliczyć: z a pierwszy indeks, z b drugi indeks ("wyrównane do liczby podzielnej przez 3")

4. Sprawdzić czy nie zachodzi przypadek: indeks_a >= indeks_b i jeśli zachodzi zgłosić brak liczb.

5. Wykonać obliczenia

???

1 odpowiedź

+1 głos
odpowiedź 13 października 2018 przez niezalogowany
wybrane 13 października 2018 przez Vitall
 
Najlepsza

Od razu wyszukaj najmniejszą i największą liczbę podzielną przez 3. Następnie iteruj pętlę po tych wartościach o 3 jednostki (unikniesz iterowania co jeden). Możesz też zostawić wszystko jak jest, a przy wypisywaniu od tych liczb użyć podobnej pętli tylko iterowanej w innym kierunku:

for (int i = b; i >= a ; --i)

PS. W obecnym kodzie masz duże uchybienie:

else
            czy_byly_liczby = false;

w przypadku gdy po podzielnej przez 3 liczbie będzie niepodzielna fladze zostanie przypisana zła wartość. Najlepiej usunąć te dwie linie i od razu zainicjować flagę na false.

PPS. Gdy użytkownik wykorzysta swoje próby możesz zakończyć program:

if (liczba_prob >= 5)
{
        cout << "Liczba dopuszczalnych prob wynosila 5! Nie masz wiecej prob!!";
        return 0;
}
komentarz 13 października 2018 przez Vitall Początkujący (400 p.)
edycja 13 października 2018 przez Vitall

@Hipcio - dzięki wielkie za podpowiedzi. 

Zastosowałem się do wszystkich poza pierwszą, której nie umiem zrobić. 
Chociaż to z ustawieniem zmiennej czy_byly_liczby na false, po usunięciu błędnej instrukcji (dzięki za wytknięcie) nie jest dla mnie do końca jasne, tzn. nie wiem co dokładnie masz na myśli. Wg mnie po usunięciu błędu, nie trzeba już nic dopisywać, bo program działa poprawnie (przynajmniej kilka razy testując nie wyskoczył mi żadnen błąd).

Prosiłbym o "rzucenie okiem", czy teraz program nie ma błędów. 

Od razu wyszukaj najmniejszą i największą liczbę podzielną przez 3. Następnie iteruj pętlę po tych wartościach o 3 jednostki (unikniesz iterowania co jeden)

Tego nie umiem, nie wiem jak to zrobić.
 

Mój kod, po poprawkach:

#include<iostream>	
#include<limits>

using namespace std;

int main()
{
	int a, b, liczba_prob = 0, ile_liczb = 0, suma = 0, max = numeric_limits<int>::min();
	bool czy_byly_liczby;

	do 
	{
		cout << "Podaj krance przedzialu domknietego. \nLewy - a, prawy - b.\na = ";
		cin >> a;
		cout << "b = ";
		cin >> b;
		if (a>b)
		{
			cout << "a  > b, wiec przedzial nie istnieje!" << endl;
			liczba_prob++;
			cout << "Pozostalo Ci: "<< 5-liczba_prob << " prob(a/y)."<< endl;
		}
		else if (a == b)
		{	
			cout << "a == b, wiec przedzial jest zdegenerowany!" << endl;
			liczba_prob ++;
			cout << "Pozostalo Ci: "<< 5-liczba_prob << "prob."<< endl;
		}
		else
			break;
		
	}
	while(liczba_prob != 5);
	
	if (liczba_prob >= 5)
	{
		cout << "Liczba dopuszczalnych prob wynosila 5! Nie masz wiecej prob!!";
		return 0; // jak użtykownik nie wykorzysta prób, to kończymy program
	}
		
	for (int i = a; i <= b ; i++)
	{
		if (i % 3 == 0)
			{
				ile_liczb ++;
				suma = suma + i;
				czy_byly_liczby = true;
				if (i > max)	
					max = i;
			}
					
	}
	
	if (czy_byly_liczby == true)
	{
		cout << "W przedziale [" << a << "," << b <<"] jest " << ile_liczb 
			 << " liczb podzielnych przez 3."
			 << endl <<  "Ich suma wynosi: " << suma << "." << endl;
			 
		cout << "Najwieksza z tych liczb:  "
			 << max << endl << "Liczby podzielne przez 3 z tego przedzialu w kolejnosci malejacej: "
			 << endl;
			 
		for (int i = b; i >= a; i--)
		{
			if (i % 3 == 0)
				cout << i << endl;
		}
			
	}
	else 
	cout << "W przedziale nie bylo liczb podzielnych przez 3.";
	
	return 0;
}

 

1
komentarz 13 października 2018 przez niezalogowany

W pierwszym kodzie dla danych wejściowych {2, 5} zmienna czy_byly_liczby ma wartość false - mimo, że 3 spełnia kryteria. Po prostu kolejne liczby 4 i 5 nie spełniają warunku i w else wartość true została zastąpiona false. To prowadziło do niewyświetlania max.

Teraz kod wygląda prawie dobrze. Brakuje jeszcze inicjowania zmiennej czy_byly_liczby na false. Inaczej może zostać zostać jej nadana przypadkowa wartość. Reszta tak na oko jest poprawna.

Ten pierwszy sposób o którym wspomniałem wymaga troszkę więcej linii kodu, ale za to będzie mniej porównań (tak ze 7 razy mniej). Z grubsza początek polegałby na znalezieniu dwoma pętla min i max, a reszta na nich operowaniu:

    if (czy_byly_liczby == true)
	{
		for (int i = min; i <= max; i += 3)
		{
			ile_liczb++;
			suma += i;
		}

		cout << "W przedziale [" << a << "," << b << "] jest " << ile_liczb
			<< " liczb podzielnych przez 3."
			<< endl << "Ich suma wynosi: " << suma << "." << endl;

		cout << "Najwieksza z tych liczb:  "
			<< max << endl << "Liczby podzielne przez 3 z tego przedzialu w kolejnosci malejacej: "
			<< endl;

		for (int i = max; i >= min; i -= 3)
		{
			cout << i << endl;
		}
	}

komentarz 13 października 2018 przez Vitall Początkujący (400 p.)

  @Hipcio,


Teraz kod wygląda prawie dobrze. Brakuje jeszcze inicjowania zmiennej czy_byly_liczby na false. Inaczej może zostać zostać jej nadana przypadkowa wartość. Reszta tak na oko jest poprawna.

Może ja naprawdę póki co jeszcze nie chwytam, ale u mnie jest tak:
 

		
	for (int i = a; i <= b ; i++)
	{
		if (i % 3 == 0)
			{
				ile_liczb ++;
				suma = suma + i;
				czy_byly_liczby = true;
				if (i > max)	
					max = i;
			}
					
	}
	

więc wg mnie, jeżeli będę miał przedział, np [1,2], to warunek w if-ie zawsze będzie "false", więc if się nie wykona, flaga będzie... a! przy definiowaniu zmiennej trzeba określić, że czy_byly_liczby = false? Zainicjować wartość, o to Ci chodzi?** ;) Chociaż ile razy wpisywałem, np. [1,2], czy [4,5] i tego typu, to zawsze działał poprawnie - czyżby poprawność losowa?

Dzięki za tę podpowiedź do drugiego rozwiązania  - muszę to jeszcze przetrawić.

** ok, przecież to napisałeś - późno jest, przepraszam

Wersja ostateczna (na dziś):
 


using namespace std;

int main()
{
	int a, b, liczba_prob = 0, ile_liczb = 0, suma = 0, max = numeric_limits<int>::min();
	bool czy_byly_liczb = false;

	do 
	{
		cout << "Podaj krance przedzialu domknietego. \nLewy - a, prawy - b.\na = ";
		cin >> a;
		cout << "b = ";
		cin >> b;
		if (a>b)
		{
			cout << "a  > b, wiec przedzial nie istnieje!" << endl;
			liczba_prob++;
			cout << "Pozostalo Ci: "<< 5-liczba_prob << " prob(a/y)."<< endl;
		}
		else if (a == b)
		{	
			cout << "a == b, wiec przedzial jest zdegenerowany!" << endl;
			liczba_prob ++;
			cout << "Pozostalo Ci: "<< 5-liczba_prob << "prob."<< endl;
		}
		else
			break;
		
	}
	while(liczba_prob != 5);
	
	if (liczba_prob >= 5)
	{
		cout << "Liczba dopuszczalnych prob wynosila 5! Nie masz wiecej prob!!";
		return 0; // jak użytkownik nie wykorzysta prób, to kończymy program
	}
		
	for (int i = a; i <= b ; i++)
	{
		if (i % 3 == 0)
			{
				ile_liczb ++;
				suma = suma + i;
				czy_byly_liczby = true;
				if (i > max)	
					max = i;
			}
					
	}
	
	if (czy_byly_liczby == true)
	{
		cout << "W przedziale [" << a << "," << b <<"] jest " << ile_liczb 
			 << " liczb podzielnych przez 3."
			 << endl <<  "Ich suma wynosi: " << suma << "." << endl;
			 
		cout << "Najwieksza z tych liczb:  "
			 << max << endl << "Liczby podzielne przez 3 z tego przedzialu w kolejnosci malejacej: "
			 << endl;
			 
		for (int i = b; i >= a; i--)
		{
			if (i % 3 == 0)
				cout << i << endl;
		}
			
	}
	else 
	cout << "W przedziale nie bylo liczb podzielnych przez 3.";
	
	return 0;
}

 

komentarz 13 października 2018 przez niezalogowany
@Vitall wszystko przyjdzie z czasem ;) Jeżeli zmienna nie będzie zainicjowana to będzie miała taką wartość jak komórka pamięci przed działaniem programu. Więc mogą (ale nie muszą) pojawić się jakieś śmieci. Czasami uruchamiając 100 razy ten sam program nie zauważysz tego, bo akurat zawsze zostanie przydzielona ta sama komórka. Może też okazać się, że kompilator zawsze inicjuje zmienne wartością domyślną, ale to nie jest reguła. Standard C++ wymaga takiego zachowania tylko dla zmiennych statycznych czy globalnych.

Podobne pytania

0 głosów
1 odpowiedź 1,954 wizyt
pytanie zadane 7 listopada 2017 w C i C++ przez rayman22 Użytkownik (710 p.)
0 głosów
1 odpowiedź 474 wizyt
pytanie zadane 19 stycznia 2016 w C i C++ przez TheFunny Gaduła (3,420 p.)
0 głosów
2 odpowiedzi 358 wizyt
pytanie zadane 7 stycznia 2017 w C i C++ przez pokrywa1 Użytkownik (990 p.)

92,568 zapytań

141,424 odpowiedzi

319,634 komentarzy

61,956 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!

...