Wielokrotne ify?

0

Cześć, jestem w trakcie pisania projektu z c++ na pierwszym roku studiów i napotkałem na taki problem.

Czy umieszczanie po sobie wielu bloków ifów jest poprawne? To znaczy: jest sobie kilka równorzędnych if, które mają sprawdzać różne warunki i które w przypadku zwrócenia 1 mają wykonać określone funkcje.

Przykład:

if	(a!=b && c!=d){											
cout << "Jakaś formułka." << endl;
		jakaś_funkcja();
}
	
if (T[x][y].wartosc==0){
	cout << "Jakaś inna formułka" << endl;
	jakaś_funkcja();
}

Czy w przypadku zwrócenia 0 w pierwszym ifie, drugi (i kolejne w przypadku zwrócenia 0) zostaną sprawdzone?

0

Dodatkowo: Co się stanie, gdy funkcja, która wykona się w ifie po kilku innych poleceniach z powrotem wróci do sprawdzenia tego samego warunku?
Jest to pętla 2 funkcji

Funkcja do wprowadzenia zmiennych(x) => Funkcja z ifami(y) => x => y itp. Czy może to w jakiś sposób wysypać program, gdyż zapisuje on fakt, że ma dalej do sprawdzenia warunki, czy może kompletnie 'usuwa' to z pamięci i przechodząc do drugiej funkcji ma czyste konto.

1
  1. Jest brzydkie ale poprawne
  2. Tak, kolejne warunki będą sprawdzane o ile ktoś nie przerwie tej funkcji
  3. Nie rozumiem pytania. Jeśli wewnatrz funkcji f wywołasz funkcje f to nazywamy to rekurencją i można wywalić program jeśli takich wywołań zrobisz za dużo, bo program musi pamiętać wszystko co było poprzednio, żeby móc do tego wrócić, kiedy aktualna funkcja się wykona.
0

Programując w C takie ify zwykle do sprawdzania błędów się używa, w C++ można wyjątki użyć.

Ale można usunąć ify, ale jak będą jakieś dodawania, operacje logiczne to low level będzie to samo co z ifami.

0

Opisany fragment działa na razie w ten sposób:

  1. Wpisanie żądanych pól (startowego i końcowego). [funkcja_1]
  2. Sprawdzenie (tymi ifami), czy jakiś warunek ruchu nie został naruszony. [funkcja_2]
  3. Jeżeli któryś if zwróci 1 to odsyła usera z powrotem do 1. punktu żeby poprawił dane. [powrót do funkcji_1]

Czy taka konstrukcja wysypie program? Jeśli tak, to w jaki sposób można by to przekształcić?

Może coś w stylu pętli while, która pobierze którąkolwiek jedynkę z warunku, tylko jak dokładnie mogło by to wyglądać?

0

@Taison: ale jak robisz to "odsyłanie"? Bo jeśli to jest po prostu pętla while to nie ma problemu. Ale jeśli wołasz kolejny raz funkcje rekurencyjnie to słabo.

0
void pola(){	
	char x, y;
	int a, b, c, d;
	cout << "Wprowadz pole poczatkowe (A-H enter, 1-8 enter):" << endl;
	cin >> x >> a;
	cout << "Wprowadz pole koncowe (A-H enter, 1-8 enter)" << endl;
	cin >> y >> c;

	
	abs(65-int(x))==b;  // Konwersja char na int o wartości odpowiadającej potrzebnemu indeksowi tablicy.
	abs(65-int(y))==d;
	
	a=abs(8-a);		   // Konwersja numeru rzędu na odpowiedni indeks tablicy.
	c=abs(8-c);
	
	poruszanie(a, b, c, d);
}

void poruszanie(int a, int b, int c, int d){


	if	(a!=c && b!=d){									//Sprawdza czy zostały zmienione jednoczesnie wartości indeksów pionowych i poziomych.
		cout << "Ruch po ukosie! Wybierz inne pole." << endl;
		pola();
	}
	
	if (T[a][b].wartosc==0){
		cout << "Pole z ktorego chcesz sie poruszyc jest puste! Wybierz inne pole." << endl;
		pola();
	}
	
	if (T[c][d].wartosc!=0){
		cout << "Pole na ktore chcesz sie poruszyc jest zajete! Wybierz inne pole." << endl;
		pola();	
	}
		
	if (b=d){
		T[a][b].wartosc -= abs(a-c);  		// Ruch poziomy
		T[c][d].wartosc += abs(a-c);
	}
	if (a=c){
		T[a][b].wartosc -= abs(b-d);		//Ruch pionowy
		T[c][d].wartosc += abs(b-d);
	}
	
	if(T[a][b].wartosc==0)		// Usunięcie koloru jeżeli wszystkie piony zostałe zabrane z pola startowego.
		T[a][b].kolor=0;
1

No nie, to się wywali, tak robic nie możesz. Zrób osobną funkcje isMoveValid() która zwraca 0 lub 1 w zależności od poprawności ruchu i wypisuje komunikat błędu i potem robisz:

do{
//wczytanie danych
while(!isMoveValid());

btw to: if (b=d) jest błąd, i to if (a=c) też, bo to nie jest porównanie tylko przypisanie nowej wartości! I tak samo to:

    abs(65-int(x))==b;  // Konwersja char na int o wartości odpowiadającej potrzebnemu indeksowi tablicy.
    abs(65-int(y))==d;

nie ma żadnego sensu bo robisz porównanie a potem nigdzie tego nie zapisujesz. Nie chciałęś tam robić b = cośtam?

0
Shalom napisał(a):

No nie, to się wywali, tak robic nie możesz. Zrób osobną funkcje isMoveValid() która zwraca 0 lub 1 w zależności od poprawności ruchu i wypisuje komunikat błędu i potem robisz:

do{
//wczytanie danych
while(!isMoveValid());

btw to: if (b=d) jest błąd, i to if (a=c) też, bo to nie jest porównanie tylko przypisanie nowej wartości! I tak samo to:

    abs(65-int(x))==b;  // Konwersja char na int o wartości odpowiadającej potrzebnemu indeksowi tablicy.
    abs(65-int(y))==d;

nie ma żadnego sensu bo robisz porównanie a potem nigdzie tego nie zapisujesz. Nie chciałęś tam robić b = cośtam?

No właśnie pętla do while, tylko co wpisać w środku odnośnie sprawdzenia warunku. Pętla wykona się raz bez sprawdzenia warunków, jak wziąć je pod uwagę w tym jednym przypadku? Na ten moment mam coś takiego:

void pola(){	
	
	char x, y;
	int a, b, c, d;
	do{
		cout << "Wprowadz pole poczatkowe (A-H enter, 1-8 enter):" << endl;
		cin >> x >> a;
		cout << "Wprowadz pole koncowe (A-H enter, 1-8 enter)" << endl;
		cin >> y >> c;
	
		
		abs(65-int(x))=b;  // Konwersja char na int o wartości odpowiadającej potrzebnemu indeksowi tablicy.
		abs(65-int(y))=d;
		
		a=abs(8-a);		   // Konwersja numeru rzędu na odpowiedni indeks tablicy.
		c=abs(8-c);
		
		poprawnosc();
	}
	while(!poprawnosc());
}

int poprawnosc(){
	if (warunki()==1)
		return 0;
	return 1;
	}

int warunki(int a, int b, int c, int d){

	if	(a!=c && b!=d){									//Sprawdza czy zostały zmienione jednoczesnie wartości indeksów pionowych i poziomych.
		cout << "Ruch po ukosie! Wybierz inne pole." << endl;
		return 1;
	}
	
	if (T[a][b].wartosc==0){
		cout << "Pole z ktorego chcesz sie poruszyc jest puste! Wybierz inne pole." << endl;
		return 1;
	}
	
	if (T[c][d].wartosc!=0){
		cout << "Pole na ktore chcesz sie poruszyc jest zajete! Wybierz inne pole." << endl;
		return 1;	
	}	
	return 0;
}
0

Jak rozumiem samo zapytanie o wartość funkcji w pewnym momencie jest jednocześnie jej wywołaniem?

1

W funkcji poprawnosc() wywołujesz funkcję warunki() bez argumentów, tymczasem funkcja ta wymaga 4.

Poza tym wywołanie funkcji poprawnosc() w pętli, tak jak tu:

do
{
	...
	poprawnosc(); <-- To
} while(!poprawnosc());

Nie wnosi nic do programu.

0

Kwestie zmiennych w funkcji (deklaracje i definicje) są dla mnie trochę niezrozumiałe. Co by się stało gdybym użył a, b, c, d jako zmiennych globalnych? Rozumiem, że wtedy potrzebowałbym przekazać je przez referencje do pozostałych funkcji (oprócz tej, która ustala ich wartości) i na samym początku tej funkcji powinienem wyzerować ich wartości.

Wiem, że nie jest to eleganckie rozwiązanie, ale jedyna wytyczna w tej kwestii to - żeby po prostu program działał.

1

Gdybyś użył ich jako zmiennych globalnych byłbyś od razu poinformowany że tak robić nie należy. I słusznie, Twój projekt nie wymaga takich zmiennych.

Zrób tak aby funkcja poprawnosc (użyj lepszej nazwy) przyjmowała 4 parametry i tak samo je przekazywała do funkcji warunki (tutaj też).

Przekazywanie zmiennych wygląda tak:

/* Jak naprawdę nazywa się zmienna którą ktoś przekaże nas nie obchodzi.
 * My zwracamy się do niej 'number'.
 * Warto zauważyć że number nie jest tym samym co zmienna która zostanie przekazana
 * tylko kopią.
*/
void change_number(int number) 
{
	number = 10; // Przypisujemy 
}

int main()
{
	int foo = 5;
	print_number(foo);
	printf("%d", foo);
}

Tak jak napisałem - jako że pracujemy na kopii zmiennej foo jakakolwiek zmiana w funkcji change_number nie zmieni foo. Po uruchomieniu programu kod wyświetli 5.

1 użytkowników online, w tym zalogowanych: 0, gości: 1